Errors
Error format and status codes.
Error shape
Every error - validation, auth, or server - returns the same envelope. Many errors also carry a stable machine-readable code (branch on it, not on the message), and some add details in meta:
{ "error": "a human-readable message", "code": "missing_required_variables", "meta": { "missing": ["amount"] } }
Common codes: api_scope_missing, workspace_suspended, agent_not_published, agent_not_call, agent_not_outbound, missing_required_variables, flow_not_ready, from_number_not_owned, agent_uses_flow, agent_in_use, knowledge_base_not_found, idempotency_key_reused, idempotency_in_progress, opt_out_downgrade, phone_immutable, contact_erased.
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" }
Request IDs
Every response carries an X-Request-Id header, and a 500 includes the same value as requestId in its body. Log it, and quote it when you contact support so we can find the exact request. If you send your own X-Request-Id (8–64 characters: letters, digits, ., _, -), we use it, which lets you match our records to your own traces.
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 (api_scope_missing), workspace suspended (workspace_suspended - every endpoint), or unverified |
404 |
Not found | The resource doesn’t exist in your workspace |
409 |
Conflict | A conflict with current state (e.g. deleting an agent a campaign uses, an Idempotency-Key still in progress) |
422 |
Unprocessable | A gate rejected it - call blocked by compliance, an agent that can’t run the call, a reused Idempotency-Key |
423 |
Locked | The agent is locked by its creator in the console |
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 →