Errors
One shape, stable codes.
Every error has the same shape. Branch on code; show message to people if you like (it's written for them).
JSON
{
"error": {
"code": "invalid_request",
"message": "Check subject: Too small: expected string to have >=1 characters.",
"details": {
"fields": [
{
"path": "subject",
"message": "Too small: expected string to have >=1 characters"
}
]
}
},
"requestId": "req_3kPq0d1nV2a8sLmG"
}| Status | code | Means |
|---|---|---|
| 400 | invalid_request | A parameter or field is missing or wrong. `details.fields` says which. |
| 400 | invalid_json | The body isn't a JSON object. |
| 401 | unauthorized | No token, or the token isn't valid (signed out, revoked or mistyped). |
| 401 | token_expired | The access token is past its hour: get a new one with the refresh token. |
| 403 | insufficient_scope | The token doesn't carry the permission this needs (`details.scope`). |
| 403 | forbidden | The person's own access doesn't allow it (role, branch, territory). |
| 403 | api_disabled | The organisation turned the API off (Control › API access). |
| 403 | app_not_allowed | The organisation doesn't allow this app, or the app is turned off. |
| 403 | ip_not_allowed | The key only works from its listed addresses. |
| 404 | not_found | Nothing with that id that this person can see. |
| 405 | method_not_allowed | The path exists but not with this method. |
| 409 | conflict | It clashes with what's there (a duplicate, or a request with the same Idempotency-Key still running). |
| 410 | cursor_expired | A changes-feed position older than 30 days: list again and start the feed afresh. |
| 412 | precondition_failed | If-Match didn't match: someone changed it since you read it. Read it again. |
| 413 | payload_too_large | The body is over the limit for this endpoint. |
| 415 | unsupported_media_type | Send `Content-Type: application/json` (or the type the endpoint says). |
| 422 | unprocessable | Understood, but it can't be done (`message` says why), e.g. an Idempotency-Key reused with a different body. |
| 429 | rate_limited | Too many requests: wait `Retry-After` seconds. |
| 500 | internal_error | Our fault. Retry with the same Idempotency-Key; quote `requestId` to support. |
| 503 | unavailable | A service behind the API is busy or restarting: retry shortly. |
What to retry#
429: afterRetry-Afterseconds.500,502,503, network errors: with backoff (1 s, 2 s, 4 s…), and the sameIdempotency-Keyon POSTs.401 token_expired: refresh, then retry once.- Anything else in the 400s: fix the request; retrying won't help.