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

# Error Handling

## Error Responses

All errors return JSON with an `error` object. Validation errors add an `errors` array detailing each problem:

```json
{
  "error": {
    "message": "Language code is required",
    "code": "VALIDATION_ERROR",
    "statusCode": 400,
    "errors": ["Provide \"lang\" or \"voice\" parameter"]
  }
}
```

### Error Codes

| HTTP Code | Code                         | Description                                                                            |
| --------- | ---------------------------- | -------------------------------------------------------------------------------------- |
| 400       | VALIDATION\_ERROR            | Invalid request parameters                                                             |
| 401       | UNAUTHORIZED                 | Invalid or missing API key or secret                                                   |
| 404       | NOT\_FOUND                   | Voice or resource not found                                                            |
| 429       | RATE\_LIMIT\_EXCEEDED        | Tier request-rate limit exceeded                                                       |
| 429       | BURST\_RATE\_LIMIT\_EXCEEDED | Too many requests from one client in a short window                                    |
| 500       | INTERNAL\_ERROR              | Server error                                                                           |
| 502       | *(none)*                     | Upstream TTS provider error; `message` carries the provider's failure, no `code` field |

## Rate Limits

Rate limits apply per API key, which is required — requests without a valid key are rejected. The same limits apply to both the v1 and v2 APIs.

| Plan       | Requests per minute |
| ---------- | ------------------- |
| Free       | 100                 |
| Commercial | 1,000               |
| Enterprise | Custom              |

The per-minute limits above are counted per API key. A separate burst check applies per API key **and** client IP over a short window, so unusually rapid bursts from one client can be limited briefly even while you're under the per-minute limit.

### Monthly character quota

| Plan       | Characters per month                  |
| ---------- | ------------------------------------- |
| Free       | 1,000,000                             |
| Commercial | Fair use — contact us for high volume |
| Enterprise | Custom                                |

Keys that exceed the monthly quota are suspended until upgraded.

> [!NOTE]
> A `429` carries a `Retry-After` header — the seconds to wait before retrying (dynamic; read and honor it, and the retry will succeed). The body `code` says which limit was hit: `RATE_LIMIT_EXCEEDED` (per-minute tier limit) or `BURST_RATE_LIMIT_EXCEEDED` (per API key + client IP burst). `X-RateLimit-Limit` and `X-RateLimit-Remaining` accompany responses and reflect the per-minute limit, so a burst `429` may show remaining requests alongside a short `Retry-After`.
