Skip to content

Status Codes & Errors

The Uspeech API follows conventional REST semantics. The HTTP status code is the source of truth for whether a request succeeded; the response body adds detail.


CodeMeaning
200 OKSuccessful read (GET) or action returning a body.
201 CreatedA new resource was created (typically a file upload).
202 AcceptedThe request was accepted and work has been queued asynchronously.
204 No ContentSuccessful action with no body to return.
400 Bad RequestThe request body or query parameters are invalid. The response body describes which fields.
401 UnauthorizedNo credentials were supplied. Add the Authorization: Api-Key … header.
403 ForbiddenCredentials are missing, malformed, revoked, the user is inactive, or the user has no access to the resource.
404 Not FoundThe resource doesn’t exist — or exists but isn’t visible to the caller.
429 Too Many RequestsRate limit exceeded. Retry after a short delay.
5xxAn unexpected server error. Safe to retry idempotent reads; check status before retrying writes.

DRF returns errors as JSON. The exact shape depends on what failed:

Validation error (per-field):

{
"project": ["This field is required."],
"file": ["No file was submitted."]
}

Generic error (auth, not-found, etc.):

{
"detail": "Authentication credentials were not provided."
}

Subscription / usage error:

{
"detail": "Free trial limit exceeded.",
"reason": "free_trial_exceeded"
}

Always check the HTTP status first; use the body for human-readable detail.


A transcription job can complete the request lifecycle (HTTP 201 on upload) and still fail asynchronously in the background. When that happens, the transcript record’s status becomes failed and the error_reason field tells you why:

error_reasonWhen it’s set
audio_too_shortThe audio is below the minimum length needed for transcription — typically empty or beep-only recordings.
hallucinated_transcriptA safeguard fired: the model returned text whose timestamps extend far past the actual audio duration, which usually signals a fabricated transcript.

If error_reason is empty on a failed transcript, the cause is upstream (storage, model API, etc.) — check server logs or contact support.

💡 Tip: when polling GET /api/files/{id}/, treat failed as terminal. Don’t retry blindly — for audio_too_short the file genuinely has nothing to transcribe; for hallucinated_transcript, re-uploading the same audio will likely produce the same result.


A few common pitfalls return 401 or 403:

  • Header is exactly Authorization: Api-Key <key> (with the space after Api-Key).
  • The plaintext key is <prefix>.<secret> — both halves must be sent.
  • A revoked key returns 403 even if it was previously valid.
  • An inactive user (is_active = False) cannot use the key.

See Authentication for the full setup.