Skip to main content

Examples & recipes

Copy-paste recipes for common tasks. Replace <your-api-origin> and the API key with your own. Set the key as an env var to avoid pasting it inline.

export POSTBUZZ_API_KEY="sx_live_YOUR_API_KEY"
export POSTBUZZ_ORIGIN="https://api.your-deployment.example.com"

List your connected accountsโ€‹

curl "$POSTBUZZ_ORIGIN/api/v1/accounts" \
-H "Authorization: Bearer $POSTBUZZ_API_KEY"

Grab an id from the response to use as accountId below.

Create and schedule a postโ€‹

curl -X POST "$POSTBUZZ_ORIGIN/api/v1/posts" \
-H "Authorization: Bearer $POSTBUZZ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"caption": "Starting a draft โ€” coming soon.",
"accountIds": ["acc_abc123"]
}'

No scheduledAt, so this saves as a draft. Add a time to schedule it:

curl -X POST "$POSTBUZZ_ORIGIN/api/v1/posts" \
-H "Authorization: Bearer $POSTBUZZ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"caption": "Shipping today ๐Ÿš€",
"accountIds": ["acc_abc123"],
"scheduledAt": "2026-07-15T14:30:00Z"
}'

Both return 201 with { "data": { "id": "...", "status": "draft" | "scheduled" } }.

Cross-post with per-channel overridesโ€‹

Same base caption everywhere, tailored on X and LinkedIn:

curl -X POST "$POSTBUZZ_ORIGIN/api/v1/posts" \
-H "Authorization: Bearer $POSTBUZZ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"caption": "Our new feature ships today ๐Ÿš€",
"accountIds": ["acc_instagram", "acc_x", "acc_linkedin"],
"accountOverrides": [
{ "accountId": "acc_x", "captionOverride": "Shipping today. ๐Ÿงต" },
{ "accountId": "acc_linkedin", "captionOverride": "Today we are launching..." }
],
"scheduledAt": "2026-07-15T14:30:00Z"
}'

Upload media, then post itโ€‹

First upload a file (or ingest by URL):

curl -X POST "$POSTBUZZ_ORIGIN/api/v1/media/upload" \
-H "Authorization: Bearer $POSTBUZZ_API_KEY" \
-F "file=@./teaser.mp4" \
-F "mediaType=video"

Note the id in data, then attach it:

curl -X POST "$POSTBUZZ_ORIGIN/api/v1/posts" \
-H "Authorization: Bearer $POSTBUZZ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"caption": "Behind the scenes",
"postType": "reel",
"accountIds": ["acc_instagram"],
"mediaIds": ["med_01"]
}'

List and filter postsโ€‹

# Scheduled posts whose caption mentions "launch"
curl "$POSTBUZZ_ORIGIN/api/v1/posts?status=scheduled&q=launch&limit=10" \
-H "Authorization: Bearer $POSTBUZZ_API_KEY"

Reschedule a postโ€‹

curl -X POST "$POSTBUZZ_ORIGIN/api/v1/posts/pst_abc123/reschedule" \
-H "Authorization: Bearer $POSTBUZZ_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "scheduledAt": "2026-07-16T09:00:00Z" }'

Delete a scheduled postโ€‹

curl -X DELETE "$POSTBUZZ_ORIGIN/api/v1/posts/pst_abc123" \
-H "Authorization: Bearer $POSTBUZZ_API_KEY"

Returns { "data": { "success": true } }; published posts return 400 Cannot delete published post.

Check quota and setupโ€‹

# Post quota + credits
curl "$POSTBUZZ_ORIGIN/api/v1/usage" \
-H "Authorization: Bearer $POSTBUZZ_API_KEY"

# Key/organization self-check
curl "$POSTBUZZ_ORIGIN/api/v1/diagnostics/setup" \
-H "Authorization: Bearer $POSTBUZZ_API_KEY"

Verify a webhook signatureโ€‹

Outbound webhook deliveries carry X-Webhook-Signature โ€” a hex HMAC-SHA256 of the raw body keyed with the webhook's signing secret:

import { createHmac, timingSafeEqual } from "node:crypto";

app.post("/webhooks/postbuzz", express.raw({ type: "*/*" }), (req, res) => {
const expected = createHmac("sha256", process.env.POSTBUZZ_WEBHOOK_SECRET)
.update(req.body) // raw bytes โ€” do NOT use a JSON-parsed body here
.digest("hex");

const given = req.headers["x-webhook-signature"];
const a = Buffer.from(expected);
const b = Buffer.from(given ?? "");
if (a.length !== b.length || !timingSafeEqual(a, b)) {
return res.status(401).send("bad signature");
}

const event = JSON.parse(req.body.toString());
switch (req.headers["x-webhook-event"]) {
case "post.published":
console.log("published", event.postId, event.publishedAt);
break;
case "post.failed":
console.error("failed", event.postId, event.errorMessage);
break;
}
res.sendStatus(200); // any 2xx acknowledges the delivery
});

JavaScript: a small API clientโ€‹

class PostbuzzClient {
constructor(origin, apiKey) {
this.origin = origin;
this.apiKey = apiKey;
}

async request(path, init = {}) {
const res = await fetch(`${this.origin}${path}`, {
...init,
headers: {
Authorization: `Bearer ${this.apiKey}`,
"Content-Type": "application/json",
...init.headers,
},
});
if (!res.ok) {
const body = await res.json().catch(() => ({}));
const err = body.error ?? res.statusText;
throw new Error(
`${res.status}: ${typeof err === "string" ? err : JSON.stringify(err)}`,
);
}
return res.status === 204 ? null : res.json();
}

listAccounts() {
return this.request("/api/v1/accounts");
}

listPosts({ limit = 25, offset = 0 } = {}) {
const q = new URLSearchParams({ limit, offset });
return this.request(`/api/v1/posts?${q}`);
}

createPost(post) {
return this.request("/api/v1/posts", {
method: "POST",
body: JSON.stringify(post),
});
}

deletePost(id) {
return this.request(`/api/v1/posts/${id}`, { method: "DELETE" });
}
}

// Usage
const client = new PostbuzzClient(
process.env.POSTBUZZ_ORIGIN,
process.env.POSTBUZZ_API_KEY,
);

const { data: accounts } = await client.listAccounts();
const { data } = await client.createPost({
caption: "Posted from my script",
accountIds: [accounts[0].id],
scheduledAt: new Date(Date.now() + 3_600_000).toISOString(), // +1h
});
console.log("Scheduled:", data.id, data.status);

Note the client unwraps both error shapes โ€” a plain string (legacy) and the structured { code, message } object. See Errors.

  • Posts API โ€” full field reference.
  • Errors โ€” how to interpret failures.
  • Limits โ€” avoid limit 400s.
  • Webhooks โ€” event catalog and delivery semantics.