WebSocket protocol
Munsit runs two WebSockets: one that streams text in and returns audio chunks, and one that streams audio in and returns live transcripts. This page is the full wire protocol for both — connection, auth, message shapes and lifecycle.
The two sockets
Same host, same /api/v1 prefix, opposite directions.
| Socket | Path | You send | You receive |
|---|---|---|---|
| WSS Text to speech | /websocket/text-to-speech | JSON messages carrying text chunks | Base64-encoded PCM audio chunks |
| WSS Speech to text (legacy) | /websocket/speech-to-text | Audio chunks (WAV, then WAV or raw PCM) | Cumulative Arabic transcript strings |
Text to speech — audio out
wss://api.munsit.com/api/v1/websocket/text-to-speech?x-api-key=YOUR_API_KEY
Authentication. API key via the x-api-key query parameter, or in the initial connection message as x_api_key. After the socket opens you must send an initConnection message before any text.
initConnection fields.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "initConnection". |
model_id | string | No | Model ID to use (default: "faseeh-v1-preview"). |
voice_id | string | Yes | The voice ID to use for synthesis. |
voice_settings | object | No | Voice configuration. |
voice_settings.stability | number | No | Stability setting (default: 0.5). |
voice_settings.similarity_boost | number | No | Similarity boost (default: 0.75). |
voice_settings.speed | number | No | Speed setting, range 0.7–1.2 (default: 1.0). |
output_format | string | No | Audio output format: "pcm_8000", "pcm_16000", "pcm_22050", "pcm_24000" (default: "pcm_24000"). This socket tops out at 24 kHz — for 48 kHz engine-native audio use the HTTP endpoints (synthesize, streaming output, voice preview) with sample_rate=48000. |
x_api_key | string | No | API key (if not provided in query parameter). |
text fields and the audio response.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "text". |
text | string | Yes | Text to convert to speech. |
flush | boolean | No | Force generation of audio even if buffer is small (default: false). |
try_trigger_generation | boolean | No | Attempt to trigger generation immediately (default: false). |
| Response field | Type | Description |
|---|---|---|
audio | string | Base64-encoded PCM audio data. |
sampleRate | number | Sample rate of the audio (typically 24000 Hz). |
Speech to text — audio in
WS /websocket/speech-to-text remains available for existing integrations but receives no new recognition features — no word timestamps, turn events, hotwords, confidence, sentiment or gender. New integrations should use WS /api/v1/listen. Finalization (end_of_stream) and min_buffer_seconds were added here as correctness fixes, not as new capability. It is frozen, not scheduled for removal, and stays available for existing integrations; any change to that would be announced on the Changelog.wss://api.munsit.com/api/v1/websocket/speech-to-text?x-api-key=YOUR_MUNSIT_API_KEY&model=munsit
Authentication. The server accepts any one of three methods; at least one is required. If auth is invalid, the connection is rejected or closed — there is no dedicated authentication_error event.
| Field | Type | Required | Description |
|---|---|---|---|
x-api-key | string | No | API key in header or query. |
Authorization | string | No | Bearer token header. |
token | string | No | Token query param fallback for browsers. |
| Query parameter | Type | Required | Description |
|---|---|---|---|
model | string | No | ASR model to use: munsit (default) or munsit-en-ar (mixed Arabic-English with code-switching). |
min_buffer_seconds | number | No | Seconds of audio that must accumulate before an interim transcription is emitted. Default 0.5, clamped to 0.1–5.0. Lower it for faster partials on short answers. It does not gate the final result — the pass triggered by end_of_stream runs at any duration. |
Audio input. The first chunk must be WAV (with headers); subsequent chunks can be WAV or raw PCM. audioBuffer must be an array of byte values (0–255). Any chunk size works — 100–500 ms is typical for live audio, and smaller chunks lower latency without changing what is recognized. Two client message formats are accepted:
Server events.
| Event | Direction | Type | Meaning |
|---|---|---|---|
audio_chunk | client → server | Array<Uint8> | Audio bytes; first chunk should include full WAV headers, PCM accepted after. |
end_of_stream | client → server | — | Signals end of audio. Transcribes whatever is still buffered, at any duration, and replies with a final transcription then finalized. Send this before closing. |
transcription | server → client | string | Cumulative Arabic transcript generated from all received chunks. Carries an isFinal boolean. |
finalized | server → client | string | The complete transcript for the session. Emitted once, in response to end_of_stream. Safe to close the socket after this. |
transcription_error | server → client | string | Error details during streaming transcription. |
Finalizing a stream. Closing the socket does not flush buffered audio, and waiting after the audio stops does not produce a final result — an interim hypothesis stays isFinal: false indefinitely, and audio shorter than min_buffer_seconds produces no event at all. Send end_of_stream, wait for finalized, then close.
min_buffer_seconds, so end_of_stream is the only thing that will return them. Clients that open one socket per utterance must send it every time. On WS /api/v1/listen the equivalent is the CloseStream control frame, and the flag is is_final.Recommended flow. Connect with auth → confirm the socket is open on the client side → emit audio_chunk payloads as audio arrives → listen for transcription_error and handle failures → listen for transcription and render live text updates → send end_of_stream when the speaker stops → wait for finalized → close the socket.
Errors
On the TTS socket, errors arrive as a typed JSON message. On the STT socket, listen for the transcription_error event; invalid auth is handled by rejecting or closing the connection.
{
"type": "error",
"errorCode": 40101,
"errorMessage": "Invalid API key"
}| Field | Type | Description |
|---|---|---|
type | string | Always "error". |
errorCode | number | Numeric error code (e.g. 40101, 40001). |
errorMessage | string | Human-readable error message. |
Full lifecycle example
Open, initialize, stream text, collect audio, handle errors — the complete TTS round-trip in the browser or Node.
Best practices
Five habits that keep streams smooth.
| Practice | Why |
|---|---|
| Always initialize | Send initConnection immediately after opening the TTS connection. |
| Handle errors | Check for error messages in responses. |
| Flush when done | Use flush: true when sending the last text chunk to ensure all audio is generated. |
| Close gracefully | Send closeConnection before closing the WebSocket. |
| Buffer audio | Collect audio chunks and play them sequentially for smooth playback. |
Working with an AI assistant? Every page is available as Markdown: add .md to the URL, or send an Accept: text/markdown header. For the whole documentation in one request, point it at llms-full.txt; the page index is llms.txt. Or use Copy Page, top right.
