Errors
Error format and status codes.
Error shape
Every error - validation, auth, or server - returns the same envelope:
{ "error": "a human-readable message" }
Internal details are never leaked in 5xx responses. Validation failures name the first field that failed:
{ "error": "invalid toNumber: toNumber must be a valid Indian (+91) subscriber number" }
Success envelope
Successful responses wrap the payload in a data key:
{ "data": { "id": "agt_…", "name": "…" } }
The one exception is POST /v1/calls, which returns a bare object ({ "placed": true, … }) with no data wrapper.
Status codes
| Code | Meaning | When |
|---|---|---|
200 |
OK | Reads, updates, deletes, upsert-update |
201 |
Created | POST /v1/agents, POST /v1/campaigns, POST /v1/contacts (new) |
202 |
Accepted | POST /v1/campaigns/:id/run - dialing starts in the background |
400 |
Bad request | Validation failure, or malformed JSON |
401 |
Unauthorized | Missing/invalid/revoked API key |
402 |
Payment required | Insufficient wallet balance (placing a call) |
403 |
Forbidden | Key missing the required scope, or workspace suspended / unverified |
404 |
Not found | The resource doesn’t exist in your workspace |
409 |
Conflict | Referential conflict (e.g. deleting an agent attached to a campaign) |
422 |
Unprocessable | A gate rejected it - call blocked by compliance, or an unpublished agent |
429 |
Too many requests | Rate limit, or a concurrency cap - see the Retry-After header |
502 |
Bad gateway | The call couldn’t be placed at the provider |
503 |
Unavailable | Required voice providers aren’t configured for the workspace |
Handling errors
- Treat any non-
2xxas a failure and readerrorfor the reason. - On
429, back off for the seconds in theRetry-Afterheader before retrying. See Rate limits. 402,403, and422are your conditions to fix (top up, add a scope, publish the agent) - retrying without changing anything won’t help.
Next: Rate limits →