{ "code": "ERROR_CODE", "message": "Human-readable description" }
Enrollment errors (HTTP 400)
| Code | Cause | Action |
|---|---|---|
AUDIO_TOO_SHORT | Clip under 2 seconds | Prompt re-record with more speech |
AUDIO_TOO_QUIET | RMS energy too low — silent or muted | Prompt to move closer to mic |
LOW_VOICE_SIGNAL | ECAPA embedding norm too low — noise, music, or no voice | Prompt to record in a quiet environment |
AUDIO_CONVERSION_FAILED | Unrecognised audio format | Use WAV, WebM/Opus, MP3 or M4A |
Verify errors (HTTP 400)
| Code | Cause | Action |
|---|---|---|
VOICE_MISMATCH | Speaker cosine similarity below match threshold | Show “Voice not recognised” — offer retry |
CHALLENGE_EXPIRED | challenge_id unknown or past 120s TTL | Request a new challenge |
Auth errors
| Code | Status | Cause | Action |
|---|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid API key | Check key and Authorization header |
TOKEN_EXPIRED | 401 | Verify token past 60s TTL | Re-verify |
PIPELINE_UNAVAILABLE | 503 | Voice model transient failure | Retry with exponential backoff |
SDK-only codes (not from API)
| Code | Cause |
|---|---|
NETWORK_ERROR | Fetch-level failure (no response) |
MICROPHONE_DENIED | getUserMedia permission refused by browser |