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

# Errors

> Wave's bilingual error envelope, error codes, and HTTP statuses.

Errors return a consistent **bilingual envelope** with a machine-readable code, English and Arabic messages, a request id for support, and a docs link:

```json theme={null}
{
  "error_code": "VALIDATION_ERROR",
  "message": "to must be a valid KSA phone number",
  "message_ar": "خطأ في التحقق من البيانات",
  "request_id": "req_abc123",
  "docs_url": "https://wave.sa/docs/errors"
}
```

Always branch on **`error_code`** (stable), not the message text.

## HTTP statuses

| Status | Meaning                                                          |
| ------ | ---------------------------------------------------------------- |
| `400`  | Validation error — check the request body.                       |
| `401`  | Missing or invalid API key.                                      |
| `403`  | Sandbox trial expired, or the key lacks the required permission. |
| `429`  | Rate limit exceeded — see [Rate limits](/rate-limits).           |
| `5xx`  | Upstream/telephony error — safe to retry with backoff.           |

## Error codes

| `error_code`                      | Typical status | Meaning                                                         |
| --------------------------------- | -------------- | --------------------------------------------------------------- |
| `VALIDATION_ERROR`                | 400            | The request body failed validation.                             |
| `INVALID_PHONE_NUMBER`            | 400            | `to` isn't a valid KSA number.                                  |
| `INVALID_API_KEY`                 | 401            | Missing, malformed, or unknown key.                             |
| `INSUFFICIENT_PERMISSIONS`        | 403            | The key lacks the `web_callback` permission.                    |
| `SANDBOX_EXPIRED`                 | 403            | The 30-minute sandbox trial has elapsed.                        |
| `SANDBOX_DESTINATION_NOT_ALLOWED` | 403            | Sandbox calls may only ring the owner's signup number.          |
| `RATE_LIMIT_EXCEEDED`             | 429            | More than 60 requests/minute — see [Rate limits](/rate-limits). |
| `CALL_FAILED`                     | 502            | The telephony backend could not place the call.                 |

The **complete** code list (including OTP, webhook, session, and Nafath codes) is in the [API Reference](/api-reference/overview) `Error` schema.

## Request id

Every response carries a `request_id`. Include it when contacting support — it lets us find the exact request in the logs.
