Error handling
Most production errors fall into a small number of patterns. This page covers the right response to each.
Standard error shape
Every 4xx and 5xx response from the public API uses the platform's shared standard error envelope:
{
"error": {
"code": "INVALID_LANGUAGE_CODE",
"message": "Invalid language code. Must be a 2-letter ISO 639-1 code.",
"timestamp": "2026-04-21T12:34:56.789Z",
"requestId": "req_1705412345678_abc123",
"details": { /* optional, code-specific extras */ }
}
}
code, message, and timestamp are always present. requestId and
details are included when they apply — requestId is emitted once the
route handler has generated one (middleware-level rejections happen before
that and omit it). It's the same envelope on every module; see
Identifiers for how requestId differs from the
run id and your externalId.
Rate-limit and service-warming responses also include
error.retryAfterSeconds and the standard HTTP Retry-After header.
Respect the header.
Common cases
400 Bad Request
Malformed input. Fix the request and retry. Typical codes:
MISSING_AUDIO_FILEUNSUPPORTED_FORMATFILE_TOO_LARGE— audio exceeds the per-request file-size limit.INVALID_LANGUAGE_CODEINVALID_EXTERNAL_IDINVALID_METADATAAUDIO_TOO_SHORT/AUDIO_TOO_LONG
Do not retry a 400. It will fail the same way.
401 Unauthorized
Check your API key. Possible codes:
MISSING_API_KEY— noX-API-KeyorAuthorizationheader.INVALID_API_KEY— key not recognized or marked inactive.API_KEY_EXPIRED— key had an expiration date that's now past. Rotate.CLIENT_INACTIVE— the account behind the key has been disabled. Contact support.
402 Payment Required
INSUFFICIENT_CREDITS — balance below minimum. Top up before retrying.
403 Forbidden
MULTILINGUAL_NOT_ENABLED— request language is non-English and the permission isn't enabled on your account.IP_NOT_ALLOWED— the API key has an IP whitelist and your request didn't originate from an allowed address.
429 Too Many Requests
Two flavors — treat them differently:
RATE_LIMIT_EXCEEDEDon submit: you're submitting too fast. Back off with exponential delay.POLL_RATE_LIMITEDon poll: you're polling a singlerequestIdtoo fast. RespectRetry-Afterand continue polling the samerequestId.
503 Service Unavailable
SERVICE_WARMING_UP— the scoring service is warming up after a fresh deployment (typically 15–20 minutes after a deploy). Retry with the suggestedretryAfterSeconds, then back off further if still warming.
status: "failed" on a poll response
The run reached a terminal failure. No credits were charged. Common codes:
TRANSCRIPTION_FAILED— audio quality issue or provider error.TRANSCRIPTION_LOW_CONFIDENCE— audio content doesn't match the requested language.SCORING_FAILED— scoring service error after retry.SERVICE_CONFIGURATION_ERROR— external provider misconfigured (rare; contact support).STUCK_TIMEOUT— run exceeded its watchdog timeout.INTERNAL_ERROR— unexpected error (contact support).
Retry policy: resubmit the audio with a fresh request. Do not reuse the
same requestId — it's terminal.
Retry strategy at a glance
| Response | Retry? | How |
|---|---|---|
400 | No | Fix input. |
401 | No | Check key / rotate if expired / contact support if account inactive. |
402 | No | Top up balance. |
403 | No | Contact support (language permission, IP whitelist). |
429 RATE_LIMIT_EXCEEDED | Yes | Respect Retry-After, then exponential backoff. |
429 POLL_RATE_LIMITED | Yes | Respect Retry-After, continue polling same requestId. |
503 SERVICE_WARMING_UP | Yes | Retry after 30–60s, back off further if repeated. |
status: "failed" | Case-by-case | Fresh submission with new audio if applicable. |
Full error code catalog
See Resources → Error codes for every code the API can return, with recommended actions.
See in the API reference
Every endpoint page lists the full response schema for each status code:
- POST /api/v1/speech/analyze — 400 / 401 / 402 / 403 / 429 / 503
- GET /api/v1/speech/analyze/{id} — 200 (including
status: failed), 404, 429 - GET /api/v1/speech/runs — 400 / 401
- GET /api/v1/credits — 401