Social media posting API. Know what really happened to every post.
Create one post for the networks you pick, preview it, then schedule it or send it now. Each network then reports its own state: published with a link, still sending, or waiting for a person. Your code, your agents and the Postbroad app all use the same API.
curl -X POST "https://app.postbroad.com/v1/posts" \
-H "Authorization: Bearer $POSTBROAD_TOKEN" \
-H "Idempotency-Key: first-post-0001" \
-H "Content-Type: application/json" \
-d '{
"brandId": "<brandId>",
"baseText": "Spring menu is out. Six new drinks.",
"destinations": [
{ "channelId": "<bluesky channelId>" },
{ "channelId": "<mastodon channelId>" }
]
}'Each network has its own state.
A post isn't “sent” or “failed” as a whole. Every network moves on its own, so a partial failure is something you can see and act on.
published | Found on the network, with a link and the time. | Nothing. It's live. |
accepted | The network said yes. Not yet seen live. | Reads it back from the network. |
processing | The network is still working on media, such as a video. | Checks again until it's done. |
unknown | The network went quiet mid-send. It may or may not be there. | Searches the network before any retry, so nothing goes out twice. |
needs_reconnect | The account was signed out or lost a permission. | Holds the post and asks a person to reconnect. |
failed | The network said no, with a reason it won't change on a retry. | Stops and shows the reason with one action. |
How sure is “live”?
Networks don't all let you read a post back. Each one carries a verification level, so your code knows how much “published” means there.
fullRead back from the network and matched. Instagram, Facebook, Bluesky, YouTube, Farcaster, Lemmy, WordPress, Ghost, Hashnode, DEV.url_onlyAccepted by the network, with a link. Mastodon, X, LinkedIn, Telegram, Discord, Slack, LinkedIn pages, TikTok, Whop, Twitch, Kick, VK, Nostr, Listmonk, Threads, Google Business Profile, Dribbble. Mastodon and Google Business Profile are designed to be read back, but until that is verified they run as accepted, with a link.accepted_no_readbackAccepted by the network, can't be checked. Pinterest, Medium.manualA person confirms it. Reddit, MeWe. A person posts the draft by hand, or confirms a post the network can't show, and pastes the link back.Webhooks when anything changes.
Every state change is an event, such as delivery.published or delivery.unknown. Events are signed and use the Standard Webhooks format. If your endpoint is down, Postbroad tries up to 8 times over 3 days, counting the first.
{
"type": "delivery.published",
"timestamp": "2026-10-25T09:00:03.120Z",
"data": {
"event_key": "...",
"aggregate_type": "delivery",
"aggregate_id": "0b7e8f8e-5a4c-4d0e-9f53-0c8f2a6d1e01",
"revision": 4
}
}
# data also carries the fields of the changed row.
# Read the resource through the API for its full state.Authentication
In the app, open Settings, then Security, and create an API key. You see it once. Send it on every call as Authorization: Bearer <key>.
content.read, post.draft, post.schedule, post.publish_now, media.upload, analytics.read, webhook.manage.Limits
Each API key or session gets 600 requests a minute, counted in a fixed 60 second window. Reads and writes share it.
RateLimit-Limit: 600 RateLimit-Remaining: 597 RateLimit-Reset: 41 # Over the limit: 429, code "rate_limited", and Retry-After: 41 # Wait that long, then repeat. A write repeated with # the same Idempotency-Key is never sent twice.
- For bulk work, send up to 50 posts in one batch request instead of 50 calls.
- Postbroad paces each network to that network's own limits. A busy network waits and is tried again; it isn't marked failed.
- There is no cap on how many posts you publish.
Errors
Every error is application/problem+json (RFC 9457) with a stable code, a plain detail, a requestId and retryable. Branch on the code, not the text.
unauthenticated401No key, or a key that has ended or was revoked.forbidden403The key is valid but lacks the scope for this call.not_found404Nothing there for you. A resource of another organization, or outside the key's brands, is always 404.validation_failed422The body is wrong. The errors list names each field.rule_violation422A brand rule or preflight check failed. The errors list names each one.revision_mismatch409The post changed since you read it. Read it again, then retry.preview_stale409The preview no longer matches. The fresh one is in the answer.idempotency_key_reused422The same Idempotency-Key was sent with a different body.request_in_progress409A call with this Idempotency-Key is still running.rate_limited429Over the limit. Wait for Retry-After.unavailable503Try again shortly. retryable is true.For AI agents reading this page
Prefer MCP when your client supports it. Otherwise call the API with an API key from the organization settings. Report a post as live only when its state is published, and never repeat a post to be safe.
Developer questions.
Do agents use a different API?
No. The app, MCP and your own code all use the same API, with the same states.
Which networks can I post to?
The same ones as in the app, each with its own state and verification level. See every channel.
Is there a command line?
It is coming soon. Until then, scripts and cron jobs call the API with an API key.
How is the API priced?
Paid plans are coming soon. See pricing.