> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hubtalk.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Error codes and an end-to-end example

> The full list of codes and a working scenario in one piece.

# Error codes and an end-to-end example

## Error codes

### By type

| Status | `error.type`                | Codes on the endpoints of this guide                                                                                                                                                                                                     |
| ------ | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400    | `invalid_request_error`     | `caller_number_not_allowed`, `caller_number_outside_grant_pool`, `destination_number_invalid`, `ring_duration_invalid`, `invalid_filter_value`, `invalid_cursor`                                                                         |
| 401    | `authentication_error`      | `api_key_required`, `api_key_unknown`, `api_key_revoked`                                                                                                                                                                                 |
| 403    | `permission_error`          | `agent_not_in_subgroup`, `destination_not_allowed`, `privileged_key_required`, `root_org_key_required`                                                                                                                                   |
| 404    | `not_found_error`           | `trunk_not_found`, `subgroup_not_found`, `call_not_found`, `campaign_not_found`, `import_not_found`, `agent_not_found` (web calls only)                                                                                                  |
| 409    | `conflict_error`            | `agent_subgroup_ambiguous`, `agent_not_published`, `launch_blocked`, `campaign_transition_invalid`, `campaign_closed`, `market_package_not_installed`, `idempotency_key_in_flight`, `dnc_decision_without_upload`, `dnc_screen_required` |
| 422    | `invalid_request_error`     | `invalid_request` (schema) and the campaign codes below                                                                                                                                                                                  |
| 429    | `rate_limit_error`          | `api_key_rate_limit_exceeded`, `dial_queue_full`, `subgroup_concurrency_limit`, `subgroup_rate_limit`                                                                                                                                    |
| 500    | `api_error`                 | `internal_error`                                                                                                                                                                                                                         |
| 502    | `api_error`                 | `dial_failed` (synchronous fallback only), `contact_file_storage_unavailable`                                                                                                                                                            |
| 503    | `service_unavailable_error` | `voice_backend_unavailable`, `agent_dispatch_failed` (web calls)                                                                                                                                                                         |

### Campaign error codes

| Status | `error.code`                                                       | Cause                                                                                                                                          |
| ------ | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| 404    | `campaign_not_found` / `import_not_found`                          | No such object **in your organization**; anything outside that boundary is indistinguishable from missing.                                     |
| 409    | `launch_blocked`                                                   | Launch or resume checks did not pass; `error.blockers` names them.                                                                             |
| 409    | `campaign_transition_invalid`                                      | The transition is impossible from the current state.                                                                                           |
| 409    | `campaign_closed`                                                  | `calls`: the campaign is completed or cancelled.                                                                                               |
| 409    | `market_package_not_installed`                                     | Contacts cannot be screened for this organization; contact support.                                                                            |
| 409    | `idempotency_key_in_flight`                                        | A request with this key is still being processed; wait for its answer.                                                                         |
| 409    | `dnc_decision_without_upload`                                      | A `dnc` decision on a campaign that has no import.                                                                                             |
| 409    | `dnc_screen_required`                                              | The import has no source-row projection (pre-feature import): on a `dnc` decision, on `?only=dnc_match`, or as a launch blocker. Upload again. |
| 422    | `invalid_request`                                                  | Body fails schema validation; `message` is an array of field issues.                                                                           |
| 422    | `idempotency_key_required`                                         | The `Idempotency-Key` header is missing or blank.                                                                                              |
| 422    | `idempotency_key_reuse`                                            | This key was already used for a **different** request body.                                                                                    |
| 422    | `campaign_agent_unknown`                                           | No agent with this name in your organization.                                                                                                  |
| 422    | `campaign_window_invalid`                                          | `ends_at` is not later than `starts_at`.                                                                                                       |
| 422    | `campaign_timezone_unknown`                                        | Not an IANA zone name.                                                                                                                         |
| 422    | `campaign_classification_invalid`                                  | `classification` is not one of the three documented values.                                                                                    |
| 422    | `campaign_spec_invalid`                                            | Name length, pace tier, retry configuration, working-hours form or duplicate action rejected.                                                  |
| 422    | `campaign_open_ends_at_required` / `campaign_open_ends_at_too_far` | A campaign open to call additions has no `ends_at`, or one beyond the horizon.                                                                 |
| 422    | `dialing_route_unresolved` / `dialing_route_ambiguous`             | No binding, or more than one candidate.                                                                                                        |
| 422    | `dialing_binding_incomplete`                                       | `route_id` or `from_number` named without `trunk_id`.                                                                                          |
| 422    | `working_hours_wider_than_law`                                     | The schedule is wider than the floor (legal window or organization calling window).                                                            |
| 422    | `attestation_import_id_required`                                   | `attestation.import_id` missing on `launch`.                                                                                                   |
| 422    | `dnc_decision_invalid`                                             | `dnc` is neither `block` nor `skip`.                                                                                                           |
| 422    | `contact_rows_rejected`                                            | The planned calls could not be stored at all; read the import report.                                                                          |
| 422    | `report_format_invalid`                                            | `format` is neither `csv` nor `xlsx`.                                                                                                          |
| 422    | `report_filter_invalid`                                            | `only` is neither omitted nor `dnc_match`.                                                                                                     |
| 422    | `calls_required` / `calls_batch_too_large`                         | `calls` is empty, or has more rows than the cap (1000 by default).                                                                             |
| 422    | `attestation_invalid`                                              | `calls`: `attestation` is not exactly `{"confirmed": true}`.                                                                                   |
| 422    | `calls_rejected`                                                   | The batch was refused whole because of a data error (or a structural parse refusal); `error.import` names the rows.                            |
| 422    | `calls_dnc_matched`                                                | The batch was refused whole because at least one number is on the do-not-call registry; read the `dnc_match` report.                           |
| 502    | `contact_file_storage_unavailable`                                 | The contact source could not be stored, so the upload was not accepted; retry.                                                                 |

## End-to-end example

```bash theme={null}
BASE_URL="https://app.hubtalk.ai"   # the host your dashboard runs on
API_KEY="cfk_…"   # the secret shown once when the key was created

# 1. Look up the agent's available lines (optional: omit the binding
#    entirely and the platform resolves it itself)
curl -s "$BASE_URL/v1/dialing-routes?agent_id=collections-agent" \
  -H "Authorization: Bearer $API_KEY"

# 2. Create the campaign, hand over the numbers and launch — one request
curl -s -X POST "$BASE_URL/v1/campaigns" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: june-collections-2026-09-09" \
  -d '{
        "name": "june collections",
        "agent_id": "collections-agent",
        "calls_per_minute": 10,
        "timezone": "Asia/Almaty",
        "classification": "debt_collection",
        "working_hours": [{"days": [0,1,2,3,4], "start": "09:00", "end": "19:00"}],
        "attestation": {"confirmed": true},
        "planned_calls": [
          {"phone": "+77001234567", "name": "Aigerim", "variables": {"debt": "15000"}},
          {"phone": "+77007654321", "name": "Daniyar"}
        ]
      }'
# → 201. Check "status": "running" | "scheduled" | "draft".
#   "draft" means the reason is named in "blockers": fix it and call
#   POST /v1/campaigns/{id}/launch with
#   {"attestation": {"confirmed": true, "import_id": "<import.import_id>"}}
#   Note: by default retry_config.attempts = 1 — nobody is called back.

# 3. Stream more numbers later (the campaign must not be closed)
curl -s -X POST "$BASE_URL/v1/campaigns/cam-b9b536a86e/calls" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: crm-batch-2026-09-09-17" \
  -d '{"calls": [{"phone": "+77009998877", "name": "Symbat"}],
       "attestation": {"confirmed": true}}'
# → 201 (accepted whole) or 422 calls_rejected / calls_dnc_matched (refused whole)

# 4. Follow it
curl -s "$BASE_URL/v1/campaigns/cam-b9b536a86e/progress" \
  -H "Authorization: Bearer $API_KEY"

# 5. Inspect the problematic rows
curl -s "$BASE_URL/v1/imports/imp-353d158dd2/report?format=csv" \
  -H "Authorization: Bearer $API_KEY" -o import-report.csv

# ...and the do-not-call matches on their own
curl -s "$BASE_URL/v1/imports/imp-353d158dd2/report?only=dnc_match&format=csv" \
  -H "Authorization: Bearer $API_KEY" -o import-dnc.csv

# 6. Per-call results arrive as the usual call_ended / call_analyzed webhooks —
#    a campaign dials the same calls this API places one by one
```
