Errors

Reference for every error type returned by Soniox APIs (REST, async, STT WebSocket, TTS WebSocket, TTS REST), with the cause and how to resolve each one.

Overview

This page documents errors from every Soniox API surface:

  • REST API at api.soniox.com: synchronous endpoints for files, transcriptions, speakers, usage logs, temporary API keys, and async transcription submission.
  • Async transcription failure: a job created via POST /v1/transcriptions returned 200, but the transcription itself ends in status: "failed" after the audio is downloaded or transcribed.
  • STT WebSocket at stt-rt.soniox.com: real-time speech-to-text.
  • TTS WebSocket at tts-rt.soniox.com/tts-websocket: real-time text-to-speech.
  • TTS REST at tts-rt.soniox.com/tts: single-request text-to-speech.

All surfaces share one error_type taxonomy. Branch your client code on error_type, not on the human-readable message; the wording may change, the slug will not. Every error response carries:

  • error_type: stable, machine-readable identifier. See API error types for the full list.
  • request_id: unique per request. Include it when contacting support@soniox.com; server logs are keyed on it.
  • more_info: a URL pointing at the section on this page describing the error_type. The pattern is https://soniox.com/docs/api-reference/errors#<error_type> with underscores replaced by hyphens.

The HTTP status code mapped to each error_type is the same on every surface.


Response structure

REST API response

REST API errors return a JSON body with the HTTP status code:

{
  "status_code": 401,
  "error_type": "unauthenticated",
  "message": "Incorrect API key provided. You can get an API key at https://console.soniox.com",
  "validation_errors": [],
  "request_id": "3d37a3bd-5078-47ee-a369-b204e3bbedda",
  "more_info": "https://soniox.com/docs/api-reference/errors#unauthenticated"
}
status_codenumber

HTTP status code, mirrored in the response body for convenience.

error_typestring

Stable, machine-readable identifier of the error. Branch on this, not on message. See the error reference below for the full list.

messagestring

Human-readable description of the error. Safe to show to operators or log; do not parse or pattern-match against it.

validation_errorsarray<object>

Populated when error_type is invalid_request and the cause is a per-field validation failure. Each entry has error_type, location (dotted path of the offending field), and message.

request_idstring

Unique identifier of this request. Server logs are keyed on it, so include it when contacting support@soniox.com.

more_infostring

Link to the section on this page describing the error_type. The URL pattern is https://soniox.com/docs/api-reference/errors#<error_type> with underscores replaced by hyphens.

Async transcription failure

When you create a transcription with POST /v1/transcriptions, the call returns 200 and a transcription object as soon as the job is accepted. The work itself happens asynchronously: the audio is downloaded (if a URL was supplied), then transcribed.

If the job fails, the HTTP layer doesn't see the failure. Instead, GET /v1/transcriptions/{id} returns status: "failed" with error_type and error_message fields populated. Always check status and read these fields when polling a transcription.

{
  "id": "84c32fc6-4fb5-4e7a-b656-b5ec70493753",
  "status": "failed",
  "error_type": "file_download_failed",
  "error_message": "Failed to download audio from the provided URL.",
  "...": "..."
}

Failed async jobs are not auto-retried. Fix the cause and submit a new transcription. The error_type values that can appear on a failed job are flagged below with Async on their Surfaces line.

STT WebSocket error frame

On error, the STT WebSocket sends a single JSON text frame and then closes the connection with WebSocket close code 1000 (Normal Closure). Branch on error_type inside the frame, not on the close code.

{
  "tokens": [],
  "error_code": 401,
  "error_type": "unauthenticated",
  "error_message": "Incorrect API key provided. You can get an API key at https://console.soniox.com",
  "more_info": "https://soniox.com/docs/api-reference/errors#unauthenticated",
  "request_id": "3d37a3bd-5078-47ee-a369-b204e3bbedda"
}

The error frame reuses the shape of a normal response frame (hence the empty tokens array), with the error fields populated. error_code is the HTTP status as an integer, and the human-readable text lives in error_message rather than message. The frame does not carry a validation_errors array; a single failure is described in error_message.

TTS WebSocket error frame

The TTS WebSocket multiplexes multiple streams over a single connection. Every error frame carries a stream_id:

{
  "stream_id": "stream-1",
  "error_code": 400,
  "error_type": "invalid_stream_state",
  "error_message": "Stream stream-1 is already active on this connection. Choose a different stream_id, or cancel the existing stream first.",
  "more_info": "https://soniox.com/docs/api-reference/errors#invalid-stream-state",
  "request_id": "3d37a3bd-5078-47ee-a369-b204e3bbedda"
}

Per-stream errors do not close the connection. Other streams on the same connection continue running and the client may keep using the WebSocket. A {"terminated": true, "stream_id": "..."} frame typically follows for the affected stream.

Connection-level errors (malformed top-level message, server shutting down) carry stream_id: "" and close the connection.

TTS REST response

TTS REST has two error paths depending on whether response headers have been sent.

Headers not yet sent. Validation and authentication errors, as well as errors raised before audio streaming starts, return a JSON body with the HTTP status code:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "error_code": 401,
  "error_type": "unauthenticated",
  "error_message": "Missing API key. Provide it as an Authorization header (e.g. 'Authorization: Bearer <SONIOX_API_KEY>'). You can get an API key at https://console.soniox.com.",
  "more_info": "https://soniox.com/docs/api-reference/errors#unauthenticated",
  "request_id": "3d37a3bd-5078-47ee-a369-b204e3bbedda"
}

Headers already sent (mid-stream failure). The initial response was 200 OK and audio bytes have already been flushed to the client. The connection closes abruptly with no in-band error payload. Clients should treat a truncated audio stream as a server-side failure.


API error types

Each section below documents one error_type. The badge shows the HTTP status code (the same on every surface), and the Surfaces line lists every API where this error_type can appear.

invalid_request

HTTP 400

Surfaces: REST · STT WebSocket · TTS WebSocket · TTS REST

Cause. The request body or query parameters failed validation. Common triggers:

  • REST: a required field is missing, a value is out of range, an enum value is unknown, a multipart upload is malformed or has unknown size, an uploaded file exceeds the per-file byte limit, or a request-level invariant is violated (for example, end_time not strictly after start_time on GET /v1/usage-logs).
  • WebSocket / TTS REST: a required start-request or per-stream field is missing or too long, a JSON message is malformed, an audio frame is not valid base64, or a translation parameter combination is invalid.

When the cause on REST is a per-field validation failure, the response includes validation_errors with the exact location and reason for each field:

{
  "status_code": 400,
  "error_type": "invalid_request",
  "message": "Invalid request.",
  "validation_errors": [
    {
      "error_type": "missing",
      "location": "file.file",
      "message": "Field required"
    }
  ],
  "request_id": "..."
}

WebSocket and TTS REST responses do not carry validation_errors; the single failure is described in error_message.

Solution. Read validation_errors (REST) or error_message (streaming) and resend the request with corrected values.

invalid_cursor

HTTP 400

Surfaces: REST

Cause. The cursor query parameter on a paginated endpoint (/v1/files, /v1/transcriptions, /v1/usage-logs) could not be decoded. The cursor is opaque and only valid when copied verbatim from the previous page's next_page_cursor; any modification, truncation, or stale cursor triggers this error.

Solution. Omit cursor to start from the first page, or pass the exact next_page_cursor from the previous response without modification. Keep all other query parameters constant across pages of the same listing.

model_not_available

HTTP 400

Surfaces: REST · Async · STT WebSocket · TTS WebSocket · TTS REST

Cause. The requested model is unknown, has been retired, or is not enabled for the calling project or region.

Solution. Use a model from the STT models catalog or TTS models catalog. If you've been pinning a specific model, switch to a current one before its retirement date.

max_concurrent_streams_reached

HTTP 400

Surfaces: TTS WebSocket

Cause. The TTS WebSocket connection has reached its server-imposed cap on the number of simultaneous streams it can run. This is a per-connection limit and is not the per-organization or per-project concurrency cap (which surfaces as limit_exceeded).

Solution. Send a cancel message for one of the active streams on this connection to free a slot, or open a new WebSocket connection.

invalid_stream_state

HTTP 400

Surfaces: TTS WebSocket

Cause. A request was issued against a stream that is in the wrong state for that operation. Concrete cases:

  • start with a stream_id that is already active on the connection.
  • text or cancel for a stream_id that does not exist.
  • text or text_end after the stream already received text_end.
  • cancel after the stream was already cancelled.

Solution. Read error_message for the specific state issue. Most cases indicate a client-side bug; verify the stream lifecycle follows starttext…text_end (or cancel from any state).

invalid_audio_file

HTTP 400

Surfaces: REST (POST /v1/files upload) · Async

Cause. The audio could not be decoded, contains no audio stream, or exceeds the model's maximum audio duration. For async jobs this is set during the download / convert step or during the transcribe step's duration recheck.

Solution. Try transcribing the file directly in the Soniox Console to confirm whether the file itself is the problem. If it is, re-encode to a supported container/codec or split long audio into shorter segments. See the supported audio formats.

unauthenticated

HTTP 401

Surfaces: REST · STT WebSocket · TTS WebSocket · TTS REST

Cause. The request did not authenticate. The Authorization header was missing, or the API key was malformed, revoked, expired, scoped to a different environment, or longer than 256 characters. Temporary API keys can also fail here when they are expired, single-use and already consumed, or used for an action they were not issued for.

Solution. Pass a valid key as Authorization: Bearer <SONIOX_API_KEY> on REST and TTS REST, or in the api_key field of the start message on the WebSocket APIs. Get or rotate API keys in the Soniox Console. For client apps, use a temporary API key.

organization_balance_exhausted

HTTP 402

Surfaces: REST · Async · STT WebSocket · TTS WebSocket · TTS REST

Cause. The available balance has dropped to zero. Raised before the request runs, and also evaluated when an async job is about to start downloading or transcribing. In the async case the job moves to failed with this error_type.

Solution. Top up at Billing overview or enable autopay. Failed async jobs are not auto-retried; resubmit after funding.

organization_monthly_budget_exhausted

HTTP 402

Surfaces: REST · Async · STT WebSocket · TTS WebSocket · TTS REST

Cause. The organization has hit its configured monthly budget cap (monthly_budget_usd). Resets at the start of the next calendar month.

Solution. Raise the cap on the organization limits page, or wait for the month to roll over.

project_monthly_budget_exhausted

HTTP 402

Surfaces: REST · Async · STT WebSocket · TTS WebSocket · TTS REST

Cause. The project has hit its configured monthly budget cap.

Solution. Raise the cap on the project limits page, or wait for the month to roll over.

file_download_blocked

Surfaces: Async (failed transcription, no HTTP error)

Cause. The supplied audio_url could not be fetched for safety reasons: the URL resolved to a private or otherwise blocked IP (SSRF guard).

Solution. Use a publicly reachable URL whose host resolves to a routable IP. If the project or organization was deleted, recreate it (or use a different one) and resubmit.

file_download_failed

Surfaces: Async (failed transcription, no HTTP error)

Cause. Fetching audio_url failed: HTTP error (4xx / 5xx), DNS failure, TLS failure, connection timeout, or the server closed the connection mid-stream. 4xx responses are not retried; other transient failures are retried internally up to a bound before the job is marked as failed.

Solution. Make the URL reachable and stable. For files you control, prefer uploading via POST /v1/files rather than relying on a remote URL.

transcription_output_too_long

Surfaces: Async (failed transcription, no HTTP error)

Cause. The transcription completed but produced more output than the model is allowed to return in a single job. Not expected to occur in normal use. If you see this error_type, please contact support@soniox.com with the transcription ID.

file_not_found

HTTP 404

Surfaces: REST

Cause. No file with the given ID exists in the project the API key belongs to. Returned for IDs that never existed, IDs that were deleted, and IDs that exist but belong to a different project. Soniox does not leak cross-project existence.

Solution. Confirm the ID by listing files via GET /v1/files, and make sure the API key is scoped to the project that owns the file.

transcription_not_found

HTTP 404

Surfaces: REST

Cause. No transcription with the given ID exists in the caller's project. Same semantics as file_not_found: deleted, never existed, or belongs to a different project.

Solution. Confirm the ID with GET /v1/transcriptions, and check that the API key is scoped to the project that owns the transcription.

temp_api_key_session_expired

HTTP 403

Surfaces: STT WebSocket · TTS WebSocket · TTS REST

Cause. The temporary API key in use was created with a max_session_duration_seconds cap, and that duration has elapsed for the current session. The temporary key itself may still be valid for new sessions (subject to its other limits); only the current session has been cut off.

Solution. Create a new temporary API key (or use the same one if it has remaining uses) and start a new session. Long-running clients should refresh before the per-session cap rather than after.

request_timeout

HTTP 408

Surfaces: STT WebSocket · TTS WebSocket · TTS REST

Cause. A deadline was exceeded before the request could complete. Most common triggers:

  • STT WebSocket: client too slow on audio. The client failed to send audio chunks fast enough. For example, the initial chunk never arrived, or the decoder starved mid-stream.
  • TTS WebSocket: client too slow on text. After start, the client did not send any text within the allowed window, or stopped sending intermediate text chunks and never sent text_end to close the stream. The server cannot keep an idle stream open indefinitely.

Solution. Retry the request. For STT, ensure audio is streamed in real time or faster and that the first chunk is sent promptly after opening the connection. For TTS, send text chunks as soon as you have them and send text_end when the input is complete; if you have no more text to send but want to keep the stream alive, cancel it and start a new one when ready. If the timeout persists across retries, contact support@soniox.com with the request_id.

transcription_invalid_state

HTTP 409

Surfaces: REST

The transcription exists but is in a state that doesn't allow the requested operation. Read message for the specific reason.

Not completed yet

GET /v1/transcriptions/{id}/transcript while status is queued, downloading, or transcribing.

Solution. Poll GET /v1/transcriptions/{id} until status is completed, or configure a webhook on the transcription to be notified.

Failed

The transcript was requested for a transcription that ended in status: "failed".

Solution. Read error_type and error_message from GET /v1/transcriptions/{id} to see why, and submit a new transcription after fixing the cause.

No longer available

Transcript data was retained for a limited window after completion and has since been purged.

Solution. Re-submit the original audio as a new transcription.

Cannot delete while processing

DELETE /v1/transcriptions/{id} while status is transcribing.

Solution. Wait for status to reach completed or failed, then retry the delete.

limit_exceeded

HTTP 429

Surfaces: REST · STT WebSocket · TTS WebSocket · TTS REST

A single error_type covers many distinct limits. Read message (REST) or error_message (streaming) to find out which one was hit. The sub-causes below are grouped by what kind of limit triggered the response.

All current limits and your usage are visible in the Soniox Console. Per-product reference: Async STT, Real-time STT, REST TTS, Real-time TTS.

Requests per minute (RPM)

Too many calls of the same kind in a 60-second window, evaluated per organization or per project. RPM limits exist for:

  • WebSocket transcription
  • Async transcription
  • File management
  • Text-to-Speech
  • Temporary API key creation
  • Usage logs

Solution. Slow down, batch where possible, or raise the limit in the console: organization limits or project limits.

Concurrent requests

Too many simultaneous in-flight requests on the organization or project. Applies to streaming workloads such as STT WebSocket, TTS WebSocket, and TTS REST.

Solution. Reduce parallelism in the client, or request a higher concurrent-requests cap in the console.

The TTS WebSocket also enforces a per-connection cap on simultaneous streams, which surfaces as the separate max_concurrent_streams_reached error_type.

Total file count / total file size (GB)

Adding this file would put the organization or project over its retained-storage cap (files_total_count or files_total_size_gb).

Solution. Delete unused files via DELETE /v1/files/{id}, or raise the cap in the console.

Pending file count

Too many uploaded files are awaiting transcription (transcribe_async_pending_num_files).

Solution. Wait for in-flight transcriptions to complete, then retry.

Total transcription count / pending transcription count

Analogous caps on the number of stored transcriptions (transcribe_async_total_num_files, transcribe_async_pending_num_files).

Solution. Delete completed transcriptions with DELETE /v1/transcriptions/{id}, or raise the cap.

internal_error

HTTP 500

Surfaces: REST · Async · STT WebSocket · TTS WebSocket · TTS REST

Cause. Unhandled server-side exception, or an unrecoverable internal inconsistency.

Solution. Retry once. If the error persists, contact support@soniox.com and include the request_id from the response.

service_unavailable

HTTP 503

Surfaces: STT WebSocket · TTS WebSocket · TTS REST

Cause. The service cannot accept the request right now. Concrete sub-causes include a backend model service being overloaded, encoder or decoder cache exhausted, the server gracefully shutting down, the deployment-level session-duration cap firing, or no eligible model backend being available. The numeric (code N) in the message identifies the specific sub-cause for support triage.

Solution. Retry with exponential backoff. The condition is transient; the retry will typically be routed to a healthy backend. If retries consistently fail, contact support@soniox.com with the request_id and the (code N) from the error message.


Getting help

If you can't determine the cause from error_type and message, or if an internal_error keeps recurring, contact support@soniox.com and include:

  • The request_id from the error response.
  • The error_type and message (or error_message).
  • The endpoint and HTTP method, or for async failures the transcription ID.
  • A short description of what you were trying to do.