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

# Error Codes

> Comprehensive reference for all error codes returned by the Trackly SMS v2 API

# Error Codes

All API errors follow a consistent JSON response format. When a request fails, the response body contains a structured error object that you can use for programmatic error handling.

## Error Response Format

All error responses are JSON objects. The `error` field is always present. Two additional fields may be present depending on the endpoint:

```json theme={null}
{
  "error": "Invalid credentials",
  "code": "invalid_credentials"
}
```

| Field     | Type   | Always present? | Description                                                                                                                                                                                                              |
| --------- | ------ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `error`   | string | Yes             | Human-readable description of the error.                                                                                                                                                                                 |
| `code`    | string | Mostly          | Machine-readable error code for programmatic handling. Present on virtually all v2 API errors, including the `403 Account is suspended` response; a few legacy paths may omit it, so defensively check for its presence. |
| `message` | string | Sometimes       | Optional supplementary detail. Some endpoints (notably v1 phone validation and a few v2 paths) include a third `message` field with additional context; most do not.                                                     |

<Note>
  Treat `error` as guaranteed and `code`/`message` as optional. Switch on `code` when present and fall back to the `error` text otherwise.
</Note>

***

## Authentication Errors (401)

Returned when the request is missing valid authentication credentials.

| Error Code            | Message                    | Description                                                                                                                          |
| --------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `invalid_credentials` | Missing or invalid API key | The `X-Api-Key` header is missing or invalid. Verify the key format (`trk_[32-char-alphanumeric]`) and that it has not been revoked. |

<Warning>
  API keys are sensitive credentials. Never expose them in client-side code, public repositories, or logs.
</Warning>

<Accordion title="Troubleshooting authentication errors">
  **Common Causes:**

  * API key was revoked or rotated in the dashboard
  * Key is being sent in the wrong header (must be `X-Api-Key`, not `Authorization`)
  * Extra whitespace or newline characters in the key value

  **Resolution:**

  1. Verify your key in **Dashboard > Settings > API Keys**
  2. Ensure the header is exactly `X-Api-Key: trk_...` with no extra spaces
  3. Generate a new key if the current one may be compromised
</Accordion>

### Example

```json theme={null}
{
  "error": "Invalid credentials",
  "code": "invalid_credentials"
}
```

***

## Validation Errors (400)

Returned when the request payload is malformed, missing required fields, or contains invalid values.

### General Validation

| Error Code         | Message              | Description                                                                 |
| ------------------ | -------------------- | --------------------------------------------------------------------------- |
| `not_found`        | Resource not found   | The referenced resource does not exist or is not accessible.                |
| `confirm_required` | confirm must be true | A destructive operation requires explicit confirmation via `confirm: true`. |

### Send / Message Validation

| Error Code                       | Message                                        | Description                                                                          |
| -------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------ |
| `missing_to`                     | to is required                                 | The `to` field (recipient phone number) was not provided.                            |
| `missing_list_number`            | list\_number is required                       | The `list_number` field (sending phone number) was not provided.                     |
| `missing_body`                   | body is required                               | The message `body` field was not provided.                                           |
| `invalid_phone`                  | Invalid recipient phone number format          | The `to` value is not a valid E.164 phone number (e.g. `+14155551234`).              |
| `invalid_phone`                  | Invalid E.164 phone number format              | A phone number field does not conform to E.164 format.                               |
| `invalid_list_number`            | Invalid list\_number E.164 format              | The `list_number` value is not a valid E.164 phone number.                           |
| `missing_from`                   | from is required                               | The sending number/list (`from`, `from_phone_number_id`) was not provided.           |
| `missing_to_number`              | to\_number is required                         | The `to_number` field was not provided on a raw send.                                |
| `missing_phones`                 | phones array is required and must be non-empty | The `phones` array (batch phone validation) was not provided or is empty.            |
| `invalid_force`                  | force must be a boolean                        | The `force` field was not a strict boolean (string `"true"` / int `1` are rejected). |
| `invalid_channel`                | channel must be one of: sms, voice, auto       | The OTP `channel` value is not one of the allowed options.                           |
| `missing_consent_method`         | consent\_method is required                    | TCPA consent method was not provided when adding/resubscribing a contact.            |
| `invalid_consent_method`         | Invalid consent\_method                        | Provided consent method is not one of the allowed values.                            |
| `verbal_not_valid_for_marketing` | Verbal consent not valid for marketing         | Verbal consent cannot be used to opt a contact into marketing messages.              |
| `missing_messages`               | messages array is required                     | The `messages` array was not provided in a bulk send request.                        |
| `list_not_found`                 | Sending list not found for this list\_number   | No sending list is associated with the provided `list_number`.                       |
| `webhook_not_configured`         | Webhook verification required before sending   | The BYOC list requires webhook verification before messages can be sent.             |

### Phone Number Validation

| Error Code             | Message                                | Description                                                                                                             |
| ---------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `missing_phone_number` | phone\_number is required              | The `phone_number` field was not provided.                                                                              |
| `missing_phone`        | phone number is required               | The `phone` field was not provided (single-number validation endpoint).                                                 |
| `phone_type_blocked`   | Phone type blocked by account settings | The recipient line type (e.g. VOIP, landline) is blocked by the account's OTP settings. Returned by OTP endpoints only. |

### Generic Input Validation

| Error Code             | Message                            | Description                                                                             |
| ---------------------- | ---------------------------------- | --------------------------------------------------------------------------------------- |
| `invalid_input`        | Invalid input                      | The request payload could not be parsed or contains invalid structure.                  |
| `missing_fields`       | Required fields missing            | One or more required fields are absent from the request.                                |
| `missing_id`           | id is required                     | A resource identifier was not provided.                                                 |
| `missing_url`          | url is required                    | A `url` field was not provided.                                                         |
| `missing_url_or_offer` | url or offer\_id is required       | Either a raw URL or an offer reference must be provided.                                |
| `invalid_url`          | Invalid URL                        | The URL is malformed or cannot be parsed.                                               |
| `invalid_url_scheme`   | URL scheme must be http or https   | The URL uses an unsupported scheme.                                                     |
| `unsafe_url`           | Unsafe URL                         | The URL points to a domain blocked by the carrier-safety list.                          |
| `url_too_long`         | URL exceeds maximum length         | The URL is longer than the per-endpoint maximum.                                        |
| `field_too_long`       | Field exceeds maximum length       | A string field exceeds its per-endpoint character cap.                                  |
| `too_long`             | Value too long                     | Generic length-cap violation.                                                           |
| `invalid_metadata`     | Invalid metadata                   | The `metadata` field is not a valid object.                                             |
| `metadata_too_large`   | Metadata exceeds maximum size      | The `metadata` payload exceeds the per-endpoint byte cap.                               |
| `invalid_ip_address`   | Invalid IP address                 | The `ip_address` field is not a valid IPv4 or IPv6 address.                             |
| `invalid_timestamp`    | Invalid timestamp                  | The timestamp value cannot be parsed.                                                   |
| `mutually_exclusive`   | Mutually exclusive fields provided | Two fields that may not coexist were both provided.                                     |
| `payload_too_large`    | Payload exceeds size limit         | The total request body exceeds the 5 MB limit.                                          |
| `required`             | Field is required                  | Generic required-field violation. The accompanying `error` text identifies which field. |
| `validation_failed`    | Validation failed                  | Generic validation rejection covering compound rules.                                   |

### Creative Validation

| Error Code                             | Message                                                   | Description                                                                                             |
| -------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `missing_name`                         | name is required                                          | The creative `name` field was not provided.                                                             |
| `missing_message`                      | message is required                                       | The creative `message` field was not provided.                                                          |
| `missing_offer_links`                  | offer\_links is required                                  | The `offer_links` array was not provided for a creative that uses link placeholders.                    |
| `name_too_long`                        | name must be 255 characters or less                       | The creative name exceeds the 255 character limit.                                                      |
| `message_too_long`                     | message must be 1600 characters or less                   | The creative message exceeds the 1600 character limit.                                                  |
| `invalid_status`                       | status must be one of: ...                                | The provided `status` value is not a valid option.                                                      |
| `invalid_creative_type`                | creative\_type must be one of: ...                        | The provided `creative_type` value is not a valid option.                                               |
| `missing_link_placeholder`             | message must contain at least one \{\{linkN}} placeholder | The creative message does not contain a required `{{linkN}}` placeholder.                               |
| `missing_offer_links_for_placeholders` | Missing offer\_links for placeholders: ...                | One or more `{{linkN}}` placeholders in the message do not have corresponding entries in `offer_links`. |
| `missing_offer_link_key`               | offer\_link key is required                               | An entry in the `offer_links` array is missing its `key` field.                                         |
| `missing_offer_link_offer_id`          | offer\_link offer\_id is required                         | An entry in the `offer_links` array is missing its `offer_id` field.                                    |
| `offer_not_found`                      | Offer not found: ...                                      | The referenced offer ID does not exist in your account.                                                 |

### Contact Validation

| Error Code         | Message                    | Description                                                      |
| ------------------ | -------------------------- | ---------------------------------------------------------------- |
| `missing_contacts` | contacts array is required | The `contacts` array was not provided in a bulk contact request. |
| `missing_records`  | records array is required  | The `records` array was not provided in a bulk import request.   |

### Audience Validation

| Error Code                       | Message                          | Description                                                                        |
| -------------------------------- | -------------------------------- | ---------------------------------------------------------------------------------- |
| `missing_filter`                 | filter is required               | The audience `filter` object was not provided.                                     |
| `missing_audiences`              | audiences is required            | The `audiences` array was not provided.                                            |
| `empty_filter_group`             | Filter group cannot be empty     | A filter group was provided with zero conditions.                                  |
| `invalid_condition_type`         | Invalid condition type           | The audience condition `type` is not a recognized value.                           |
| `invalid_audience_id`            | Invalid audience ID              | An audience ID could not be parsed or is not a valid ObjectId.                     |
| `invalid_time_field`             | Invalid time field               | The time-based filter references a field that does not exist or is not filterable. |
| `invalid_time_operator`          | Invalid time operator            | The time-based filter uses an operator that is not supported.                      |
| `invalid_time_unit`              | Invalid time unit                | The time-based filter uses an unsupported unit (allowed: hours, days, weeks).      |
| `missing_time_value`             | Time value is required           | A time-based filter is missing its numeric value.                                  |
| `invalid_count_field`            | Invalid count field              | The count-based filter references a non-countable field.                           |
| `invalid_count_operator`         | Invalid count operator           | The count-based filter uses an unsupported operator.                               |
| `missing_count_value`            | Count value is required          | The count-based filter is missing its numeric threshold.                           |
| `invalid_revenue_field`          | Invalid revenue field            | The revenue filter references a non-existent field.                                |
| `invalid_revenue_operator`       | Invalid revenue operator         | The revenue filter uses an unsupported operator.                                   |
| `missing_revenue_value`          | Revenue value is required        | The revenue filter is missing its numeric threshold.                               |
| `missing_revenue`                | revenue is required              | The `revenue` field was not provided on a record-revenue call.                     |
| `invalid_revenue`                | Invalid revenue                  | The `revenue` value is not a non-negative number.                                  |
| `invalid_carrier_operator`       | Invalid carrier operator         | The carrier filter uses an unsupported operator.                                   |
| `missing_carrier_value`          | Carrier value is required        | The carrier filter is missing its target value.                                    |
| `invalid_phone_numbers_operator` | Invalid phone\_numbers operator  | The phone-numbers filter uses an unsupported operator.                             |
| `missing_phone_numbers_value`    | phone\_numbers value is required | The phone-numbers filter is missing its array of values.                           |
| `invalid_timezone_operator`      | Invalid timezone operator        | The timezone filter uses an unsupported operator.                                  |
| `missing_timezone_value`         | Timezone value is required       | The timezone filter is missing its target value.                                   |
| `invalid_custom_field_operator`  | Invalid custom field operator    | A custom-field filter uses an unsupported operator.                                |
| `missing_custom_field_name`      | custom field name is required    | A custom-field filter is missing its `name`.                                       |
| `missing_custom_field_value`     | custom field value is required   | A custom-field filter is missing its `value`.                                      |
| `missing_custom_fields`          | custom\_fields are required      | The `custom_fields` object is required for this operation.                         |
| `invalid_custom_fields`          | Invalid custom\_fields           | The `custom_fields` payload could not be parsed.                                   |
| `invalid_group_operator`         | Invalid group operator           | A filter group uses an unsupported logical operator (allowed: AND, OR).            |
| `invalid_entities`               | Invalid entities                 | The `entities` array contains values that aren't recognized.                       |
| `missing_entities`               | entities is required             | The `entities` array was not provided to history/clear.                            |
| `invalid_events`                 | Invalid events                   | The `events` array contains unrecognized event names.                              |

### Schedule Validation

| Error Code              | Message                                   | Description                                                            |
| ----------------------- | ----------------------------------------- | ---------------------------------------------------------------------- |
| `missing_send_type`     | send\_type is required                    | The `send_type` field was not provided.                                |
| `invalid_send_type`     | Invalid send\_type                        | The `send_type` value is not one of the allowed options.               |
| `missing_send_date`     | send\_date is required                    | One-time schedule is missing its `send_date`.                          |
| `missing_send_time`     | send\_time is required                    | The `send_time` (HH:MM) was not provided.                              |
| `missing_start_date`    | start\_date is required                   | A repeating schedule is missing its `start_date`.                      |
| `missing_end_date`      | end\_date is required                     | A repeating schedule is missing its `end_date`.                        |
| `missing_is_repeating`  | is\_repeating is required                 | The `is_repeating` boolean was not provided.                           |
| `no_days_selected`      | At least one day of week must be selected | A repeating weekly schedule has no `days_of_week` enabled.             |
| `missing_blasts`        | blasts is required                        | A blast schedule is missing its `blasts` array.                        |
| `missing_blast_message` | Each blast must have a message            | A blast variant is missing its `message`.                              |
| `invalid_blast_percent` | Invalid blast percent                     | A blast variant's `percent` is invalid or the totals don't sum to 100. |
| `schedule_complete`     | Schedule is already complete              | Operation cannot be performed on a schedule that has finished.         |
| `source_list_not_found` | Source list not found                     | A `source_lists` ID does not match any list on the account.            |

### Offer / Partnership Offer Validation

| Error Code                    | Message                               | Description                                                      |
| ----------------------------- | ------------------------------------- | ---------------------------------------------------------------- |
| `missing_offer_id`            | offer\_id is required                 | The `offer_id` field was not provided.                           |
| `invalid_offer_id`            | Invalid offer\_id                     | The offer ID could not be parsed.                                |
| `invalid_offer_link_offer_id` | Invalid offer\_link offer\_id         | An entry in `offer_links` references an invalid offer ID.        |
| `invalid_offer_links`         | Invalid offer\_links                  | The `offer_links` array is malformed.                            |
| `invalid_payout_type`         | payout\_type must be one of: cpa, cpc | The `payout_type` value is not a recognized option.              |
| `missing_attribution_type`    | attribution\_type is required         | The revenue `attribution_type` was not provided.                 |
| `invalid_attribution_type`    | Invalid attribution\_type             | The revenue `attribution_type` is not a recognized option.       |
| `invalid_external_platform`   | Invalid external\_platform            | The `external_platform` value is not one of the allowed options. |

### List / Contact / Resource Errors

| Error Code                | Message                              | Description                                                        |
| ------------------------- | ------------------------------------ | ------------------------------------------------------------------ |
| `contact_not_found`       | Contact not found                    | The contact does not exist for this account.                       |
| `list_contact_not_found`  | List contact not found               | The contact is not subscribed to the specified list.               |
| `message_not_found`       | Message not found                    | The message ID does not match any message on the account.          |
| `missing_message_id`      | message\_id is required              | The `message_id` field was not provided.                           |
| `missing_list_identifier` | list\_id or list\_number is required | Neither `list_id` nor `list_number` was provided.                  |
| `missing_tracking_url`    | tracking\_url is required            | The offer's `tracking_url` was not provided.                       |
| `missing_timestamp`       | timestamp is required                | The `timestamp` field was not provided.                            |
| `id_collision`            | ID collision                         | The provided client-supplied ID conflicts with an existing record. |
| `already_active`          | Already active                       | Cannot reactivate — record is already in active state.             |
| `voice_not_enabled`       | Voice channel not enabled            | The OTP voice channel is not enabled for this account.             |
| `otp_not_active`          | OTP not active                       | The OTP session has expired or is not in an active state.          |
| `invalid_code`            | Invalid code                         | The OTP code provided does not match.                              |

<Accordion title="Troubleshooting validation errors">
  **Common Causes:**

  * Phone numbers missing the `+` prefix or country code (must be E.164 format like `+14155551234`)
  * Sending to a `list_number` that belongs to a different account
  * Bulk request arrays exceeding the 1,000 item limit
  * Creative message body exceeding the 1,600 character limit

  **Resolution:**

  1. Validate phone numbers match E.164 format before sending
  2. Use the List endpoint to verify your `list_number` values
  3. Check the `code` field in the error response for the specific validation that failed
</Accordion>

***

## Resource Limit Errors (413)

Returned when a bulk request exceeds the maximum number of items allowed per request.

| Error Code                          | Message                                   | Limit     | Description                                                                                                                             |
| ----------------------------------- | ----------------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `too_many_messages`                 | Maximum 1000 messages per request         | 1,000     | The `messages` array in a bulk send exceeds the limit.                                                                                  |
| `too_many_contacts`                 | Maximum 1000 contacts per request         | 1,000     | The `contacts` array in a bulk contact operation exceeds the limit.                                                                     |
| `too_many_contacts_with_validation` | Maximum reduced when use\_validation=true | (smaller) | When `use_validation=true` is set on bulk contact create, the per-request cap is lower because each contact triggers a billable lookup. |
| `too_many_records`                  | Maximum 1000 records per request          | 1,000     | The `records` array in a bulk import exceeds the limit.                                                                                 |
| `too_many_phones`                   | Maximum 500 phones per request            | 500       | The `phones` array in batch phone validation exceeds the limit.                                                                         |

### Example

```json theme={null}
{
  "error": "Maximum 1000 messages per request",
  "code": "too_many_messages"
}
```

<Note>
  To process more than 1,000 items, split your data into batches and send multiple requests sequentially.
</Note>

<Accordion title="Troubleshooting resource limit errors">
  **Common Causes:**

  * Attempting to send more than 1,000 messages in a single bulk request
  * Importing more than 1,000 contacts or records in one API call

  **Resolution:**

  1. Split large datasets into batches of 1,000 or fewer items
  2. Process batches sequentially with error handling between each batch
  3. Use the response `error_count` and `errors` array to identify and retry failed items
</Accordion>

***

## Not Found Errors (404)

Returned when the requested resource does not exist or is not accessible under your account.

| Error Code  | Message            | Description                                                                                                                                         |
| ----------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `not_found` | Resource not found | Generic not-found error. The message may include the specific resource type (e.g. "Contact not found", "Creative not found", "Schedule not found"). |

### Example

```json theme={null}
{
  "error": "Contact not found",
  "code": "not_found"
}
```

<Accordion title="Troubleshooting not found errors">
  **Common Causes:**

  * Using an ID from a different account (all resources are account-scoped)
  * Referencing a resource that was deleted
  * Typo in the resource ID

  **Resolution:**

  1. Verify the resource exists by calling the corresponding List endpoint
  2. Ensure your API key belongs to the same account that owns the resource
  3. Check that you are using the correct ID format (a 24-character hexadecimal ID for most resources)
</Accordion>

***

## Forbidden / Access Errors (403)

Returned when a valid API key is presented but the account is not permitted to perform the requested action. The `403 Account is suspended` response intentionally omits the `code` field — see [Authentication](/api-reference/authentication).

| Error Code            | Message                                          | Description                                                                                                                                                                                                    |
| --------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `product_not_enabled` | `{PRODUCT}` product not enabled for this account | The endpoint belongs to a product not enabled for your account. The actual code follows the pattern `{product}_not_enabled` (e.g. `email_not_enabled`, `partnerships_not_enabled`). Contact support to enable. |
| `billing_blocked`     | Billing blocked                                  | Account has an outstanding billing problem (failed charge, suspended billing).                                                                                                                                 |
| `account_suspended`   | Account is suspended                             | The account has been suspended; resolve billing or contact support.                                                                                                                                            |
| `fraud_blocked`       | Account flagged for fraud review                 | Account is in fraud-review hold; sends are paused until cleared.                                                                                                                                               |
| `geo_restricted`      | Geographic restriction                           | The recipient country is not enabled for this account.                                                                                                                                                         |
| `phone_type_blocked`  | Phone type blocked by account settings           | OTP recipient's line type (VOIP/landline) is blocked by account settings.                                                                                                                                      |

***

## Conflict Errors (409)

Returned when the request conflicts with the current state of the resource.

| Error Code             | Message                                 | Description                                                                                                                 |
| ---------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `id_collision`         | ID collision                            | A client-supplied ID conflicts with an existing record.                                                                     |
| `already_active`       | Already active                          | The record is already in the requested state.                                                                               |
| `no_domain_configured` | No link domain configured for this list | The sending list has no link-shortener domain configured; cannot create or shorten links until one is set in the dashboard. |

***

## Rate-Limit / Throttling Errors (429)

Returned when the request is throttled by a per-endpoint rate limit (for example the OTP and phone-validation endpoints) or a per-account limit (such as a daily send cap). Retry with exponential backoff after the window resets.

| Error Code           | Message                      | Description                                                                                                        |
| -------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `rate_limited`       | Rate limit exceeded          | A per-endpoint rate limit (e.g. OTP or phone validation) was exceeded. Back off and retry after the window resets. |
| `daily_cap_exceeded` | Daily send cap exceeded      | The account has hit its 24-hour send cap.                                                                          |
| `cooling_off`        | Cooling-off period in effect | Recipient is in a cooling-off window after a recent send.                                                          |
| `limit_reached`      | Limit reached                | A per-account or per-endpoint quota has been exhausted.                                                            |

***

## Server / Infrastructure Errors (5xx)

Returned when a subsystem fails. These are generally transient — retry with exponential backoff.

| Error Code             | HTTP | Message              | Description                                                               |
| ---------------------- | ---- | -------------------- | ------------------------------------------------------------------------- |
| `send_failed`          | 500  | Send failed          | The send pipeline encountered an unrecoverable error.                     |
| `save_error`           | 500  | Save error           | A datastore write failed.                                                 |
| `queue_failed`         | 500  | Queue failed         | The send-queue insertion failed.                                          |
| `provider_sync_failed` | 502  | Provider sync failed | An upstream provider (CRM/affiliate platform) sync did not complete.      |
| `provider_error`       | 503  | Provider unavailable | An upstream provider is unavailable.                                      |
| `redis_unavailable`    | 503  | Service unavailable  | The rate-limiter / dedup cache is unreachable.                            |
| `circuit_open`         | 503  | Circuit breaker open | A subsystem circuit breaker is open after repeated failures; backing off. |

***

## Handling Errors in Code

<CodeGroup>
  ```bash cURL theme={null}
  curl -i -X POST https://api.tracklysms.com/api/v2/send \
    -H "X-Api-Key: trk_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "list_number": "+14155551234",
      "to": "+14155556789",
      "body": "Hello!"
    }'

  # Check the HTTP status code and parse the JSON error response:
  # HTTP/1.1 400 Bad Request
  # {"error": "Invalid recipient phone number format", "code": "invalid_phone"}
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.tracklysms.com/api/v2/send",
      headers={"X-Api-Key": "trk_your_api_key_here"},
      json={"list_number": "+14155551234", "to": "+14155556789", "body": "Hello!"}
  )

  if not response.ok:
      data = response.json()
      code = data.get("code")
      error = data.get("error")

      if code == "invalid_credentials":
          # Re-authenticate or alert
          pass
      elif code == "invalid_phone":
          # Skip this recipient or fix the number format
          pass
      elif code == "too_many_messages":
          # Split into smaller batches
          pass
      else:
          print(f"API error [{code}]: {error}")
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://api.tracklysms.com/api/v2/send", {
    method: "POST",
    headers: {
      "X-Api-Key": "trk_your_api_key_here",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      list_number: "+14155551234",
      to: "+14155556789",
      body: "Hello!",
    }),
  });

  if (!response.ok) {
    const data = await response.json();

    switch (data.code) {
      case "invalid_credentials":
        // Re-authenticate or alert
        break;
      case "invalid_phone":
        // Skip this recipient or fix the number format
        break;
      case "too_many_messages":
        // Split into smaller batches
        break;
      default:
        console.error(`API error [${data.code}]: ${data.error}`);
    }
  }
  ```
</CodeGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="API Limits & Best Practices" icon="gauge" href="/api-reference/v2/rate-limiting">
    Payload limits, batch sizes, and retry strategies
  </Card>

  <Card title="Send Message" icon="paper-plane" href="/api-reference/v2/messages/send-single">
    Send your first API message
  </Card>
</CardGroup>
