Guides
Errors & retries
Every error, at the request level or per target, uses one normalised shape, so you (or an agent) can handle failures the same way everywhere.
The error envelope
Errors return { "error": { … } } with a stable type, a human message, an optional platform, and a retryable boolean.
{
"error": {
"type": "entitlement_exceeded",
"message": "Not enough credits: this post costs 5, you have 2.",
"platform": null,
"retryable": false
}
}Two levels of error
- Request-level: the whole call is rejected (bad auth, malformed body, out of credits). Returned with a
4xxstatus and the envelope above. - Per-target: the call succeeds but one platform fails (over a limit, invalid option). The post is
partial, and the failingtargets[].errorcarries the same envelope. You're not charged for failed targets.
Error types
| Type | HTTP | Meaning | Retry? |
|---|---|---|---|
invalid_request | 400 | Malformed body or invalid field/option. | Fix & resend |
unauthorized | 401 | Missing or invalid API key. | No |
entitlement_exceeded | 402 | Out of credits, or your plan doesn't allow this (e.g. X/TikTok on free). | After topping up / upgrading |
rate_limited | 429 | Too many requests. | Yes, after a short back-off |
| platform errors | — | A specific network rejected the target (see platform). | Depends on the message |
Retrying safely
When retryable is true (e.g. rate_limited), back off and retry. Always send the same Idempotency-Key on retries so a post that actually went out isn't duplicated. On 429, honour any Retry-After header. Non-retryable errors (unauthorized, invalid_request) need a fix, not a retry.