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

# Errors

> Understand the structure and types of errors returned by the Chirp API

The Chirp API uses a consistent error format across all endpoints. Every error response follows the same structure, making it easy to handle errors programmatically regardless of which endpoint you are calling.

## The Error Object

When an API request fails, the response body contains an `error` object with the following structure:

```json icon="code" title="Error response" theme={null}
{
  "error": {
    "type": "provider_error",
    "code": "message_undeliverable",
    "message": "Unable to deliver message. The recipient may have blocked your number or is not available on WhatsApp.",
    "doc_url": "https://docs.buildwithchirp.com/api_reference/error-codes#message_undeliverable",
    "param": null,
    "provider": {
      "source": "meta",
      "code": 131026,
      "message": "Unable to deliver message",
      "fbtrace_id": "A9PT_GrZ5LIImkA8UdH--jZ"
    }
  }
}
```

### Attributes

| Attribute                | Type             | Always present | Description                                                                                                                                                                      |
| ------------------------ | ---------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`                   | string           | Yes            | The category of error. One of `invalid_request_error`, `authentication_error`, `provider_error`, or `api_error`.                                                                 |
| `message`                | string           | Yes            | A human-readable description of the error. Safe to display to end users.                                                                                                         |
| `code`                   | string           | No             | A machine-readable error code for programmatic handling. Only present for errors that benefit from branching logic. See [Error Codes](/api_reference/error-codes).               |
| `doc_url`                | string           | No             | A URL to the documentation page for this specific error code.                                                                                                                    |
| `param`                  | string           | No             | The request parameter that caused the error (e.g., `"from"`, `"to[0]"`). Present for validation errors.                                                                          |
| `provider`               | object           | No             | Upstream provider error details. Only present when the error originates from Meta or Telnyx.                                                                                     |
| `provider.source`        | string           | --             | The provider that returned the error: `"meta"` or `"telnyx"`.                                                                                                                    |
| `provider.code`          | number or string | --             | The provider's native error code.                                                                                                                                                |
| `provider.message`       | string           | --             | The provider's error message.                                                                                                                                                    |
| `provider.fbtrace_id`    | string           | --             | Meta's trace ID. Include this when contacting Meta support.                                                                                                                      |
| `provider.health_status` | object           | --             | Meta Health Status payload. Present when Chirp enriched the error via Meta's Health Status API (see [Health Status Enrichment](/whatsapp/error-codes#health-status-enrichment)). |
| `additional_info`        | string\[]        | No             | Human-readable remediation hints. Ordered: BLOCKED entities' suggested solutions first, then LIMITED entities' additional info. Populated alongside `provider.health_status`.    |

## Error Types

Every error has a `type` that tells you the category of the problem. The HTTP status code tells you the status; the `type` tells you *what kind of problem* occurred.

| Type                    | Description                                                                                              | Typical HTTP Codes |
| ----------------------- | -------------------------------------------------------------------------------------------------------- | ------------------ |
| `invalid_request_error` | The request has invalid parameters, missing fields, or bad formatting.                                   | 400, 404, 409      |
| `authentication_error`  | The API key is missing, invalid, or does not have the required permissions.                              | 401, 403           |
| `provider_error`        | Meta or Telnyx returned an error. The request was valid, but the operation failed at the provider level. | 402, 424           |
| `api_error`             | Something went wrong on Chirp's end. These are rare and typically transient.                             | 500, 502, 503      |

### invalid\_request\_error

Returned when the request itself is malformed or references something that does not exist. Check the `param` field to identify which parameter caused the issue.

```json icon="code" title="Validation error" theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "message": "The \"from\" field is required.",
    "param": "from"
  }
}
```

```json icon="code" title="Invalid phone number" theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_phone_number",
    "message": "The phone number \"+1abc\" is not in E.164 format. Expected format: +[country code][number].",
    "param": "from",
    "doc_url": "https://docs.buildwithchirp.com/api_reference/error-codes#invalid_phone_number"
  }
}
```

### authentication\_error

Returned when there is a problem with the API key. No `code` is needed because the `type` and HTTP status are sufficient.

```json icon="code" title="Authentication error" theme={null}
{
  "error": {
    "type": "authentication_error",
    "message": "Missing Authorization header. Expected: Bearer <api_key>"
  }
}
```

### provider\_error

Returned when the request was valid but the operation failed at Meta or Telnyx. The `provider` object contains the raw error from the upstream API. This is the most common error type when sending messages.

```json icon="code" title="Provider error" theme={null}
{
  "error": {
    "type": "provider_error",
    "code": "conversation_window_expired",
    "message": "More than 24 hours since the recipient last replied. Send a template message to re-open the conversation.",
    "doc_url": "https://docs.buildwithchirp.com/api_reference/error-codes#conversation_window_expired",
    "provider": {
      "source": "meta",
      "code": 131047,
      "message": "Re-engagement message",
      "fbtrace_id": "BxYZ_abc123def456"
    }
  }
}
```

### api\_error

Returned when something goes wrong on Chirp's end. These errors are rare and typically resolve on their own. Safe to retry with exponential backoff.

```json icon="code" title="API error" theme={null}
{
  "error": {
    "type": "api_error",
    "message": "An unexpected error occurred. Please try again later."
  }
}
```

## HTTP Status Codes

The Chirp API uses specific HTTP status codes to indicate the nature of the error:

| Code | Name              | Description                                                                              |
| ---- | ----------------- | ---------------------------------------------------------------------------------------- |
| 200  | OK                | The request succeeded.                                                                   |
| 201  | Created           | A new resource was created.                                                              |
| 400  | Bad Request       | Invalid parameters, missing fields, or bad formatting.                                   |
| 401  | Unauthorized      | No valid API key was provided.                                                           |
| 402  | Request Failed    | The request was valid, but the operation failed (e.g., message could not be delivered).  |
| 403  | Forbidden         | The API key does not have the required permissions.                                      |
| 404  | Not Found         | The requested resource does not exist.                                                   |
| 409  | Conflict          | The request conflicts with the current state (e.g., duplicate resource).                 |
| 424  | Failed Dependency | An external provider (Meta or Telnyx) is unavailable or returned an unrecoverable error. |
| 429  | Too Many Requests | Rate limit exceeded. See [Rate Limits](/api_reference/rate-limits).                      |
| 500  | Server Error      | Something went wrong on Chirp's end.                                                     |

<Info>
  **402 vs 400:** A `400` means your request was malformed. A `402` means your request was valid, but the operation failed downstream (e.g., the message could not be delivered). This distinction helps you separate input errors from delivery failures.
</Info>

<Info>
  **424 vs 500:** A `424` means an external provider (Meta or Telnyx) failed. A `500` means Chirp's own systems had an issue. This tells you whether the problem is on Chirp's side or the provider's side.
</Info>

## Provider Errors

When errors originate from Meta (WhatsApp) or Telnyx (SMS/MMS), the `provider` object contains the raw error details from the upstream API. Chirp maps these provider errors to standardized Chirp error codes so you can handle them consistently.

The `provider` object is useful for:

* **Debugging** -- The provider's native error code and message give you additional context.
* **Meta support tickets** -- Include the `fbtrace_id` when contacting Meta support about WhatsApp issues.
* **Detailed logging** -- Log the full provider object for your operations team.

For a complete mapping of provider error codes, see:

* [WhatsApp Error Codes](/whatsapp/error-codes) for Meta error code mappings
* [SMS Error Codes](/sms/error-codes) for Telnyx error code mappings

### Health Status Enrichment (WhatsApp)

For certain vague Meta errors — `account_restricted` and `display_name_not_approved` — Chirp automatically calls Meta's Health Status API and attaches the specific blocked entity and Meta's suggested remediation to the error response.

When enrichment runs, you get two extra fields:

* `additional_info` -- a flat `string[]` with Meta's `possible_solution` text, ordered with the most critical hints first.
* `provider.health_status` -- the full entity tree (phone number, WABA, business portfolio, app, template) with per-entity status and error details.

```json icon="code" title="Enriched account_restricted response" theme={null}
{
  "error": {
    "type": "provider_error",
    "code": "account_restricted",
    "message": "Account has been locked due to policy violation.",
    "doc_url": "https://docs.buildwithchirp.com/api_reference/error-codes#account_restricted",
    "additional_info": [
      "Appeal via Business Manager."
    ],
    "provider": {
      "source": "meta",
      "code": 131031,
      "message": "Account has been locked",
      "fbtrace_id": "BxYZ_abc123def456",
      "health_status": {
        "can_send_message": "BLOCKED",
        "entities": [
          {
            "entity_type": "PHONE_NUMBER",
            "id": "852850827913949",
            "can_send_message": "BLOCKED",
            "errors": [
              {
                "error_code": 131031,
                "error_description": "Account has been locked",
                "possible_solution": "Appeal via Business Manager."
              }
            ]
          },
          {
            "entity_type": "WABA",
            "id": "1472866130489042",
            "can_send_message": "AVAILABLE"
          }
        ]
      }
    }
  }
}
```

<Info>
  Enrichment is best-effort. If Chirp's follow-up call to Meta fails, you still get the base error — `additional_info` and `provider.health_status` will simply be absent. Never branch on whether they exist; treat them as hints on top of `error.code`.
</Info>

See [Health Status Enrichment](/whatsapp/error-codes#health-status-enrichment) in the WhatsApp error guide for the full list of enriched codes, entity types, and failure-webhook behavior.

## Next Steps

<CardGroup cols={2}>
  <Card title="Error Codes" icon="list" href="/api_reference/error-codes">
    Complete reference of all error codes with causes and solutions
  </Card>

  <Card title="Handling Errors" icon="code" href="/api_reference/handling-errors">
    Learn how to handle errors in your application
  </Card>
</CardGroup>
