Errors
Every error has the same shape. Branch on error, which is stable; show or log message, which may change wording.
{
"success": false,
"error": "consent_required",
"message": "consent.opt_in_confirmed must be true and consent.consented_at must be an ISO 8601 timestamp."
}
Should I retry?
- 4xx: no. Fix the request first. The one exception is
429: wait, then retry. - 5xx: yes, with backoff (for example 2, 4, 8 seconds). Send the same
Idempotency-Keyso a retry can never create a second call.
POST /v1/orders and GET /v1/orders/{id}
| HTTP | Code | Meaning | Fix |
|---|---|---|---|
| 400 | invalid_json | The body is not a JSON object. | Send a JSON object with Content-Type: application/json. |
| 400 | consent_required | consent is missing, opt_in_confirmed is not true, or consented_at is missing, has no zone, is not a real date, or is more than 5 minutes in the future. Checked before the API key. | Send "consent": { "opt_in_confirmed": true, "consented_at": "2026-10-14T09:00:00Z", "source": "…" }. See Consent. |
| 400 | invalid_consent_source | consent.source starts with test_ or manual:, which are reserved for the dashboard. Checked before the API key. | Use your own source, for example the form or page the lead came from. |
| 401 | unauthorized | The API key is missing, malformed, unknown or revoked. | Send Authorization: Bearer av_live_… with an active key. |
| 400 | invalid_request | A field is wrong. The message names it: agent_id missing; lead or lead.phone missing; cadence not an object; max_attempts not 1 to 3; retry_interval_minutes not 5 to 10080; send_sms_on_voicemail not a boolean; webhook_url not https; external_reference_id over 200 characters; a bad Idempotency-Key. Also "The order was refused by validation" when the consent is older than 1,461 days. | Correct the field the message names. |
| 404 | agent_not_found | No agent with this agent_id in your key's workspace. | Copy the agent ID again; check you used the right workspace's key. |
| 409 | agent_inactive | The agent is switched off. | Switch the agent on. |
| 409 | agent_not_published | The agent has never been published, so it cannot take a call. | Publish the agent, then retry. |
| 400 | invalid_phone | lead.phone could not be read as a phone number. | Send E.164, for example +14155550199. |
| 422 | unsupported_destination | The number is not in the US mainland, Alaska or Hawaii: not +1, or a +1 number in Canada, the Caribbean, Puerto Rico or another US territory, or another country that shares +1, or no calling window could be found for it in the next 3 days. | v1 calls those US numbers only. Do not retry. |
| 409 | idempotency_key_conflict | The Idempotency-Key was already used by an order made with the other kind of key (test vs live). | Use a new key. |
| 429 | rate_limited | Test keys only: more than 500 test orders in this workspace in the last 24 hours. | Wait, or test with fewer orders. |
| 422 | high_cost_destination | The US number is in a high-cost area we do not call (a small set of rural US exchanges). | Reach this lead another way. Do not retry. |
| 402 | insufficient_balance | The wallet is under $1.00, or calling is paused on the account. | Top up the wallet, then retry. |
| 402 | plan_inactive | The account has no active plan (not yet paid, or cancelled). | Choose or reactivate a plan in the app, then retry. |
| 409 | do_not_contact | This number asked not to be contacted by your business (said "stop calling" on a call, replied STOP, or was added by you). | Do not retry. Mark the contact as do-not-call in your system. |
| 503 | suppression_unavailable | The do-not-contact list could not be read. We never call when we cannot check. | Retry shortly. |
| 503 | rate_unavailable | The destination could not be checked. | Retry shortly. |
| 503 | wallet_unavailable | The wallet could not be checked. | Retry shortly. |
| 404 | not_found | GET: no such order in your workspace. | Check the order_id and the key. |
| 405 | method_not_allowed | Only POST and GET are supported. | Use the right method. |
| 500 | internal_error | Something failed on our side. | Retry with the same Idempotency-Key. |
GET /v1/orders, /v1/me and /v1/agents
| HTTP | Code | Meaning | Fix |
|---|---|---|---|
| 401 | unauthorized | The API key is missing, malformed, unknown or revoked. | Send Authorization: Bearer av_live_… with an active key. |
| 400 | invalid_request | A query value of the order list is wrong: status, since, limit or agent_id. The message names it. | Correct the value the message names. |
| 405 | method_not_allowed | /v1/me and /v1/agents take GET only. | Use GET. |
| 429 | rate_limited | More than 120 read requests in a minute for this workspace. | Wait the seconds in Retry-After, then retry. |
| 503 | unavailable | The agents or orders could not be read. | Retry shortly. |
POST /v1/hooks/lead/{token}
The trigger URL can return any order error above except invalid_json, consent_required and unauthorized, plus these:
| HTTP | Code | Meaning | Fix |
|---|---|---|---|
| 404 | not_found | Unknown URL, or the URL or its agent is switched off. | Copy the URL again; tick the consent statement to switch it on. |
| 400 | invalid_body | Not JSON or form fields, or larger than 64 KB. | Send JSON or application/x-www-form-urlencoded. |
| 400 | invalid_request | No phone number was found in the lead. | Send a field named phone (or one of the other names). |
| 403 | test_number_not_verified | A test lead (?test=1) to a number your workspace has not confirmed in the last 90 days. | Confirm the number with a one-time code first. |
| 429 | rate_limited | More than 60 leads in one minute to this URL. | Wait for Retry-After (60 seconds). |
| 503 | unavailable | A short problem on our side. | Retry shortly. |
| 405 | method_not_allowed | Only POST is accepted. | Use POST. |
| 500 | internal_error | Something failed on our side. | Retry. The same payload within 24 hours will not call twice. |
GET /v1/recordings/…
| HTTP | Code | Meaning | Fix |
|---|---|---|---|
| 404 | not_found | No such order, not your workspace, no valid key, or the call has no recording. | Send your API key; check the order has a recording_url. |
| 410 | recording_deleted | The recording was deleted after your workspace's retention period (30 days by default). | Nothing to fetch. Download recordings you need before the period ends, or lengthen it in your workspace settings. |
| 502 | recording_unavailable | The audio could not be fetched right now. | Retry shortly. |
| 503 | unavailable | Playable links cannot be made right now. | Retry shortly. |
| 405 | method_not_allowed | Only GET is accepted. | Use GET. |
| 500 | internal_error | Something failed on our side. | Retry. |
Developer settings (dashboard)
Errors the dashboard shows when an owner or admin manages API keys and webhooks (see Managing keys and Webhook settings). They are not returned by the public API.
| HTTP | Code | Meaning | Fix |
|---|---|---|---|
| 409 | api_key_limit | The workspace already has 20 active API keys. | Revoke a key you no longer use, then create the new one. |
| 400 | invalid_webhook_url | The webhook URL is not https://, carries a user name or password, does not resolve, or points at a private, loopback, link-local or otherwise non-public address (including IPv6 forms of such addresses). | Use a public https:// URL. |
| 400 | no_webhook_url | A test event was asked for with no URL, and the workspace has no default (or test) webhook URL. | Give a URL or set the webhook URL first. |
| 429 | rate_limited | More than 10 test events, or more than 20 new API keys, in this workspace in the last hour. | Wait and try again later. |
| 403 | forbidden | Only an owner or admin of the workspace can do this. | Ask an owner or admin. |
Problems after an order is accepted
Some problems only show up when we try to dial, after you already got 202. The order then ends as FAILED and you get an order.completed webhook. Common causes: the lead said "stop calling" or replied STOP to another order in the meantime, the agent was switched off, or your workspace has no active phone number to call from. The reason is in the reason field of the webhook and of GET /v1/orders/{order_id} (for example do_not_contact, agent_inactive, no_caller_id, unsupported_destination), and on the order's timeline in the dashboard.
An order that cannot start because the wallet cannot cover the start of a call, or because the plan is cancelled or overdue, does not fail: it stays queued with reason waiting_for_balance, plan_inactive or plan_past_due, you get one order.updated webhook, and it dials once the problem is fixed.