# Error Codes

> Error handling reference for the TBit API

- Page: https://tbit.app/docs/api/errors
- Base URL: `https://rest-api.tbit.app/v1`
- Authentication: `X-API-Key` header with your key on every request (the examples read it from the `TBIT_API_KEY` environment variable)

Looking for why a WhatsApp message was not delivered? See [WhatsApp delivery errors](https://tbit.app/docs/whatsapp-delivery-errors).

## Error Response Format

All errors follow a consistent JSON structure:

```json
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Activity not found"
  }
}
```

## Error Codes

| Status | Code | Description |
| --- | --- | --- |
| `400` | `VALIDATION_ERROR` | Invalid request body or query parameters |
| `401` | `UNAUTHORIZED` | Missing or invalid API key |
| `404` | `NOT_FOUND` | Resource not found or does not belong to your agent |
| `405` | `METHOD_NOT_ALLOWED` | HTTP method not supported for this endpoint |
| `409` | `CONFLICT` | Resource already exists (e.g., contact with this channel) |
| `422` | `SEND_FAILED` | Template send failed (e.g., no messaging window) |
| `429` | `RATE_LIMITED` | Rate limit exceeded (100 requests/minute) |
| `500` | `INTERNAL_ERROR` | Unexpected server error |

## Rate Limit Headers

Every response includes rate limit information in headers:

| Header | Description |
| --- | --- |
| `X-RateLimit-Remaining` | Requests remaining in current window |
| `X-RateLimit-Reset` | Timestamp (ms) when the window resets |

## Error Handling

Best practices for handling API errors:

- Always check the HTTP status code before parsing the response body
- Implement exponential backoff for 429 (rate limit) errors
- Log error codes and messages for debugging
- Do not retry 400 or 401 errors: fix the request first
