# Error Message Catalog

All error messages returned by the Mobile Text Alerts API follow a consistent JSON structure. This page gives examples of error responses, the specific scenarios that can trigger each error, and how to resolve them.

## Error Body Structure

All error responses use `Content-Type: application/json` and contain the following fields:

**Error body structure:** `{ httpCode, message, timestamp, type, name, requestId }`

<table><thead><tr><th width="127">Field</th><th width="163">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>httpCode</code></td><td><code>number</code></td><td>The <a href="/pages/QD3TvDH56e5gMyqhu9Tq#http-status-codes">HTTP status code</a> of the request (e.g. <code>400</code>, <code>429</code>).</td></tr><tr><td><code>message</code></td><td><code>string</code></td><td>A human-readable description of the specific error.</td></tr><tr><td><code>timestamp</code></td><td><code>string</code> (ISO 8601)</td><td><p>This is an ISO 8601-formatted string. This may include an offset timestamp, which indicates how far the local time is from UTC.</p><p>Example: <code>"2026-05-01T13:43:09-05:00"</code></p></td></tr><tr><td><code>type</code></td><td><code>string</code> (enum)</td><td>Machine-readable error category.</td></tr><tr><td><code>name</code></td><td><code>string</code> (enum)</td><td>Exception class name.</td></tr><tr><td><code>requestId</code></td><td><code>string</code> (UUID)</td><td>A unique identifier for each request. Include this when contacting support.</td></tr></tbody></table>

**Note:** `403` errors may also include a `reason` field. It adds context about why access was denied, such as the account restriction type. This field may be `null`.

### Rate limit response headers <a href="#response-headers" id="response-headers"></a>

All API responses include [response headers](/api-basics/request-response-headers.md#response-headers) to provide information about your account's [rate limit](/api-basics/rate-limits.md) usage.

## Error HTTP status code examples

### 400 — Bad Request

This indicates the request was malformed or is missing a required field. The `message` field will describe the specific problem.

#### Missing Required Field

The [`/send` endpoint](/api-reference/send.md#post-send) requires at least one content field: `message`, `image`, or `templateId`.

**Example: `POST /send`** The following response is returned when the `message` field is omitted.

```json
{
    "httpCode":400,
    "message":"message, image, or templateId required",
    "timestamp":"2026-05-01T13:43:09-05:00",
    "type":"invalid_field_error",
    "name":"MTAInvalidFieldError",
    "requestId":"bb31b127-b4e5-44e5-a4af-daa57a52ad4a"
}
```

**Fix:** Include at least one content field — `message`, `image`, or `templateId`.

#### Character Limit Exceeded

The message you are trying to send is too long and exceeds the character limit. SMS messages are limited to 160 characters while MMS can be longer.

**Example: `POST /send`** The following response is returned when the `message` field contains too many characters.

```json
{
    "httpCode":400,
    "message":"Messages cannot be longer than 2000 characters.",
    "timestamp":"2026-05-01T13:35:10-05:00",
    "type":"invalid_field_error",
    "name":"MTAInvalidFieldError",
    "requestId":"b76efd2c-81b8-4ebf-ad14-06ac1e38640a"
    }     
```

**Fix:** Shorten your message content.

#### Template requires `linkId`

When using a `templateId` that corresponds to a template containing a link, you must also provide a `linkId`.

**Example: `POST /send`** The following response is returned when the request includes a `templateId` for a template that contains a link.

```json
{
  "httpCode":  400,
  "message": "linkId is required when using a template that contains a link.",
  "timestamp": "2026-05-01T13:43:09-05:00",
  "type":"invalid_field_error",
  "name":"MTAInvalidFieldError",
  "requestId": "123e4567-e89b-12d3-a456-426614174000"
}
```

**Fix:** Add the `linkId` for the link defined in your controlled template. You can retrieve available links via the [Links endpoints](/api-reference/links.md).

#### Invalid recipient

Phone numbers in the `subscribers` field that cannot be parsed as valid numbers will be flagged as invalid.

**Example: `POST /send`** The following response is returned when the `subscribers` field contains an invalid number.

```json
{
    "httpCode":400,
    "message":"Given number 1122333 is not valid.",
    "timestamp":"2026-05-01T14:04:28-05:00",
    "type":"invalid_field_error",
    "name":"MTAInvalidFieldError",
    "requestId":"8ab24cc7-9949-440e-bfed-d8be3b0173f4"
}
```

**Fix:** Use [`/send/validate-recipients`](/api-reference/send.md#post-send-validate-recipients) to return invalid numbers in the `invalidRecipients` array instead of triggering a top-level `400`. This lets you filter them before sending.

#### Duplicate Subscriber

{% hint style="warning" %}
If you add a subscriber that already exists on your account, that subscriber is updated and no error message is shown.
{% endhint %}

**Example:** A subscriber is added in a `POST` request to the [/subscribers](/api-reference/subscribers.md#post-subscribers) endpoint, but a subscriber with this number already exists.

**Request:**

```bash
curl --location --request POST 'https://api.platform.com/v3/subscribers' \
  --header 'Authorization: Bearer <APIKey>' \
  --header 'Content-Type: application/json' \
  --data '{"firstName": "FirstName","lastName": "LastName","number": "+18002223333","email": "example@mobile-text-alerts.com"}'
```

**Response:** The API does **not** return an error. It returns an update for that subscriber.

```json
{"message":"Subscriber updated successfully.",
    "data":{
        "id":111713494,
        "firstName":"FirstName",
        "lastName":"LastName",
        "email":"example@mobile-text-alerts.com",
        "number":8002223333,"e164Number":"+18002223333",
        "date":"2026-04-13T15:32:32.000Z",
        "countryId":209,
        "groups":[],
        "subscriberFieldData":[],
        "signupMethod":5,
        "longNumber":8002223333,
        "carrierId":41
    }
}
```

### 401 — Unauthorized

A 401 response indicates a request did not include a [valid API key](/getting-started/get-an-api-key.md), or the key has been revoked. The API uses Bearer token authentication — every request must include a valid `Authorization` header.

#### Missing Authorization Header

**Example: `POST /send`** The following response is returned when the Authorization header is missing:

```json
{   "httpCode":401,
    "message":"Unauthorized [AUTH-GLOBAL-001]",
    "timestamp":"2026-05-14T14:43:45-05:00",
    "type":"unauthorized_error",
    "name":"MTAUnauthorizedError",
    "requestId":"2742fa1c-0580-4609-9b82-8c6af6a601b4"
}
```

**Fix:** Include your account API key in the `Authorization` header. For example: `--header 'Authorization: Bearer 3099eebf-7661-5458-930e-65cd058a0b03'`. See [Get an API Key](/getting-started/get-an-api-key.md) to learn more.

#### Invalid, malformed, or expired API key

**Example: `POST /send`** The following response is returned when the Authorization header contains an invalid API key:

```json
{   "httpCode":401,
    "message":"Unauthorized [AUTH-GLOBAL-001]",
    "timestamp":"2026-05-14T14:43:45-05:00",
    "type":"unauthorized_error",
    "name":"MTAUnauthorizedError",
    "requestId":"2742fa1c-0580-4609-9b82-8c6af6a601b4"
}
```

**Fix:** Make sure the API key you are using matches the key shown in the dashboard. See [Get an API Key](/getting-started/get-an-api-key.md) to learn more.

### 403 — Forbidden

For this type of error, the API key is valid, but your account does not have permission to perform the requested action.

Possible reasons your account may be restricted from certain actions:

* Your account is suspended or restricted.
* You have a trial account and are attempting a non-template message send.
* You are trying to use a feature that is not enabled for your account, such as iMessage sending.
* The payment method on your account has expired or been declined.

The optional `reason` field provides additional context for some responses:

<table><thead><tr><th width="251">Reason value</th><th>Cause</th></tr></thead><tbody><tr><td><code>EXPIRED_TRIAL_ACCOUNT</code></td><td>The trial period has ended for your account.</td></tr><tr><td><code>DISABLED_ACCOUNT</code></td><td>The account has been disabled. Contact support to learn more.</td></tr><tr><td><code>PAUSED_ACCOUNT</code></td><td>Your account's subscription has been paused.</td></tr><tr><td><code>CANCELED_ACCOUNT</code></td><td>Your account's subscription has been canceled.</td></tr><tr><td><code>DECLINED_CARD</code></td><td>The payment method on your account has been declined.</td></tr><tr><td><code>EXPIRED_CARD</code></td><td>The payment method on your account has expired.</td></tr></tbody></table>

**Fix:** If you are having account issues, [contact support](https://mobile-text-alerts.deskpro.com/new-ticket) to ensure your account is enabled for the features you need.

### 409 — Conflict

This type of error is returned when a duplicate request is detected. The `/send` endpoint supports idempotency via an `X-Request-Id` header.

**Example: `POST /send`** The following response is returned for a repeat request. It confirms that the original request succeeded.

```json
{
  "httpCode":  409,
  "message":   "Duplicate request detected. The request with this X-Request-Id has already been processed.",
  "timestamp": "2026-03-04T19:24:00.365Z",
  "type":      "conflict_error",
  "name":      "MTAConflictError",
  "requestId": "123e4567-e89b-12d3-a456-426614174000"
}
```

**Fix:** Include a unique `X-Request-Id` header on each `/send` call. If a network error leaves you unsure whether the request succeeded, you can safely re-send with the same `X-Request-Id`. The API will either confirm the original succeeded (`409`) or process as a new request.

### 429 — Rate Limit Exceeded

This type of error indicates too many requests were made within the allowed time window. Rate limits vary by endpoint. See [Rate Limits](/api-basics/rate-limits.md) to learn more about specific endpoint limits.

**Example: `POST /send`** The following response is returned when you exceed the rate limit of 25 requests every 15 seconds for message sends.

```json
{
  "httpCode":  429,
  "message":   "Too many requests. You have exceeded the rate limit for this endpoint. Please wait before retrying.",
  "timestamp": "2026-04-04T19:24:00.365Z",
  "type":      "rate_limit_error",
  "name":      "MTARateLimitError",
  "requestId": "123e4567-e89b-12d3-a456-426614174000"
}
```

**Fix:** You can track your rate limit usage in the `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` [response headers](/api-basics/request-response-headers.md#response-headers).

For large-scale subscriber changes, the [Bulk Create/Update Subscribers](/tutorials/manage-subscribers/bulk-create-update-subscribers.md) endpoints are recommended.

### 500 — Internal Server Error

This error type is returned when an unexpected error occurs on the server. It is not caused by your request.

**Example:**

```json
{
  "httpCode":  500,
  "message":   "An unexpected server error occurred. Please try again or contact support if this persists.",
  "timestamp": "2025-03-04T19:24:00.365Z",
  "type":      "internal_server_error",
  "name":      "MTAInternalServerError",
  "requestId": "123e4567-e89b-12d3-a456-426614174000"
}
```

**Fix:** If you receive a `500`, retry after a short delay. If the error persists, [contact support](https://mobile-text-alerts.deskpro.com/new-ticket) and include the following details:

* Request URL
* Request headers and body
* Request ID


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developers.mobile-text-alerts.com/api-basics/error-response-codes/error-message-catalog.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
