code is the stable identifier to branch on. message is written for a human debugging an integration and may change at any time — never match on it. details is present when the failure has a per-field or per-network breakdown.
Codes
Per-network failures
A post addressed to several profiles is validated against every one of them before anything is sent. If it is invalid anywhere, nothing publishes anddetails lists one entry per network:
details, code is a publishing code rather than a top-level one:
Validate the same body against
POST /v1/validate first and you get the same answer without publishing anything.
A failure after publishing has started is not an error response. The post is created, the request returns
201, and the post’s status is partially_published or failed with the reason on each target. Retry those targets with POST /v1/posts/{postId}/retry — targets that already published are never re-sent. For a scheduled post there is no request to inspect, which is what webhooks are for: post.failed and post.partially_published carry the same targets.Rate limits
Limits are per API key, not per IP, so a key used from two regions still gets one bucket and two customers behind one cloud NAT do not share one.
Successful responses carry the current state:
429 carries those plus Retry-After, in seconds.
Recommended handling
- Do not retry
400,401,402,404or409without changing the request. - Retry
429afterRetry-After, and5xxwith exponential backoff. - Send an
idempotency_keyonPOST /v1/postsso a retry after a timeout returns the original post instead of publishing twice. - Log
error.codeand the HTTP status. Never log the API key.