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.