Skip to content
postpeg

Errors

Every error is JSON in the RFC 9457 problem details format, served as application/problem+json, with a stable code you can branch on.

The shape

Response · 400 Bad Request
{
  "type": "https://postpeg.com/errors/invalid_request",
  "title": "Invalid request",
  "status": 400,
  "detail": "X: text is 312 characters, the limit is 280",
  "code": "invalid_request",
  "request_id": "8f14e45f-ceea-467a-9575-1f2a5c3e6b0d",
  "issues": [
    {
      "path": "content",
      "message": "X: text is 312 characters, the limit is 280"
    }
  ]
}
  • code is stable and only ever gains new values. Branch on it, not on detail.
  • detail is written for a person: show it, log it, don’t parse it.
  • issues appears on invalid_request and lists every problem found, each with the path of the field.
  • retry_after appears on rate_limited, in seconds, matching the Retry-After header.
  • request_id matches the X-Request-Id response header. Send your own X-Request-Id to correlate with your logs, and quote it when you contact us.

Codes

CodeStatusWhat to do
invalid_request400The body, query or a platform rule is wrong. Read issues: it lists every problem with its path. Fix the request; retrying it unchanged fails the same way.
unauthorized401The key is missing, malformed or revoked. Send Authorization: Bearer pp_live_… with a key from the dashboard.
account_limit402Connecting one more account would go over your plan. Disconnect an account or upgrade.
subscription_required402The trial or subscription has ended. Only GET /v1/me and /v1/billing still work: start a checkout to continue.
forbidden403The network refused because the account’s login has expired. The account is now reconnect_required: run the connect flow again.
not_found404No such route, or no object with that id on your account (disconnected accounts count as gone).
conflict409The object is in the wrong state for this request, for example cancelling a post that already went out. detail says which.
rate_limited429Too many requests, from your key or on the network’s side. Wait retry_after seconds (also in the Retry-After header), then retry.
internal_error500Something broke on our side. Retry with backoff, and quote request_id if it persists.
upstream_error502The network failed or refused the request; detail carries its reason. Retry later if it didn’t respond; fix the request if it refused.
platform_unavailable503That feature or network is not available on postpeg yet. Retrying won’t help until it is.

What to retry

Retry rate_limited after retry_after, and internal_error and upstream_error with backoff when the network didn’t respond. Don’t retry invalid_request, unauthorized, account_limit, subscription_required or platform_unavailable unchanged: they’ll fail the same way. Send an Idempotency-Key on writes so a retry is always safe.

Publishing itself retries on its own: a failed target is retried in the background, and you see the outcome on the post. See Retries.