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

# Errors

> Every error code the API returns, with its HTTP status and what to do about it.

Errors are JSON with a stable, machine-readable `error` string. Match on the string, not on the HTTP status: two `429` codes and several `403` codes mean different things. Some errors add fields (`status`, `message`, `balance_halalas`, `price_halalas`, `provider_code`, `fields`).

```json theme={null}
{ "error": "insufficient_credits", "message": "Insufficient credits", "balance_halalas": 0, "price_halalas": 9 }
```

Every response carries an `X-Request-Id` header. Quote it when you contact support.

## Shared by every endpoint

Checked in this order, before the endpoint's own logic.

| HTTP | `error`              | Meaning                                                                                                       |
| ---- | -------------------- | ------------------------------------------------------------------------------------------------------------- |
| 429  | `too_many_requests`  | Per-key rate limit exceeded (120 requests per minute, fixed 60-second window). Checked before authentication. |
| 401  | `unauthorized`       | Missing, unknown, revoked or mode-mismatched key, or an unknown or suspended partner.                         |
| 401  | `key_expired`        | The key's `expires_at` has passed. Checked right after the key is recognised.                                 |
| 403  | `ip_not_allowed`     | The caller's IP is outside the key's `ip_allowlist`.                                                          |
| 403  | `insufficient_scope` | A check-scoped key called anything but `check` or `GET /v1/verify/{id}`.                                      |
| 400  | `service_required`   | A partner key with no `application` (or `service`) in the request.                                            |
| 404  | `service_not_found`  | A partner key, but `application` does not match any of that partner's provisioned applications.               |
| 403  | `account_not_active` | The application is not approved yet, the account is banned, or a partner disabled the application.            |
| 400  | `invalid_json`       | The request body is not valid JSON.                                                                           |
| 400  | `invalid_request`    | A required field is missing: `to` on `start`, `id` or `code` on `check`.                                      |
| 500  | `internal_error`     | An unhandled server error. Quote the `X-Request-Id`.                                                          |

## Verify

| HTTP | `error`                          | Endpoints                     | Meaning                                                                                                         |
| ---- | -------------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------- |
| 422  | `unsupported_channel`            | start                         | Unknown channel, or a known channel that is not live over this API.                                             |
| 422  | `sandbox_unsupported_channel`    | start                         | A sandbox key on a channel that cannot carry the `[TEST]` stamp (WhatsApp).                                     |
| 422  | `invalid_destination`            | start                         | Not an accepted Saudi mobile format. See [Destinations](/destinations).                                         |
| 422  | `sandbox_unverified_destination` | start                         | Sandbox key, and the destination is not on the account's proven list.                                           |
| 429  | `sandbox_quota_exceeded`         | start                         | The application's lifetime sandbox cap of 10 sends is reached.                                                  |
| 429  | `rate_limited`                   | start, resend                 | The per-destination hourly cap is reached. Same status as `too_many_requests`, different meaning.               |
| 429  | `ip_rate_limited`                | start, resend                 | The `client_ip` you passed sent more starts this hour than `max_per_ip_per_hour` allows.                        |
| 429  | `spend_cap_reached`              | start, resend                 | Today's charges plus this send would pass `daily_spend_cap_halalas`.                                            |
| 403  | `application_paused`             | start, resend                 | Auto-paused by the protection guard after a spike in new destinations. The owner resumes it from the dashboard. |
| 402  | `insufficient_credits`           | start, resend                 | The prepaid balance is below the channel price. Nothing was sent.                                               |
| 502  | `send_failed`                    | start, resend                 | The delivery provider failed. The charge is refunded automatically; retry with the same `Idempotency-Key`.      |
| 404  | `not_found`                      | check, status, resend, cancel | Unknown id, or an id that belongs to another account or application.                                            |
| 409  | `not_resendable`                 | resend                        | Already verified, failed, expired or canceled. The body carries the current `status`.                           |
| 409  | `not_cancelable`                 | cancel                        | Already in a terminal state. The body carries the current `status`.                                             |
| 429  | `resend_limit_reached`           | resend                        | This verification already used its 3 resends.                                                                   |

## WhatsApp

After the shared checks, in this order.

| HTTP | `error`                         | Meaning                                                                                                                                                                                             |
| ---- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 403  | `live_key_required`             | A sandbox key. WhatsApp has no sandbox; use the application's live key.                                                                                                                             |
| 403  | `whatsapp_not_enabled`          | WhatsApp is turned off for this application. Contact support if that is a mistake.                                                                                                                  |
| 409  | `no_whatsapp_number`            | No WhatsApp number is connected to this application yet. Connect one from the application's WhatsApp tab.                                                                                           |
| 409  | `number_disconnected`           | The number is attached but Meta does not report it as connected right now. The dashboard shows the number's health.                                                                                 |
| 422  | `invalid_destination`           | Not an accepted Saudi mobile format.                                                                                                                                                                |
| 422  | `unknown_template`              | No template with that name (and language, when given) on the number's WhatsApp Business Account. `GET /v1/whatsapp/templates` lists what exists.                                                    |
| 422  | `template_not_approved`         | The template exists but Meta has not approved it. `message` carries Meta's status.                                                                                                                  |
| 422  | `template_category_not_allowed` | An authentication template. One-time codes go through Verify.                                                                                                                                       |
| 422  | `unsupported_template`          | The template needs a media header, a non-text button parameter, or mixes named and positional placeholders. `message` says which.                                                                   |
| 422  | `invalid_params`                | A placeholder value is missing, empty, unexpected, too long or contains a control character, or the template exists in several languages and `lang` was not given. `message` names the placeholder. |
| 402  | `insufficient_credits`          | The balance is below the WhatsApp message fee. The body adds `balance_halalas` and `price_halalas`.                                                                                                 |
| 502  | `send_failed`                   | Meta refused the send or is unreachable. The body adds `provider_code` and `message`; the fee is refunded.                                                                                          |
| 503  | `templates_unavailable`         | Meta did not answer the read of the template list. Nothing was sent or charged; retry shortly.                                                                                                      |
