Errors and rate limits

What each status code means, the error body, and how to back off.

Error bodies

Every error returns an HTTP status and a JSON body with a readable error, plus issues when the request failed validation:

{
  "error": "You don't have permission to publish posts (post:publish).",
  "issues": []
}

Errors are written to be shown to a person or read by an agent: they say what was refused and why.

StatusMeaningWhat to do
400The request is invalid: a field is missing, or the post breaks a network's rule (too long, wrong media). issues says which.Fix the request. Don't retry it unchanged.
401No credential, a malformed one, or a revoked key or withdrawn sign-in.Check the Authorization header.
403The credential is valid but lacks a permission (named in the message), or the plan doesn't include the feature.Use a credential with that permission, or upgrade.
404It doesn't exist, or it belongs to another workspace.Check the id.
409A conflict: the post already moved on (it published, or someone decided its approval first).Read the current state, then decide.
429Rate limited.Wait for Retry-After seconds, then retry.
502A network or provider we called failed, or our access to it is broken.Retry later; if it persists, reconnect the channel.
500Something went wrong on our side.Retry later, and tell support if it persists.

Rate limits

Limits are counted per credential (each API key, or each signed-in person), never per workspace, so one busy integration can't lock your team out.

  • Endpoints that cost something, such as AI generation, link previews, GIF search, inbox replies and forced inbox syncs, each have their own budget.
  • The MCP server allows 240 tool calls a minute per credential.

A 429 carries a Retry-After header in seconds. A 429 is always safe to retry, because the limiter refuses before anything runs.

Retrying writes safely

Don't blindly retry a POST that failed with a 5xx or a dropped connection: a POST /posts may already have committed, and replaying it publishes twice. Read the post back (GET /posts, or GET /posts/publish-status) first. The SDK follows this rule for you.

Platform limits

Network limits, like X's 280 characters or Instagram's five hashtags, are enforced on our side before anything is sent, and come back as a 400 with the reason. Fit posts up front with GET /api/v1/platforms, which serves the same rules.