Postato Docs
Guides

Error Handling

Error envelope, retry strategy, and distinguishing transient from permanent failures.

Error handling

Every non-2xx response from the Postato API carries a structured error envelope. Treat status code + error field as the pair you branch on; never parse the human message.

Envelope

{
  "error": "INVALID_REQUEST",
  "message": "Body failed validation",
  "details": { "content": ["Required"] }
}
  • error: stable machine code. Safe to switch on.
  • message: human string. Can change at any time; don't match regex against it.
  • details: optional, shape varies by error. For validation errors it's { field: string[] }.

Status codes

CodeMeaningYour response
400 INVALID_REQUESTBody failed schema validation.Fix the payload. Do not retry with the same body.
401Missing or invalid API key.Surface a "reconnect" prompt; don't retry blindly.
403 permission_deniedAPI key is valid but lacks the required permission.Ask a tenant admin to adjust the agent's grants.
403 plan_inactiveTenant's subscription is not active.Surface billing state, don't retry.
403 policy_violationPost violated a workspace policy (agent-specific facet).facet and reason fields explain which rule.
403 workspace_requiredCaller has access to multiple workspaces and didn't pass an ID.Re-issue with workspaceId from the response's available_workspaces.
404 not_foundResource doesn't exist (or caller can't see it).Do not retry.
409Resource state conflict (e.g. already revoked).Do not retry; surface to user.
422 VALIDATION_FAILEDPost failed platform-specific rules.Read errors[] for specifics. Not retryable as-is.
429Rate limit hit.Respect Retry-After header. See Rate limits.
500 / 502 / 503 / 504Transient server / upstream error.Retry with exponential backoff.

Retry strategy

Retry: 429 (after Retry-After), 500, 502, 503, 504, plus network-level timeouts.

Don't retry: 4xx except 429. The request is wrong; retrying yields the same error and wastes quota.

Always: use an Idempotency-Key for retried POST /posts so duplicates don't leak into the underlying network. See Idempotency.

Backoff shape we recommend: min(cap, base * 2^attempt + jitter) with base 500 ms, cap 30 s, 5 retries max. Anything longer than 5 min of retrying is probably a deeper problem.

Platform-origin errors

Posts that fail at the social network surface as post.failed with a structured error:

{
  "postId": "pst_...",
  "status": "failed",
  "error": {
    "origin": "platform",
    "code": "MEDIA_TOO_LARGE",
    "message": "Instagram rejected: file exceeds 100 MB",
    "platformRawCode": "...",
    "retryable": false
  }
}

retryable tells you whether resubmitting (with the same or different media) could succeed. Trust it: our post worker already did its own retry logic for transient platform errors before marking the post failed.

What to log

At minimum: status, error code, details or message, correlation ID from the X-Request-Id response header. That's enough to reproduce and debug. Skip logging raw response bodies long-term; validation error details can contain user content you shouldn't retain.

On this page