---
title: Errors | API Docs
description: Handle the WhatsApp API error envelope and its numeric codes safely.
---

Every failure uses the same envelope:

```
{
  "success": false,
  "error": {
    "status": 422,
    "code": 1001,
    "message": "Field required.",
    "doc_url": "https://docs.linqapp.com/channel/whatsapp/error/codes/1xxx/1001/",
    "param": "/parts/0/body",
    "details": [
      { "code": "field_required", "param": "/parts/0/body", "message": "Body is required." }
    ]
  },
  "request_id": "req_…"
}
```

`error.status` is the HTTP status the response was written with, `error.code` is a number, and `error.message` is for a human reading a log — it may be reworded at any time, so never match on it. Every code has a page in the [error code reference](/channel/whatsapp/error/index.md), which also carries the complete tables.

## Branch on the code, fall back to the range

Codes are allocated into five ranges. The range says what kind of failure it is; together with `error.status` it says whether the request or the service was at fault.

| Range                                                                               | Category                              | Retry?                                                       |
| ----------------------------------------------------------------------------------- | ------------------------------------- | ------------------------------------------------------------ |
| [1xxx](/channel/whatsapp/error#1xxx--request-errors/index.md)                       | Request errors                        | No — correct the request first                               |
| [2xxx](/channel/whatsapp/error#2xxx--resource-permission-and-state-errors/index.md) | Resource, permission and state errors | No — inspect or reconcile that state                         |
| [3xxx](/channel/whatsapp/error#3xxx--service-errors/index.md)                       | Service errors                        | Yes — bounded backoff, unless the code’s page says otherwise |
| [4xxx](/channel/whatsapp/error#4xxx--operational-and-send-refusals/index.md)        | Operational and send refusals         | Sometimes — follow the code’s remedy                         |
| [5xxx](/channel/whatsapp/error#5xxx--attachment-and-file-errors/index.md)           | Attachment and file errors            | Sometimes — follow the code’s remedy                         |

The set of codes grows additively. Branch on the integers you know, and treat an integer you do not know by its range plus the HTTP status that came with it — a `3xxx` with a `503` is retryable, a `1xxx` with a `422` is not, and an integer outside every range is a generic failure. Do not model the codes as a closed enum. A number is never removed and never reassigned to a different failure: once it means something, it means that forever, so a branch you write today stays correct.

## Honor `retry_after`

When `error.retry_after` is present, it overrides the range guidance above: wait that many seconds, then retry. It appears exactly when the response also carries a `Retry-After` header, with the same value, so either source is safe to read. A `3xxx` with no `retry_after` is retried with bounded exponential backoff, starting at 1 second and capping at 30. Sends are idempotent on `Idempotency-Key`, so retrying a send that actually succeeded returns the original result rather than sending twice.

## Read the optional members

- `param` is present only when the response is about exactly one field and is that field’s JSON Pointer. A fault about the whole body points at the root, which is the empty string, so `param` may be present and empty.
- `details` lists every field-level finding on a validation failure. Each entry has a string `code`, a JSON Pointer `param` naming the most specific request location the API could identify, and a `message`. Validation rejects and points; it never coerces a value into something acceptable.
- `context` carries typed facts about the failure you may need to branch on, such as whether a customer window ever opened. Its members are documented on the codes that set them.
- `doc_url` is the absolute address of the code’s page in the [error code reference](/channel/whatsapp/error/index.md), present on every response whose code has a published page and absent for a code reachable only on a surface that has not been released yet; it is derived from the code alone, so link to it rather than building the address yourself.
- `trace_id` appears when a valid trace context exists.

None of these is guaranteed on every error.

## Log what support needs

Log the HTTP status, `request_id`, and `error.code`. Never log credentials or message content. Include `request_id` when contacting Linq support; it identifies the exact request in our logs.

These codes belong to WhatsApp. Every channel numbers its own errors, so the same integer means something different on another channel — branch on the code only in code paths you know are talking to this API, and follow the `doc_url` it gives you rather than one from another channel.
