Back to app

Errors and HTTP status codes

Error format

Errors are JSON with a human readable detail and, when available, a stable machine code:

{ "detail": "invalid, expired or revoked API key", "code": "unauthorized" }

Validation errors add an errors list, one entry per problem, with the dotted path of the field (loc) and a message (msg):

{
  "detail": "invalid scenario",
  "code": "invalid_scenario",
  "errors": [{ "loc": "target.phone", "msg": "Value error, phone must be E.164, e.g. +15550123456" }]
}

Match on code and the status, never on detail: texts can change. Every error has a code. New codes can appear: treat an unknown code like the generic code of its status.

Status codes

Status Generic code Meaning What to do
200 201 204 Success. 201 created, 204 no body
202 CI mode: the run is still going at the wait timeout Poll GET /runs/{id}
400 bad_request The request is valid JSON but cannot be done (see below) Read code and detail
401 unauthorized Missing, malformed, unknown, expired or revoked key, or suspended organization Check the key
403 forbidden Not allowed: see the specific codes below Add the scope, fix the network or upgrade
404 not_found Unknown id, or an object of another organization Check the id
409 conflict Conflict: see the specific codes below Read detail
410 endpoint_sunset The endpoint was removed after its deprecation period See Versioning
412 CI mode: the run finished and failed the quality gate. Body: the run Fail the pipeline
422 invalid_request The request does not match the schema (wrong type, missing field, out of range) Fix the fields in errors
422 invalid_scenario The scenario or variant is invalid Fix the fields in errors
429 rate_limited Too many requests Wait Retry-After seconds
503 service_unavailable A dependency is not available Retry later
5xx Server error Retry GET requests with backoff; quote X-Request-Id to support

Specific codes

400

code Endpoint Meaning
invalid_threshold POST /scenarios/{id}/runs threshold must be between 0 and 100
run_not_possible POST /scenarios/{id}/runs The scenario is archived, or none of the requested variants exist or are enabled
replay_not_possible POST /replays The bundle's target number is not registered in this organization
invalid_bundle, missing_bundle POST /replays, .../variants/from-bundle invalid bundle at <field>: <message>, or neither call_id nor bundle given
invalid_target POST /targets The number is invalid, or its destination cannot be called
attestation_not_accepted, attestation_signer_missing, verification_failed POST /targets/{id}/verify, .../verification/attest, .../verification/start The attestation was not accepted (accept is not true, or the signer name is missing or shorter than 3 characters)
attestation_required .../verification/start Sign the attestation first (in the same request, or with .../verification/attest)
method_unavailable, unknown_method, wrong_method .../verification/start, .../verification/call The verification method is not available for this number, unknown, or not the one of the active code
no_active_code .../verification/call No active code: ask for a new one (.../verification/retry)
unsafe_url POST /webhooks, PATCH /webhooks/{id} The URL is not https, or its host resolves to a private address
unknown_event POST /webhooks, PATCH /webhooks/{id} An event type does not exist, or the list is empty
invalid_filters POST /webhooks, PATCH /webhooks/{id} A filter names an unknown scenario, tag or environment, or an unknown filter key
invalid_tags, invalid_request POST /tags/bulk Nothing to add or remove, no object, or an unknown object kind
unknown_environment, invalid_environment Runs, versions, environments, comparisons The environment (slug, name or id) does not exist in your organization
unknown_version, invalid_version POST /scenarios/{id}/runs, versions, comparisons The version does not exist in that environment, or its label is invalid
unknown_target, unknown_scenario Versions, environment bindings The number or the scenario does not exist in your organization
invalid_name, invalid_color, invalid_schedule, invalid_source_url, invalid_action Environments, versions, bindings A field is invalid (see detail)
invalid_period GET /environments/stability, GET /environments/compare days must be 7, 30 or 90
invalid_alert_channel POST /alert-channels, PATCH /alert-channels/{id} Not a Slack incoming webhook URL, invalid email address, more than 10 recipients, or no rule
invalid_cidr POST /api-keys, PATCH /api-keys/{id} An allowed network is not a valid IP address or CIDR, or there are more than 20
key_not_active POST /api-keys/{id}/rotate The key is already revoked or expired
invalid_url POST /wallet/checkout, /billing/... A redirect URL is not https
unknown_plan POST /billing/subscription/checkout Not a public plan that can be bought online
no_stripe_customer POST /billing/portal No subscription was ever bought online: subscribe first
key_creator_missing POST /invitations The admin who created the key no longer exists: create a new key
not_allowed POST /invitations, PATCH /members/{id}, DELETE /members/{id} Already a member, or the last admin (the seat limit is a 403, below)

403

A plan refusal (feature_not_in_plan, country_not_in_plan) also carries required_plan (the cheapest plan that lifts it) and upgrade_url (a one click upgrade page), when such a plan exists. An out of range top-up (POST /wallet/checkout) is a 422 invalid_request on amount_cents, like any schema error.

code Meaning Example detail
missing_scope The key lacks the scope the endpoint needs This API key lacks the 'write' scope (scenario.create).
ip_not_allowed The key is restricted to IP networks and the request comes from elsewhere This API key cannot be used from this IP address.
feature_not_in_plan Your plan does not include the feature Custom test data injection is not included in your plan (Starter). Upgrade to Growth to use it.
feature_not_in_plan (feature: seats) POST /invitations: every seat of the plan is taken (pending invitations count) Your plan includes 3 seats, all taken (pending invitations count). Upgrade to Growth to invite more people.
country_not_in_plan The number's country exceeds your plan's countries Your plan allows 1 phone country (US); GB is not one of them. Growth includes 5 phone countries.
blocked_policy POST /scenarios/{id}/runs: the scenario is held for a human review or refused by the compliance review Refused by the compliance review of this scenario (acceptable use policy): ... Change the scenario, or contact CallQA support to ask for a human review if you think this is a mistake.

409

code Meaning
already_exists A tag, an environment or a version with this name or label already exists
target_in_use The number has scenarios or call history: archive it instead
scenario_in_use The scenario cannot be deleted: archive it instead
environment_in_use, default_required The environment has runs or versions (it is kept so their history stays readable), or it is the default environment: make another one the default first
run_not_finished, call_not_finished DELETE /runs/{id} or DELETE /calls/{id} while a call is queued or in progress: cancel it first
verification_record DELETE /calls/{id} on a number verification call, kept as evidence
export_period_over, too_large, export_error POST /exports: the export period of a closed organization is over, or the archive is too large (contact support)
call_not_judged The call has not been judged yet
subscription_exists Already subscribed: change the plan in the billing portal
already_verified Number verification: the number is already verified
not_pending Number verification: start a verification first
call_in_progress, verification_in_progress Number verification: a verification call is already running (for this number, or another number of your organization)
number_suspended Number verification: the number is suspended by CallQA support

429 (besides rate_limited)

code Meaning
number_locked Number verification: 3 failed attempts in 24 hours, the number is locked for 24 hours
org_daily_limit Number verification: at most 10 verification calls per organization and 24 hours

503

code Meaning
generator_unavailable The scenario generator is not configured or not reachable
payments_unavailable Payments are not configured on this server

Call statuses and block reasons

A call can fail without any HTTP error: the trigger succeeded, but the call itself did not go through. Look at the call's status, block_reason and error.

status Final Meaning
queued no Waiting for a slot
dispatching, dialing, ringing, in_progress no Being placed or in conversation
judging no The call ended, verdicts are being computed
completed yes Judged: see verdict and score
error yes Failed after being queued: launch failure, caller error, or no result after the maximum time (the call's limits.max_duration_s plus 10 minutes, 40 minutes at least: error says "No completion received from the caller agent (timed out)."). Verdict error, reservation released
canceled yes Canceled before dialing
blocked_policy yes Not placed: a rule forbids it (see block_reason)
blocked_insufficient_credit yes Not placed: not enough quota or wallet credit

block_reason values:

block_reason status Meaning Fix
number_not_verified blocked_policy The target is not verified and has no attestation Verify it
number_locked blocked_policy 3 failed verification attempts in 24 hours Wait 24 hours or contact support
number_suspended blocked_policy Suspended by CallQA support Contact support
sandbox_no_batch blocked_policy Scheduled or CI run on an unverified number Verify the number
sandbox_daily_cap blocked_policy More than 3 calls in 24 hours to an unverified number Verify the number
attestation_outdated blocked_policy The attestation was signed under an older text Sign the new attestation
target_archived blocked_policy The target was archived Use an active number
country_not_in_plan blocked_policy The number's country exceeds your plan Upgrade the plan
blocked_destination blocked_policy This kind of line cannot be called (premium rate, shared cost...) Use another number
invalid_number blocked_policy Not a valid, dialable number Fix the number
emergency_number blocked_policy Emergency and public safety numbers (911, 988, 112, 999, 15, 17, 18, 116xxx...) are never called
compliance_blocked blocked_policy The compliance review refused the content of this call; error_message gives the reasons Change the scenario, or ask support for a human review
compliance_review blocked_policy The content of this call is held for a human compliance review by CallQA staff Wait for the decision, or contact support
daily_spend_cap blocked_policy CallQA's platform wide daily safety limit is reached (not your account) Retry later or contact support
org_suspended blocked_policy Your organization is suspended Contact support
org_closed blocked_policy Your organization is closed
subscription_inactive blocked_policy No active subscription Choose a plan
insufficient_credit blocked_insufficient_credit The wallet cannot cover the call Top up the wallet
quota_exhausted blocked_insufficient_credit Quota used up, the plan has no overage Upgrade the plan
spend_cap_reached blocked_insufficient_credit Monthly spending cap reached An admin raises the cap (PATCH /billing/settings)
overage_disabled blocked_insufficient_credit Quota and bonus calls used up, and paid overage is off An admin turns overage on, or upgrades

Some conditions only delay a call, it stays queued: a compliance review still in progress (a few seconds), your plan's concurrent call limit, the maximum number of calls per hour to the same number (30), for scheduled runs the call window of the scenario in that environment, and, for an unverified number in the sandbox, one call at a time between 8 am and 9 pm local time (see Number verification).

Retrying safely

  • GET requests are safe to retry.
  • A 429 is answered before anything happens: retrying any request after Retry-After is safe.
  • POST /scenarios/{id}/runs and POST /replays create a new run each time. After a network error, check GET /runs?scenario_id=...&since=... before triggering again, or you may pay for two runs.
  • POST /scenarios/import is an upsert by name: retrying it is safe.