Skip to content

Errors

Every error is RFC 9457 problem details, served as application/problem+json:

{
"type": "about:blank",
"title": "Validation failed",
"status": 422,
"code": "validation_failed",
"detail": "limit must be at most 100",
"errors": [{ "path": "limit", "message": "must be at most 100" }],
"requestId": "01JR..."
}
Status code What it means
401 unauthorized Missing, malformed, revoked or expired key
403 insufficient_scope Real key, but it lacks the scope this operation names
404 not_found No such row in your organization
422 validation_failed A parameter or body field is wrong; see errors[]
429 rate_limited Over the key’s per-minute limit; honour Retry-After
500 internal_error A fault on our side — quote requestId

Write operations add idempotency_in_progress, idempotency_key_reused, invalid_transition, channel_not_connected, template_not_approved, missing_variables, outside_service_window and provider_error as those endpoints ship.

An id belonging to another organization answers 404, exactly like an id that does not exist. That is deliberate: a 403 would confirm the row exists somewhere, which is enough to probe for real ids. Do not read 404 as proof that a record was deleted — see syncing.

429 and 5xx are worth retrying with exponential backoff and jitter. 4xx other than 429 will fail again identically — fix the request instead.

Always log requestId (also returned as the X-Request-Id header, on success as well as failure).