# A2P Messaging API errors

The A2P Messaging HTTP API uses standard HTTP status codes. This page lists the ones you will encounter, what they mean and whether a retry is safe.

**Language:** en
**Audience:** developer
**TLDR:** Branch on the HTTP status, not on the message text: most error bodies are JSON with error.message and error.code, but the 429 body is plain text. 400, 401, 402 (out of balance), 403, 404, 413 and 422 (a field fails validation: an unregistered sender on `from`, a destination country that is not allowed on `to`) mean the request or the account needs fixing and retrying won't help; retry only 429 and 5xx, with exponential backoff starting at 1 second.
**Docs index (every page):** https://docs.instasent.com/llms.txt
**This zone's index:** https://docs.instasent.com/a2p-messaging-api/llms-full.txt
**This page:** https://docs.instasent.com/a2p-messaging-api/http/errors/ (HTML) · https://docs.instasent.com/a2p-messaging-api/http/errors.md (Markdown)

Every response carries a meaningful HTTP status code. A `2xx` means the request was accepted; anything else signals a problem your code should handle explicitly. Most error bodies are JSON with an `error` object that carries a human-readable `message` and the numeric `code`; the exception is `429`, whose body is plain text. Branch your code on the HTTP status, not on the `message` text, which is written for people and can change.

## Status codes

### `400 Bad Request`

The request body is malformed or has the wrong shape. Not retryable — fix the payload first.

```http
HTTP/1.1 400 Bad Request
```

When the body is not valid JSON:

```json
{ "error": { "message": "Invalid JSON", "code": 400 } }
```

When the body of `POST /sms/bulk` is not a JSON array of objects (for example, a single object):

```json
{ "error": { "message": "Body should be a JSON array of objects", "code": 400 } }
```

`GET /sms/metrics` also returns `400` when its query parameters are missing or malformed, or ask for a wider window than allowed. See [SMS traffic metrics](/a2p-messaging-api/http/metrics#errors-and-limits).

### `401 Unauthorized`

The token is missing or does not exist (mistyped, rotated or deleted), or the request comes from an IP address outside the token's accepted IPs. Not retryable as is: check the token and the network you call from, and see the [Authentication](/a2p-messaging-api/http/authentication) guide.

```http
HTTP/1.1 401 Unauthorized
```

```json
{ "error": { "message": "No token could be found.", "code": 401 } }
```

### `402 Payment Required`

The account has run out of balance. Not retryable until funds are topped up in the dashboard.

```http
HTTP/1.1 402 Payment Required
```

### `403 Forbidden`

The token exists but cannot be used for this request: it is disabled, the user or account is not enabled or is pending verification, or it is not an A2P Messaging API token (`api_sms`) with HTTP access. `GET /sms/{id}` also returns `403` when the message belongs to another account. Not retryable until the cause is fixed. The `message` differs from one cause to another, so branch on the `403` status rather than parsing the text.

```http
HTTP/1.1 403 Forbidden
```

### `404 Not Found`

The resource (message id, token id, project) does not exist or is not visible to the current token. `GET /sms/metrics` returns it when the account has no A2P Messaging API project.

```http
HTTP/1.1 404 Not Found
```

### `413 Request Too Large`

The request body exceeds the maximum accepted size. Not retryable — trim the payload.

```http
HTTP/1.1 413 Request Too Large
```

### `422 Unprocessable Entity`

The request is well formed but a field fails validation. The body is a JSON object with the messages per field under `errors.fields` — for instance `errors.fields.from` or `errors.fields.to`, each an array of strings. Nothing is sent and nothing is charged. Not retryable as is: fix the field. The cases you are most likely to meet:

- **Sender not registered** — error on `from`: *"The sender is not registered in this project, register it before sending"*. Every message needs a [sender registered in your account](/a2p-messaging-api/channels/sms/senders), unless the account has the [wildcard route](/a2p-messaging-api/channels/sms/wildcard-route) for wholesale providers. A `sender` id that doesn't exist also returns `422`.
- **Destination not allowed** — error on `to`: *"The destination country is not allowed by the project settings"*. The country is outside your project's allowed list or in its blocked list; see [Destination countries](/a2p-messaging-api/channels/sms/destination-countries).
- **Field validation** — a missing or malformed field, such as a `to` that isn't a valid number or a `from` outside its length limits. The field named in `errors.fields` is the one to fix.

On `POST /sms/bulk` these are reported per item in `errors`, and the rest of the batch is sent — except a `sender` id that doesn't exist, which refuses the whole call with `422`. See [Bulk sending](/a2p-messaging-api/http/bulk).

```http
HTTP/1.1 422 Unprocessable Entity
```

### `429 Too Many Requests`

You hit the per-endpoint rate limit. The body is the plain text `You exceeded the rate limit`, not JSON, so do not try to parse it. The `X-RateLimit-Reset` header says when to retry. See [Rate limits](/a2p-messaging-api/http/rate-limits).

```http
HTTP/1.1 429 Too Many Requests

You exceeded the rate limit
```

### `500 Internal Server Error`

Something broke on our side. Retry with exponential backoff; if the failure persists, contact support with the request id.

```http
HTTP/1.1 500 Internal Server Error
```

## Retry policy

> **Tip**: Retry `429` and `5xx` with exponential backoff, starting at 1 s and capping at a minute or so. Everything in the `4xx` range other than `429` means the request itself is wrong — retrying will not help.

## What's next

- **[Receiving DLRs](/a2p-messaging-api/http/dlrs)** — delivery reporting for messages that did leave the API successfully.
- **[API Reference](/a2p-messaging-api/http/reference)** — per-endpoint responses.

---

This is one page of the Instasent documentation. For the complete machine-readable index of every guide and API reference, fetch https://docs.instasent.com/llms.txt — start there for full context.
