Errors
Every error returns a JSON body with a human message and a stable, machine-readable error code you can branch on.
{
"message": "This send would exceed your daily spend limit.",
"error": "spend_limit_exceeded"
}
HTTP status codes
What each status means at a glance.
| Status | Meaning |
|---|---|
200 / 201 / 202 | Success. 202 means the work was accepted and queued. |
401 | Missing or invalid bearer token. |
402 | Your wallet cannot cover the request. |
403 | Blocked by a token scope, the IP allowlist, a spend cap, or routing rules. |
404 | The resource does not exist (or is not yours). |
409 | An identical idempotent request is still in flight. |
422 | Validation failed (bad input, unapproved sender, no valid recipients). |
429 | Rate limited. Retry after the Retry-After header. |
Error codes
The error field values you may receive, and how to handle them.
| Code | Status | What it means / how to fix |
|---|---|---|
insufficient_balance | 402 | Top up your wallet, then retry. |
spend_limit_exceeded | 403 | A daily or monthly spend cap was hit. The body includes the period. |
ip_not_allowed | 403 | Your source IP is not on the account allowlist. |
traffic_not_routable | 422 | No route is configured for this traffic type. The body includes the traffic_type. |
sender_not_approved | 422 | Use an approved sender ID, or submit one for approval. |
no_valid_recipients | 422 | None of the supplied numbers were valid. |
no_valid_numbers | 422 | None of the supplied lookup numbers were valid. |
invalid_recipient | 422 | The destination number was not in a usable format. |
invalid_request | 422 | The request was malformed for this endpoint. |
audio_error | 422 | The voice text could not be synthesized, or audio_url could not be fetched. |
throttled | 429 | Too many requests. Wait for Retry-After seconds. |
idempotency_conflict | 409 | A request with the same Idempotency-Key is still processing. |
not_found | 404 | The resource does not exist or is not yours. |
Handling errors
Branch on the code, not the message.
Messages are for humans and may change; the error code is stable. Treat any 5xx as transient and retry with backoff. For 402 and 403, surface the message to the account owner.
Tip: pair every side-effecting request with an
Idempotency-Key so a retry after a network error never double-sends. See Authentication.