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-2xx as a failure and read error for the reason.
  • On 429, back off for the seconds in the Retry-After header before retrying. See Rate limits.
  • 402, 403, and 422 are your conditions to fix (top up, add a scope, publish the agent) - retrying without changing anything won’t help.

Next: Rate limits →