Errors & status codes
The error envelope, status codes, and which failures are safe to retry.
Every error has the same shape:
{
"error": {
"code": "validation_failed",
"message": "events must contain no more than 1000 elements",
"details": { "…": "…" }
}
}Match on code, not on message.
| Status | code | Retry? |
|---|---|---|
400 | bad_request / a specific code | No — fix the request |
401 | unauthorized | No |
402 | billing_suspended | No — pay the outstanding invoice |
403 | forbidden | No |
404 | not_found | No |
409 | conflict | No |
422 | validation_failed | No |
429 | rate_limited | Yes, after Retry-After |
5xx | internal_error | Yes, with backoff — only for idempotent calls |
What is safe to retry
Retry telemetry ingest, flag evaluation, Remote Config fetches and reads. Don't blindly retry a push send, a realtime emit, a voice action or a survey response after a timeout — it may have succeeded, and a duplicate is visible to people. The SDKs follow exactly this policy.
Successful responses that still need checking
- Voice — adding a leg returns
200with anerrorfield for expected failures (call_blocked,no_outbound_trunk,media_unavailable). - Realtime emit succeeds with
recipients: 0when nobody in the room's environment is listening. - Usage limits — over a monthly cap, ingest endpoints answer successfully
with nothing written (
written: 0).
