Error codes
Every code below appears as error.code in the standard error envelope:
{
"error": {
"code": "<CODE>",
"message": "…",
"timestamp": "2026-04-21T12:34:56.789Z",
"requestId": "req_…"
}
}
code, message, and timestamp are always present. requestId is
included once the route handler has generated one (middleware-level
rejections like INVALID_API_KEY omit it). Rate-limit and
service-warming responses add retryAfterSeconds alongside the
standard Retry-After HTTP header.
400 — Validation
| Code | When | Action |
|---|---|---|
MISSING_AUDIO_FILE | No audio field in the multipart body. | Add the file. |
UNSUPPORTED_FORMAT | File isn't a valid MP3/WAV/M4A/WebM/OGG/FLAC. | Convert or fix the file. |
AUDIO_TOO_SHORT | Audio under 3 minutes. | Submit longer audio. |
AUDIO_TOO_LONG | Audio over 45 minutes. | Trim the audio. |
AUDIO_DURATION_UNAVAILABLE | The audio duration could not be read (file corrupted or unsupported). | Re-encode the file and resubmit. |
FILE_TOO_LARGE | File exceeds 25 MB. | Compress or trim. |
INVALID_LANGUAGE_CODE | Not a 2-letter ISO 639-1 code. | Use en, es, fr, etc. |
INVALID_EXTERNAL_ID | externalId empty or > 255 chars. | Provide 1–255 chars, or omit. |
INVALID_METADATA | metadata field is not valid JSON. | Fix the JSON. |
INVALID_STATUS | status query param on /runs not in allow-list. | Use a valid lifecycle value. |
INVALID_SERVICE_TYPE | serviceType query param on /runs not in allow-list. | Use speech or cv_deepmatch. |
INVALID_DATE | createdAfter/createdBefore not valid ISO 8601. | Use a proper datetime. |
INVALID_PARAMETERS | Some cutSetting out of bounds. | Check parameter ranges. |
401 — Authentication
| Code | Action |
|---|---|
MISSING_API_KEY | No X-API-Key / Authorization header. Add it. |
INVALID_API_KEY | Key unrecognized or marked inactive. Check your env var. |
API_KEY_EXPIRED | Key's expiry has passed. Rotate to a fresh key. |
CLIENT_INACTIVE | The account behind this key is disabled. Contact support. |
402 — Credits
| Code | Action |
|---|---|
INSUFFICIENT_CREDITS | Top up before retrying. Check GET /api/v1/credits. |
403 — Permissions
| Code | Action |
|---|---|
MULTILINGUAL_NOT_ENABLED | Contact your account manager to enable non-English analysis. |
IP_NOT_ALLOWED | The API key has an IP whitelist and your request didn't originate from an allowed address. |
404 — Not found
| Code | Action |
|---|---|
REQUEST_NOT_FOUND | Wrong requestId, or it belongs to a different client. |
429 — Rate limiting
| Code | Where | Action |
|---|---|---|
RATE_LIMIT_EXCEEDED | Submit endpoint. | Exponential backoff. |
POLL_RATE_LIMITED | Poll endpoint, same requestId polled faster than every 10s. | Respect Retry-After. |
503 — Service unavailable
| Code | Action |
|---|---|
SERVICE_WARMING_UP | Scoring service still warming up (15–20 min after a new deploy). Retry with backoff. |
Terminal failures on a run (status: "failed")
Returned inside a 200 OK poll response — the error.code reveals which
pipeline step failed. No credits are charged on failed runs.
| Code | Meaning |
|---|---|
TRANSCRIPTION_FAILED | Audio quality issue or transcription provider error. |
TRANSCRIPTION_LOW_CONFIDENCE | Audio content doesn't match the requested language. |
SCORING_FAILED | Scoring service error after retry. |
VOCAB_MODEL_TIMEOUT | Vocabulary model timed out. |
FLUENCY_MODEL_TIMEOUT | Fluency model timed out. |
ACCENT_SCORE_UNAVAILABLE | Accent could not be measured. The run fails rather than returning a score we didn't measure — resubmit. |
SERVICE_CONFIGURATION_ERROR | External provider misconfigured. Contact support. |
STUCK_TIMEOUT | Run exceeded its watchdog timeout. |
INTERNAL_ERROR | Unexpected error. Contact support. |