API Guide
Errors & Response Envelope
The success/error envelope, HTTP status meanings, and the full error_code vocabulary.
Envelope
Success:
{ "success": true, "data": { … } }
Error:
{
"success": false,
"error": "Human-readable message.",
"error_code": "machine_readable_code"
}
Branch on error_code, never on the prose in error — messages may be reworded, codes are contractual.
Status codes
200— success. Deletes also return200with a deletion receipt ({ id, object, deleted, deleted_counts }) — there is no204anywhere 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, missingIdempotency-Key.401— key missing, unrecognized, or revoked; signature missing/invalid/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 (includesconverted— 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 useContent-Type: application/json.422— the request was well-formed but a value was rejected: validation failures, bad references, recipient restrictions, andIdempotency-Keyreuse with a different payload.428— the write requires anIf-Matchheader and none was sent.429— rate limited. RespectRetry-After.500— our side. Retry with backoff.502—write_indeterminateonly; see below. Do not blindly retry.503— a dependent service is briefly unavailable. Retry with backoff.
Error code vocabulary
Request-shape codes (400): invalid_id, invalid_cursor, invalid_limit, invalid_param, invalid_filter, unknown_param, invalid_fields, invalid_json, invalid_idempotency_key, idempotency_key_required, invalid_precondition.
Auth & signing codes (401): invalid_key, signature_missing, signature_malformed, signature_stale, signature_invalid, signature_unverifiable, replay_detected.
Permission codes (403): missing_scope, missing_read_scope, scope_mismatch, branch_scope_unsupported, branch_scope_mismatch, ip_not_allowed, origin_forbidden.
Route codes: not_found (404), converted (404 — the record is now the other resource type; the message tells you where), method_not_allowed (405).
Write-path codes: precondition_required (428), version_conflict (409), request_in_flight (409), estimate_locked (409), has_dependents (409), reenable_too_soon (409), idempotency_key_reuse (422), invalid_field (422), invalid_reference (422), unsupported_media_type (415), payload_too_large (413), write_indeterminate (502).
Send-route codes: insufficient_credits (402), sms_not_provisioned (409), recipient_not_on_prospect (422), recipient_opted_out (422), recipient_suppressed (422), sms_meter_unavailable (503), suppression_check_unavailable (503), email_not_configured (503).
Gateway/service codes: internal_error, server_misconfigured, auth_unavailable (500), replay_check_unavailable (503), rate_limited (429).
Every code is searchable, with its status and the endpoints that document it, on the error codes page.
write_indeterminate
A write returned write_indeterminate (502) when the gateway could not confirm whether the mutation landed. Do not retry with the same Idempotency-Key — the indeterminate outcome is stored against that key, so a same-key retry replays the same 502. Instead: GET the resource to see whether the write landed. If it did, you're done. If it didn't, retry with a new Idempotency-Key.
Partial success on sends
On the rare path where an SMS or email sends but the record write fails, the response is 201 with data: null and warning: "sent_not_recorded". The message did send — do not retry.
Retry policy
Retry 429 (honor Retry-After), 500, and 503 with exponential backoff and jitter. Handle 502 write_indeterminate as above — read before retrying, new key if you retry. Never retry 400, 401, 403, or 404 — those need a code change, not another attempt.