Errors
A single error shape with stable machine-readable codes.
Every error returns a consistent JSON envelope with a stable code (branch on this) and a human message (show this).
json
{ "error": { "code": "missing_scope", "message": "This key is missing the required scope.", "details": {} }}Common codes
| HTTP | code | Meaning |
|---|---|---|
| 401 | api_key_required | No key supplied |
| 401 | api_key_invalid | Key not recognised |
| 401 | api_key_revoked / api_key_expired | Key no longer valid |
| 402 | free_trial_expired | Subscription/trial lapsed |
| 403 | missing_scope | Key lacks the required scope |
| 409 | idempotency_key_conflict | Same key, different body |
| 409 | idempotency_request_in_progress | Same key is still being processed; retry shortly |
| 413 | payload_too_large | Request body over 1 MB |
| 409 | cap_reached | Per-workspace limit hit |
| 429 | rate_limited | Too many requests |
| 400 | bad_request | An id in the path or query string is not a valid id |
| 502 | upstream_rejected | A dependent service refused the request; retry later |
| 503 | quota_check_unavailable | Usage limits could not be checked, so a write was not attempted; retry shortly |
Always branch on code, not the human message - messages may change, codes are stable.