Error response formats
OpenAI format (/v1/audio/* endpoints)
Used for realtime WebSocket, offline HTTP, and session-token endpoints:
{
"error": {
"message": "API key is missing.",
"type": "invalid_request_error",
"code": "missing_api_key"
}
}
type is rate_limit_error for 429 responses, otherwise invalid_request_error.
Envelope format (Key management API)
{
"ok": false,
"error": {
"code": "admin_unauthorized",
"message": "Admin token required.",
"retryable": false
}
}
retryable is true for 429 and ≥500 responses.
HTTP error codes
| Code | HTTP | Cause | Client action |
|---|---|---|---|
| missing_api_key | 401 | No Authorization header / query token | Add API key |
| invalid_api_key | 401 | Key format invalid or unknown | Check key |
| revoked_api_key | 401 | Key has been revoked | Contact provider |
| expired_api_key | 401 | Key has expired | Re-provision |
| auth_unavailable | 503 | Key store unavailable | Retry later |
| invalid_session_token | 401 | Session token invalid or expired | Obtain new token |
| token_issuer_unavailable | 503 | Token issuer not configured | Retry later |
| websocket_required | 426 | Non-WS upgrade request | Use WebSocket client |
| gateway_disabled | 503 | Realtime gateway disabled | Contact provider |
| upstream_unavailable | 503 | Upstream unavailable (circuit breaker) | Back off and retry |
| connection_rate_limited | 429 | Connection rate exceeded | Honor Retry-After |
| concurrent_connection_limit | 429 | Max concurrent connections exceeded | Wait for release |
| request_rate_limited | 429 | Request rate exceeded | Honor Retry-After |
| audio_quota_exhausted | 429 | Audio window budget exhausted | Retry later |
| audio_too_long | 413 | Single request audio exceeds plan limit | Reduce audio duration |
| internal_error | 500 | Uncaught exception | Contact provider |
| bad_request | 400 | Invalid request body | Fix and retry |
| invalid_content_type | 400 | Segment endpoint expects multipart; batch expects JSON on /jobs | Fix Content-Type and path |
| transcription_failed | 502 | Segment transcription failed after worker attempts | Client may resend utterance |
| missing_file | 400 | Segment request missing file field | Add multipart file |
WebSocket error events
Within an active WebSocket connection, the server may send error events:
{ "type": "error", "code": "...", "message": "...", "request_id": "..." }
WebSocket error codes
| Code | Description | Close code |
|---|---|---|
| audio_frame_too_large | Audio frame exceeds 1 MiB | 1009 |
| concurrent_utterance_limit | Concurrent utterance limit exceeded | — |
| upstream_backpressure | Upstream backpressure | 1013 |
| client_backpressure | Client backpressure | — |
| upstream_unavailable | Upstream unavailable | 1013 |
| idle_timeout | Idle timeout reached | 4408 |
| session_duration_limit | Session duration exceeded | 1008 |
| session_audio_limit | Session audio budget exceeded | 1008 |
| audio_quota_exhausted | Audio quota exhausted | 1008 |
| bad_json | JSON parse failure | — |
| bad_message | Invalid message type | — |
| invalid_audio | Invalid audio data | — |
Key management API errors
| Code | HTTP | Description |
|---|---|---|
| admin_unauthorized | 401 | Missing admin token |
| invalid_plan | 400 | Unknown plan |
| invalid_expiry | 400 | Invalid or past expiry date |
| store_unavailable | 500 | R2 storage unavailable |
| key_not_found | 404 | Key ID not found |
| not_found | 404 | Unknown management route |
Troubleshooting
| Problem | Check |
|---|---|
| 401 missing_api_key | Ensure request includes Authorization: Bearer sk-... |
| 401 invalid_api_key | Verify key starts with sk-, length ≥ 16 |
| 429 *_rate_limited | Honor Retry-After header, exponential backoff |
| 503 upstream_unavailable | Check /readyz for upstream status |
| WS idle_timeout | Keep sending audio frames, or close explicitly |
| WS audio_frame_too_large | Reduce frame size to ≤ 1 MiB |