Docs · Reference · Errors

Errors.

Every non-2xx response uses one envelope. The code is a stable machine-readable string — branch on it, not on the message text, which can change.

The envelope#

Error response body
{
  "error": {
    "code": "invalid_request",
    "message": "languages: must be a non-empty array of ISO codes (e.g. [\"ar\", \"en\"])"
  }
}

Validation messages name the offending field as field: problem, so one response tells you exactly what to fix. Fix the payload before retrying — replaying an invalid_request unchanged fails the same way.

Error codes#

FieldTypeDescription
invalid_request400The request failed validation: a missing or malformed field, a bad languages array, an unknown dialect or voice, a bad filter value or cursor. The message names the violation.
invalid_api_key401Missing Authorization header, malformed key, unknown key, or revoked key — deliberately indistinguishable.
insufficient_credits402The wallet can't cover a call that's about to start. Nothing was dialed or charged.
forbidden403Rare. The key is valid but lacks the scope for this action — e.g. a read-only key attempting a write.
not_found404The resource doesn't exist, or it belongs to another organization — the API doesn't distinguish.
agent_not_published409You tried to place a call or attach a number to an agent that has no published version. Publish it first.
number_unavailable409The phone number isn't active for that agent — it's pending, released, or attached elsewhere.
rate_limit_exceeded429Per-key request budget exhausted for the current 60-second window. Comes with a retry-after header in seconds.
server_error500Something broke on our side. Safe to retry with backoff; the failure is already logged and alerting.

402 — insufficient credits#

402 example
HTTP/1.1 402 Payment Required
Content-Type: application/json

{
  "error": {
    "code": "insufficient_credits",
    "message": "Insufficient credits: wallet can't cover the call. Top up or upgrade."
  }
}

The wallet is checked against the call before anything is dialed — a 402 always reflects your true balance, never a half-started call to clean up. Top up or turn on auto-recharge so a low balance can never drop a call mid-campaign. Balances and top-ups live on Usage.

409 conflicts#

A 409 means the resource exists but isn't in a state that allows the action. Two cases:

  • agent_not_published — the agent has no live version. Call publish first; see Agents.
  • number_unavailable — the number isn't active for that agent. Attach an active number and confirm it's bound to the agent; see Phone numbers.
409 example
HTTP/1.1 409 Conflict
Content-Type: application/json

{
  "error": {
    "code": "agent_not_published",
    "message": "Agent ag_7Q2c51b84a07 has no published version. Publish it before placing calls."
  }
}

429 — rate limited#

The per-key request budget is exhausted. Wait retry-after seconds and retry — the window mechanics and client patterns are on Rate limits.