Errors and retries
Handle API errors, request IDs, backoff, and safe retries.
Application errors use a JSON envelope with a stable code, a message, and request ID. Validation failures can include field-level errors.
{"error":{"code":"invalid_request","message":"The request did not pass validation","request_id":"Root=1-example","errors":[{"field":"body.default.email","message":"Invalid value"}]}}Branch on error.code, not message. Log request_id and include it when contacting support.
Gateway responses are an exception. Authentication or rate limiting can fail before the application handles a request, producing a simpler body such as {"message":"Forbidden"} or {"message":"Too Many Requests"} without error.code or a request ID. Clients must handle both shapes.
| Status | Meaning | Action |
|---|---|---|
400 | Invalid request | Fix fields named in error.errors. |
401 | Missing or invalid key | Check x-api-key. |
403 | Gateway rejection or permission denied | Check the key first, then workspace and resource access. |
404 | Resource not found | Verify IDs and object type. |
409 | State or idempotency conflict | Resolve before retrying. |
412 | Stale If-Match | Re-read and reconcile. |
429 | Rate limited | Retry with exponential backoff and jitter. |
500, 503 | Server unavailable | Retry with exponential backoff and jitter. |
Retry network failures, 429, and transient server errors. Cap attempts and delays and add jitter. For writes, reuse the same idempotency key only for the exact operation. Do not blindly retry validation, authentication, permission, or not-found responses.