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

# Error Codes

> Every error code the Public API can return, what each prefix means, and where the endpoint-specific codes are documented.

Every Public API failure shares one envelope and one machine-readable `code`. This page is the map of those codes: what each prefix means, the codes that can appear on any endpoint, and where the endpoint-specific ones are documented.

```json theme={null}
{
  "errors": {
    "code": "VAL_000",
    "group": "VALIDATION",
    "description": "Validation failed.",
    "fields": {
      "websites": { "code": "WA_VAL_001", "description": "Maximum 2 websites allowed.", "params": { "max": 2 } }
    }
  },
  "isSuccess": false
}
```

The full envelope — including `params` interpolation and the `fields` map — is described under [Error envelope](/public-api-reference/getting-started#error-envelope).

<Note>
  These are the Public API codes. The Messaging API (`api.gateway.connexease.com`) returns a separate set — `AUTH_*`, `BILL_*`, `RATE_*`, `GW_*`, `WH_*` — listed under [Error Codes](/api-reference/error-codes).
</Note>

***

## Reading a code

The prefix tells you where the failure happened and whether retrying can help.

| Prefix                  | Origin                                     | Typical HTTP | Retryable                |
| ----------------------- | ------------------------------------------ | ------------ | ------------------------ |
| `ORGANIZATION_SECRET_*` | Your secret key                            | 401          | No — fix the credential  |
| `APPLICATION_*`         | The `app_id` in the path                   | 404          | No — check the ID        |
| `REQ_*`                 | The request could not be read              | 400          | No — fix the payload     |
| `VAL_*`                 | Generic field validation                   | 422          | No — fix the field       |
| `WA_VAL_*` / `WA_TPL_*` | WhatsApp domain rules, checked locally     | 422          | No — fix the payload     |
| `META_*`                | Meta returned an error, or was unreachable | 4xx / 502    | Sometimes — see below    |
| `SYS_*`                 | Internal infrastructure                    | 500 / 502    | Yes — retry with backoff |

***

## Codes on every endpoint

### Auth and tenant

| HTTP | Code                      | Group       | When                                          |
| ---- | ------------------------- | ----------- | --------------------------------------------- |
| 401  | `ORGANIZATION_SECRET_010` | `NOT_FOUND` | Secret key is missing.                        |
| 401  | `ORGANIZATION_SECRET_011` | `NOT_FOUND` | Secret key is invalid.                        |
| 404  | `APPLICATION_004`         | `NOT_FOUND` | `app_id` does not belong to the organization. |

<Note>
  An `app_id` that belongs to another organization returns `404`, never `403` — the API does not confirm that the application exists elsewhere.
</Note>

### Request level

| HTTP | Code      | Group        | When                                                                 |
| ---- | --------- | ------------ | -------------------------------------------------------------------- |
| 400  | `REQ_001` | `VALIDATION` | Missing required field, unparseable number or UUID, or invalid JSON. |

`REQ_001` carries no `fields` map: the request could not be read well enough to validate it. The exception is a missing field that has its own error code — that is reported as a normal `422` field error instead.

### Generic validation

These appear inside `errors.fields[...].code` for standard constraint failures, under a top-level `VAL_000`. Endpoint pages list only their own domain-specific codes.

| Code      | Meaning                                                          |
| --------- | ---------------------------------------------------------------- |
| `VAL_000` | Validation failed (the top-level code of any `fields` response). |
| `VAL_001` | This field is required.                                          |
| `VAL_002` | Invalid value.                                                   |
| `VAL_003` | Must be at least `{{min}}` characters.                           |
| `VAL_004` | Must be at most `{{max}}` characters.                            |
| `VAL_005` | Must have at least `{{min}}` items.                              |
| `VAL_006` | Must have at most `{{max}}` items.                               |
| `VAL_007` | Must be greater than `{{limit}}`.                                |
| `VAL_008` | Must be greater than or equal to `{{limit}}`.                    |
| `VAL_009` | Must be less than `{{limit}}`.                                   |
| `VAL_010` | Must be less than or equal to `{{limit}}`.                       |
| `VAL_011` | Invalid type; expected `{{expected}}`.                           |
| `VAL_012` | Invalid choice (not a member of the enum).                       |
| `VAL_013` | Invalid date/time format.                                        |
| `VAL_014` | Value could not be parsed.                                       |
| `VAL_015` | Invalid JSON.                                                    |
| `VAL_016` | Invalid UUID format.                                             |
| `VAL_018` | Date must be in the future.                                      |
| `VAL_019` | `endDate` must be after `startDate`.                             |

### System

| HTTP      | Code      | Group    | When                                                                               |
| --------- | --------- | -------- | ---------------------------------------------------------------------------------- |
| 500 / 502 | `SYS_001` | `SYSTEM` | Unexpected infrastructure error (for example, the analytics store is unreachable). |

Retry `SYS_001` with exponential backoff. If it persists, contact support with the timestamp of the request.

***

## Domain validation codes

Checked locally, before the request reaches Meta. Every one returns `422` with group `VALIDATION`, and the payload is never forwarded — so fixing the request is always the right response.

| Area                    | Codes                                  | Documented on                                                                                             |
| ----------------------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| Template buttons        | `WA_TPL_001`–`005`, `WA_TPL_015`–`020` | [Create Template](/public-api-reference/template/create-template#request-validation-before-reaching-meta) |
| Template header         | `WA_TPL_006`–`010`, `WA_TPL_021`       | [Create Template](/public-api-reference/template/create-template#request-validation-before-reaching-meta) |
| Template body           | `WA_TPL_011`–`014`                     | [Create Template](/public-api-reference/template/create-template#request-validation-before-reaching-meta) |
| Template category / TTL | `WA_TPL_022`–`033`                     | [Create Template](/public-api-reference/template/create-template#request-validation-before-reaching-meta) |
| Template name format    | `WA_TPL_034`                           | [Create Template](/public-api-reference/template/create-template#request-validation-before-reaching-meta) |
| Template carousel       | `WA_TPL_035`+                          | [Create Template](/public-api-reference/template/create-template)                                         |
| Business profile fields | `WA_VAL_001`+                          | [Update Business Profile](/public-api-reference/application/update-business-profile#errors)               |
| Media upload            | `WA_VAL_002`–`004`                     | [Upload Media](/public-api-reference/media/upload-media#errors)                                           |

The same button, header, and body rules apply to [Update Template](/public-api-reference/template/update-template) — it validates against the identical rule set.

***

## Meta upstream codes

`META_*` codes mean the request passed local validation and the Gateway called Meta on your behalf. What you do next depends on the HTTP status, not the code number:

* **4xx** — Meta rejected the request. The `description` carries Meta's own message. Fix the payload or the account state; retrying the identical request will fail again.
* **502** — Meta was unreachable, returned an unexpected shape, or answered `success: false`. Retry with backoff.

Each code is documented on the endpoint that can return it, with the Meta condition it maps to:

| Operation               | Codes                                                      | Documented on                                                                               |
| ----------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| Get Business Profile    | `META_001`, `META_030`–`033`                               | [Get Business Profile](/public-api-reference/application/get-business-profile#errors)       |
| Update Business Profile | `META_002`, `META_030`–`033`                               | [Update Business Profile](/public-api-reference/application/update-business-profile#errors) |
| Create Template         | `META_003`, `META_017`–`029`                               | [Create Template](/public-api-reference/template/create-template#errors)                    |
| Update Template         | `META_004`, `META_017`, `META_022`–`029`, `META_091`–`097` | [Update Template](/public-api-reference/template/update-template#errors)                    |
| Get Templates           | `META_004`, `META_034`–`037`                               | [Get Templates](/public-api-reference/template/get-templates#errors)                        |
| Get Template Detail     | `META_004`, `META_034`–`036`, `META_075`                   | [Get Template Detail](/public-api-reference/template/get-template-detail#errors)            |
| Delete Template         | `META_004`, `META_034`–`037`, `META_075`                   | [Delete Template](/public-api-reference/template/delete-template#errors)                    |
| Get Template Metrics    | `META_098`–`107`                                           | [Get Template Metrics](/public-api-reference/template/get-template-metrics#errors)          |
| Upload Media            | `META_015`, `META_016`, `META_068`–`073`                   | [Upload Media](/public-api-reference/media/upload-media#errors)                             |

<Warning>
  Do not branch your code on the numeric part of a `META_*` code alone. The same Meta condition can surface under different numbers on different operations — switch on the HTTP status first, then on the specific code for the endpoint you called.
</Warning>

***

## Handling in practice

| HTTP | What it means                           | What to do                                                                 |
| ---- | --------------------------------------- | -------------------------------------------------------------------------- |
| 400  | The request could not be read.          | Fix the payload. Never retry unchanged.                                    |
| 401  | Credential missing or invalid.          | Check the `Authorization` header and the key itself.                       |
| 404  | The `app_id` is not yours.              | Verify the application belongs to the organization behind your secret key. |
| 422  | A field or domain rule failed.          | Read `errors.fields` — it names each offending field and why.              |
| 4xx  | Meta rejected the call (`META_*`).      | Read `description`; fix the payload or account state.                      |
| 502  | Meta or infrastructure was unreachable. | Retry with exponential backoff.                                            |
| 500  | Unexpected internal error (`SYS_001`).  | Retry with backoff; contact support if it persists.                        |
