Reference
Error Codes
Every error_code the gateway can return. Branch on the code, never on the prose in error — messages may be reworded, codes are contractual.
Error envelope
{
"success": false,
"error": "Human-readable message.",
"error_code": "machine_readable_code"
}53 of 53 codes
Request-shape codes
400 — the request itself is malformed: bad parameter, cursor, field list, or JSON.
invalid_id400 | — |
invalid_cursor400 | — |
invalid_limit400 | limit must be 1–100. Out-of-range values are rejected, never clamped. |
invalid_param400 | — |
invalid_filter400 | — |
unknown_param400 | Parameters are fail-closed: anything a route does not declare — including a typo — is rejected. |
invalid_fields400 | — |
invalid_json400 | — |
invalid_idempotency_key400 | — |
idempotency_key_required400 | Every POST, PATCH, and DELETE must send an Idempotency-Key. |
invalid_precondition400 | The If-Match header could not be parsed. `*`, `W/` and lists are rejected. |
Auth & signing codes
401 — the key, the HMAC signature, or the replay check rejected the request.
invalid_key401 | — |
signature_missing401 | The key requires signing and no signature was sent. |
signature_malformed401 | — |
signature_stale401 | The timestamp is outside the ±5-minute window. Sync your clock with NTP. |
signature_invalid401 | Almost always a canonical-string mismatch: check the `v1:` prefix, the colon separators, the query string, and the body hash. |
signature_unverifiable401 | — |
replay_detected401 | That exact signature was already used. Generate a fresh timestamp per attempt. |
Permission codes
403 — authenticated, but the key is not permitted to do this.
missing_scope403 | — |
missing_read_scope403 | Subscribing a webhook to an event family requires that family's read scope as well as webhooks:manage. |
scope_mismatch403 | — |
branch_scope_unsupported403 | Branch-scoped key used on a company-wide-only resource: storage, inventory, tasks, claims, employees, audit log. |
branch_scope_mismatch403 | — |
ip_not_allowed403 | — |
origin_forbidden403 | — |
Route codes
404 / 405 — no such record within your tenancy scope, or the method isn't supported.
not_found404 | No such record within your tenancy scope. |
converted404 | The record is now the other resource type; the message points at its new resource path. |
method_not_allowed405 | — |
Write-path codes
Returned only on POST, PATCH, and DELETE.
precondition_required428 | The route needs If-Match and none was sent. |
version_conflict409 | Someone else changed the record. The response carries current_version — re-read, re-apply, retry. |
request_in_flight409 | An identical idempotent request is still executing. Wait and retry the same key. |
estimate_locked409 | — |
has_dependents409 | — |
reenable_too_soon409 | Cooldown after a webhook endpoint was auto-disabled. Test the receiver first. |
idempotency_key_reuse422 | The same Idempotency-Key was replayed with a different payload. |
invalid_field422 | — |
invalid_reference422 | — |
unsupported_media_type415 | — |
payload_too_large413 | Bodies are capped at 64 KiB. |
write_indeterminate502 | The gateway could not confirm whether the mutation landed. Do not retry with the same Idempotency-Key — GET the record first, then retry with a new key only if the write didn't land. |
Send-route codes
Returned by the SMS and email send routes.
insufficient_credits402 | — |
sms_not_provisioned409 | — |
recipient_not_on_prospect422 | — |
recipient_opted_out422 | — |
recipient_suppressed422 | — |
sms_meter_unavailable503 | — |
suppression_check_unavailable503 | — |
email_not_configured503 | — |
Gateway & service codes
Returned by the gateway or a dependent service, on any route.
rate_limited429 | Respect the Retry-After header. |
internal_error500 | — |
server_misconfigured500 | — |
auth_unavailable500 | — |
replay_check_unavailable503 | — |
HTTP status meanings
| 200 | Success. Deletes also return 200 with a deletion receipt ({ id, object, deleted, deleted_counts }) — there is no 204 anywhere in the API. |
| 201 | Created (also used by the send routes). |
| 400 | Malformed request: bad parameter, unknown parameter, bad cursor, bad field list, bad JSON, missing Idempotency-Key. |
| 401 | Key missing, unrecognized, or revoked; signature missing, invalid, or stale; replayed request. |
| 402 | Insufficient SMS credits. |
| 403 | Authenticated but not permitted: missing scope, branch-scope restrictions, IP not allowed, forbidden origin. |
| 404 | No such record within your tenancy scope (includes converted — the record now lives at the other resource). |
| 405 | Method not supported on this route. |
| 409 | Conflict: version conflict, a same-key request still in flight, a locked estimate, dependent records blocking a delete. |
| 413 | Payload too large — bodies are capped at 64 KiB. |
| 415 | Writes must use Content-Type: application/json. |
| 422 | Well-formed but a value was rejected: validation failures, bad references, recipient restrictions, and Idempotency-Key reuse with a different payload. |
| 428 | The write requires an If-Match header and none was sent. |
| 429 | Rate limited. Respect Retry-After. |
| 500 | Our side. Retry with backoff. |
| 502 | write_indeterminate only. Do not blindly retry. |
| 503 | A dependent service is briefly unavailable. Retry with backoff. |
Retry policy, the response envelope, and write_indeterminate handling are covered in the Errors & Response Envelope guide.