WebSocket API
Learn how to use and integrate Soniox Text-to-Speech WebSocket API.
Overview
The Soniox WebSocket API provides real-time Text-to-Speech with low latency over a persistent WebSocket connection.
It supports:
- Voice selection
- Audio output settings (
audio_format,sample_rate,bitrate) - Streaming text input for continuous generation
- Multiple concurrent Text-to-Speech streams on one WebSocket connection (multiplexed by
stream_id, up to 5 active streams per connection)
WebSocket endpoint
Connect to the API using:
Configuration
Before streaming text for a stream, send a configuration message on the WebSocket connection.
Send one config message per stream_id you want to start.
Parameters
api_keyRequiredstringYour Soniox API key. Create API keys in the Soniox Console.
stream_idRequiredstringClient-generated stream identifier. Must be unique among active streams on the same WebSocket connection.
You may reuse a stream_id only after its previous stream is terminated.
languageRequiredstringLanguage code. See the list of supported languages and their ISO codes.
"en"sample_ratenumberOutput sample rate in Hz. Required for raw audio formats. See audio formats.
24000Text streaming
After sending the configuration message for a stream, send text messages for that same stream_id:
Final text chunk:
Ending the stream
Normal completion
A stream completes in this order:
- The client sends a text message with
text_end: truefor the targetstream_id.
- The server sends the last audio payload with
audio_end: true.
- The server sends a final stream event with
terminated: true.
What audio_end means
audio_end: true marks the last audio chunk for that stream. No more audio payloads will follow.
You should still keep the stream open and wait for the terminal terminated: true event.
What terminated means
terminated: true indicates the server has fully closed the stream and released all stream resources.
Only after terminated: true it is safe to:
- reuse the same
stream_id - stop tracking stream state
- consider the stream lifecycle complete
Treat the stream as complete only after you receive terminated: true.
Error completion
If an error occurs for a stream:
- The server sends an error response for that
stream_id.
- The server sends
{"terminated": true}for that samestream_id.
- The failed stream is removed, but the WebSocket connection stays open and other streams can continue.
Client-initiated cancellation
To cancel a stream, send a cancel message. The server finalizes the stream and does not send audio chunks.
Cancel request:
Finalization response:
Error handling
One failed stream does not close the whole WebSocket connection.
-
Stream-level runtime errors (inside a running stream):
- The server sends an error response for that
stream_id. - The server then sends
{"terminated": true}for that samestream_id. - Only that stream ends; other active streams continue.
- The server sends an error response for that
-
Validation/input errors (invalid start/text message, unknown stream, malformed stream message):
- The server sends an error response.
- The WebSocket message loop stays alive, so valid streams can continue.
-
Connection-level failures (WebSocket disconnect/read/write failure, forced shutdown):
- The WebSocket connection closes.
- All streams on that connection end.
Response
Server messages are JSON and include stream_id for stream-specific events.
Successful audio messages include audio (base64 chunk), and terminal messages include terminated.
Terminal stream message:
Error response
If an error occurs, the server returns an error message:
For stream-level runtime errors, this is followed by {"terminated": true} for the same stream_id.
Full list of possible error codes and messages
The request is malformed or contains invalid parameters.
Invalid message formatExpected text messageMissing modelModel name is too long (max length 50).Missing stream_idStream ID is too long (max length 256).Missing languageLanguage is too long (max length 50).Missing voiceVoice is too long (max length 50).Missing audio_formatAudio format is too long (max length 50).API key is too long (max length 250).Text is too long (max length 5000).Stream (stream_id) not found. Send a start message first.Stream (stream_id) already existsStream (stream_id) has already received text_endMaximum concurrent streams (N) reached
Authentication is missing or incorrect. Ensure a valid API key is provided before retrying.
Invalid API key.Missing API key.Invalid/expired temporary API key.
The organization's balance or monthly usage limit has been reached. Additional credits are required before making further requests.
Organization balance exhausted. Please either add funds manually or enable autopay.
The client did not send a start message or sufficient text data within the required timeframe. The connection was closed due to inactivity.
Request timeout.
A usage or rate limit has been exceeded. You may retry after a delay or request an increase in limits via the Soniox Console.
Rate limit for your organization has been exceeded.Rate limit for your project has been exceeded.Your organization has exceeded max number of concurrent requests.Your project has exceeded max number of concurrent requests.
An unexpected server-side error occurred. The request may be retried.
The server had an error processing your request. Sorry about that! You can retry your request, or contact us through our support email support@soniox.com if you keep seeing this error.
Cannot continue request or accept new requests.
Cannot continue request (code N). Please restart the request. Refer to: https://soniox.com/url/cannot-continue-request
Code example
Prerequisite: Complete the steps in Get started.
See on GitHub: soniox_sdk_realtime.py.
See on GitHub: soniox_sdk_realtime.js.
See on GitHub: soniox_realtime.py.
See on GitHub: soniox_realtime.js.