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

# Error handling

> Standardized error responses with actionable suggestions

All API errors follow a consistent format designed for both developers and AI agents.

## Error response format

```json theme={null}
{
  "error": {
    "type": "not_found_error",
    "code": "CONVERSATION_ITEM_NOT_FOUND",
    "message": "No call or message found with ID 'cll_abc123'.",
    "retryable": false,
    "request_id": "req_a1b2c3d4e5f6",
    "doc_url": "https://help.withallo.com/en/v2/api-reference/guides/error-handling#CONVERSATION_ITEM_NOT_FOUND",
    "param": "id",
    "suggestion": "Search for the item using POST /v2/api/conversations/items/search."
  }
}
```

## Error fields

| Field                 | Type    | Description                                                |
| --------------------- | ------- | ---------------------------------------------------------- |
| `type`                | string  | Error category (see table below)                           |
| `code`                | string  | Stable error code for programmatic handling                |
| `message`             | string  | Human-readable explanation including the value that failed |
| `retryable`           | boolean | Whether the request can be retried                         |
| `request_id`          | string  | Unique ID for this request — include in support tickets    |
| `doc_url`             | string  | Link to documentation about this error                     |
| `param`               | string  | The parameter that caused the error (if applicable)        |
| `suggestion`          | string  | What to do next (may include endpoint names)               |
| `errors`              | array   | Field-level errors for validation failures                 |
| `retry_after_seconds` | integer | Seconds to wait before retrying (rate limits only)         |

## Error types

| Type                   | HTTP Status | When                                         |
| ---------------------- | ----------- | -------------------------------------------- |
| `authentication_error` | 401         | Invalid, missing, or expired API key         |
| `permission_error`     | 403         | Valid key but insufficient scope             |
| `validation_error`     | 400         | Bad input, missing params, wrong format      |
| `not_found_error`      | 404         | Resource doesn't exist                       |
| `conflict_error`       | 409         | Duplicate or state conflict                  |
| `rate_limit_error`     | 429         | Too many requests (always `retryable: true`) |
| `server_error`         | 500         | Internal failure                             |

## Request ID

Every response includes a `request_id` (format: `req_` + 12 alphanumeric characters). You can also send your own via the `X-Request-Id` header — the API will use it instead of generating one.

```bash theme={null}
curl -X GET "https://api.withallo.com/v2/api/conversations" \
  -H "Authorization: Api-Key ak_live_your_key" \
  -H "X-Request-Id: req_my_custom_id"
```

## Validation errors

When multiple fields fail validation, the `errors` array lists each one:

```json theme={null}
{
  "error": {
    "type": "validation_error",
    "code": "INVALID_REQUEST",
    "message": "Request validation failed.",
    "errors": [
      { "field": "date_from", "code": "INVALID_DATE", "message": "Must be a valid ISO 8601 date." },
      { "field": "allo_number", "code": "INVALID_PHONE_FORMAT", "message": "Must be E.164 format (e.g. +14155551234)." }
    ]
  }
}
```

## Phone number format

All phone numbers must be in **E.164 format**: `+` followed by country code and number, no spaces or dashes.

```
+14155551234    ← correct
0612345678      ← wrong (missing country code)
+33 6 12 34 56  ← wrong (contains spaces)
```

Invalid phone numbers return:

```json theme={null}
{
  "error": {
    "type": "validation_error",
    "code": "INVALID_PHONE_FORMAT",
    "message": "'+33 6 12 34' is not a valid E.164 phone number.",
    "suggestion": "Use E.164 format: +14155551234 (no spaces, with country code)."
  }
}
```

## Idempotency

All write endpoints (POST, PUT, DELETE) support an optional `Idempotency-Key` header to safely retry requests.

### How it works

1. Send a unique `Idempotency-Key` header with your write request (e.g., a UUID)
2. If the request **succeeds** (2xx), the response is stored for **1 hour**
3. If you send the same key again to the **same endpoint**, the API returns the stored response with an `Idempotency-Replayed: true` header — the operation is not re-executed
4. If the request **fails** (4xx/5xx), the key is **not consumed** — you can retry with the same key until the request succeeds

### Example

```bash theme={null}
# First request — executes the operation
curl -X POST "https://api.withallo.com/v2/api/conversations/items/cll-abc123/tags" \
  -H "Authorization: Api-Key ak_live_your_key" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{"tags": ["qualified"]}'
# → 200 OK, Idempotency-Key: 550e8400-...

# Retry — returns stored response without re-executing
curl -X POST "https://api.withallo.com/v2/api/conversations/items/cll-abc123/tags" \
  -H "Authorization: Api-Key ak_live_your_key" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{"tags": ["qualified"]}'
# → 200 OK, Idempotency-Replayed: true
```

### Key reuse across endpoints

Using the same idempotency key for a different endpoint or HTTP method returns a `409` error with code `IDEMPOTENCY_KEY_REUSE`.

### Response headers

| Header                 | Description                                            |
| ---------------------- | ------------------------------------------------------ |
| `Idempotency-Key`      | Echoed back on all requests that include the header    |
| `Idempotency-Replayed` | Set to `true` when the response is replayed from cache |

## Error code reference

See the [Error codes catalog](/en/v2/api-reference/guides/error-codes) for a complete list of all error codes with recovery instructions.
