Errors and rate limits
The APIs use conventional HTTP status codes. Error bodies are JSON; the shape varies by endpoint but always includes a human-readable message.
Status codes
| Code | Meaning |
|---|---|
| 400 | The request body or parameters failed validation. The message says which field. |
| 401 | No credential, an expired JWT, or an API key sent in the wrong header. |
| 403 | Valid credential, but it lacks permission. Most often a tenant key used on another tenant's resources. |
| 404 | The resource does not exist, or is outside your tenant's scope. |
| 409 | The request conflicts with current state, for example activating a conversation version that no longer exists. |
| 429 | Rate limited. Retry after a pause. |
| 500 | Something failed on our side. Retry with backoff; contact support if it persists. |
Common 401 causes
- The API key was sent as
Authorization: Bearer .... Use theX-Api-Keyheader instead. - The JWT expired. Refresh it via
POST /auth/refreshon the Auth API. - The key was revoked.
Rate limits
Most endpoints are not rate limited. The exceptions protect paid upstream services and abuse-prone surfaces:
- Text-to-speech synthesis (
POST /api/tts/...) is limited per tenant. - A handful of anonymous endpoints have per-IP limits.
A 429 response means you crossed one of these. Limits are windowed, so waiting briefly and retrying is the right client behavior. If your integration legitimately needs a higher TTS budget, contact support.