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

# Error Handling

> Handle errors and failures in the NativeMessage API

## HTTP Status Codes

| Status Code | Meaning        | Action                                        |
| ----------- | -------------- | --------------------------------------------- |
| 200         | OK             | Request succeeded                             |
| 201         | Created        | Resource created successfully                 |
| 400         | Bad Request    | Fix request parameters or body                |
| 401         | Unauthorized   | Check API token or credentials                |
| 403         | Forbidden      | Account suspended or insufficient permissions |
| 404         | Not Found      | Resource does not exist                       |
| 429         | Rate Limited   | Slow down, retry after X-RateLimit-Reset      |
| 500         | Internal Error | Server error, retry with exponential backoff  |

## Error Response Format

All errors return a JSON object with a human-readable message:

```json theme={null}
{
  "error": "to, from, and body are required"
}
```

## Common Errors

| Error Message                     | Cause                                  | Solution                              |
| --------------------------------- | -------------------------------------- | ------------------------------------- |
| `to, from, and body are required` | Missing required fields in request     | Include all required parameters       |
| `invalid username or password`    | Authentication failed                  | Verify credentials or API token       |
| `account is not active`           | Account suspended or disabled          | Contact support to reactivate account |
| `pipeline processing failed`      | Routing or billing configuration issue | Check gateway and billing settings    |
| `invalid phone number format`     | Phone number not in E.164 format       | Use format: `+[country_code][number]` |
| `insufficient balance`            | Account balance too low                | Add credits to your account           |
| `rate limit exceeded`             | Too many requests                      | Wait for reset or upgrade rate limit  |

## Message-Level Errors

Some requests succeed with HTTP 200 but individual messages may fail. Check the `error_code` and `error_message` fields on each Message object.

**Example: Bulk send with partial failures**

```json theme={null}
{
  "messages": [
    {
      "id": "msg_abc123",
      "to": "+8801712345678",
      "status": "delivered",
      "error_code": null,
      "error_message": null
    },
    {
      "id": "msg_def456",
      "to": "+1234567890",
      "status": "failed",
      "error_code": "INVALID_NUMBER",
      "error_message": "Phone number is invalid or unreachable"
    }
  ]
}
```

## Error Code Categories

Search for specific error codes to understand failure reasons:

```bash cURL theme={null}
curl -X GET "https://api-message.nativehub.live/api/v1/error-codes/search?q=invalid" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
```

```javascript Node.js theme={null}
const response = await fetch(
  'https://api-message.nativehub.live/api/v1/error-codes/search?q=invalid',
  {
    headers: {
      'Authorization': 'Bearer YOUR_API_TOKEN'
    }
  }
);

const errorCodes = await response.json();
console.log(errorCodes);
```

```python Python theme={null}
response = requests.get(
    'https://api-message.nativehub.live/api/v1/error-codes/search',
    headers={'Authorization': 'Bearer YOUR_API_TOKEN'},
    params={'q': 'invalid'}
)

error_codes = response.json()
print(error_codes)
```

**Common error code patterns:**

| Code Pattern     | Category               | Examples                                         |
| ---------------- | ---------------------- | ------------------------------------------------ |
| `INVALID_*`      | Validation failures    | INVALID\_NUMBER, INVALID\_FORMAT                 |
| `INSUFFICIENT_*` | Resource limitations   | INSUFFICIENT\_BALANCE, INSUFFICIENT\_PERMISSIONS |
| `CARRIER_*`      | Carrier/network issues | CARRIER\_REJECTED, CARRIER\_TIMEOUT              |
| `BLOCKED_*`      | Spam/compliance blocks | BLOCKED\_SPAM, BLOCKED\_OPTED\_OUT               |

## Retry Strategies

<Warning>
  Do NOT retry client errors (400, 401, 403, 404). These indicate problems with your request that will not resolve automatically.
</Warning>

**Retry these status codes:**

* **429 Rate Limited**: Wait until `X-RateLimit-Reset` timestamp, then retry
* **500 Internal Error**: Exponential backoff (1s, 2s, 4s, 8s...)
* **503 Service Unavailable**: Exponential backoff

**Implementation example:**

```javascript Node.js theme={null}
async function sendWithRetry(message, maxRetries = 3) {
  let delay = 1000; // Start with 1 second

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch('https://api-message.nativehub.live/api/v1/messages', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_API_TOKEN',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(message)
    });

    if (response.ok) {
      return await response.json();
    }

    // Don't retry client errors
    if (response.status >= 400 && response.status < 500 && response.status !== 429) {
      const error = await response.json();
      throw new Error(error.error);
    }

    // Retry with exponential backoff for 429 and 5xx
    if (response.status === 429 || response.status >= 500) {
      if (attempt < maxRetries - 1) {
        await new Promise(resolve => setTimeout(resolve, delay));
        delay *= 2; // Exponential backoff
        continue;
      }
    }

    throw new Error(`Request failed with status ${response.status}`);
  }
}
```

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

def send_with_retry(message, max_retries=3):
    delay = 1  # Start with 1 second

    for attempt in range(max_retries):
        response = requests.post(
            'https://api-message.nativehub.live/api/v1/messages',
            headers={
                'Authorization': 'Bearer YOUR_API_TOKEN',
                'Content-Type': 'application/json'
            },
            json=message
        )

        if response.ok:
            return response.json()

        # Don't retry client errors
        if 400 <= response.status_code < 500 and response.status_code != 429:
            raise Exception(response.json()['error'])

        # Retry with exponential backoff for 429 and 5xx
        if response.status_code == 429 or response.status_code >= 500:
            if attempt < max_retries - 1:
                time.sleep(delay)
                delay *= 2  # Exponential backoff
                continue

        raise Exception(f'Request failed with status {response.status_code}')
```

## Idempotency

Prevent duplicate message sends by using the `batch_id` parameter for deduplication:

```javascript Node.js theme={null}
const batchId = crypto.randomUUID();

const response = await fetch('https://api-message.nativehub.live/api/v1/messages', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    from: '+8801712345678',
    to: '+8801812345679',
    body: 'Your OTP is 123456',
    batch_id: batchId // Same batch_id will deduplicate
  })
});
```

<Note>
  Messages with identical `batch_id` values sent within 24 hours are treated as duplicates and only processed once.
</Note>

## Debugging Checklist

When troubleshooting API errors:

1. Check HTTP status code category (4xx vs 5xx)
2. Read the `error` field in the response body
3. For message-level failures, check `error_code` and `error_message`
4. Search error codes via `/error-codes/search`
5. Verify phone numbers are in E.164 format
6. Check account balance and active status
7. Review rate limit headers
8. Test with a known-good number (e.g., your own phone)
