Skip to main content

Message Protocol

All control messages are JSON. Audio data is sent as binary WebSocket frames.

Client → Server

ActionMessageDescription
Start session{"action": "start"}Start the session. Wait for {"state": "listening", ...} before sending audio.
Stop session{"action": "stop"}Signal end of audio. The server drains remaining audio and sends {"state": "stopped"} before closing.
Stream audio<binary>PCM WAVE mono 16 kHz frames. See Audio Formats.

Sessions cannot be restarted. Disconnect and reconnect to start a new one.

Server → Client

State changes

MessageDescription
{"state": "listening", "session_id": "<id>"}Session is ready. session_id is the unique ID for this session. You can now send audio.
{"state": "stopped"}Session has ended. The connection will close.
{"state": "shutting_down", "at": <unix_timestamp>}Server will shut down at the given time (up to 3600 s in the future). Finish your session before then.

Transcription results

Results arrive continuously as audio is processed.

Partial results

Some sessions emit interim results that may change:

{"partial": "text so far"}

These are not final and will be replaced. Clients must also support sessions that only send final results.

Final results

{
"result": [
["word", time_start_ms, time_end_ms, confidence],
["word", time_start_ms, time_end_ms, confidence]
],
"text": "full sentence as a string"
}
FieldTypeDescription
textstringFull sentence combining all words in this result.
resultarrayPer-word detail. Each entry: [word, start_ms, end_ms, confidence].
result[n][0]stringRecognized word.
result[n][1]integerWord start time in milliseconds (relative to total audio sent).
result[n][2]integerWord end time in milliseconds.
result[n][3]floatConfidence score 0–1.
speakerstring | nullSpeaker label when diarization is active. Optional field.
sconffloat | nullSentence-level confidence. Optional field.
channelinteger | nullAudio channel index. Optional field.
note

Timestamps are based on the total audio processed, not the wall-clock session duration. This means you can send audio at up to 2× real-time speed and timestamps will still be correct relative to the source audio.

Example

{
"result": [
["Je", 12046, 12286, 1.0],
["hoort", 12286, 12526, 1.0],
["natuurlijk", 12526, 12796, 1.0],
["zeker", 12796, 13096, 1.0],
["verhalen", 13666, 14055, 0.9997]
],
"text": "Je hoort natuurlijk zeker verhalen"
}

Errors

MessageDescription
{"error": "Session not started"}Audio was sent before {"action": "start"} was acknowledged.
{"error": "backend already listening"}{"action": "start"} was sent while a session is already active.
{"error": "restarting of sessions is not supported"}Cannot restart after {"action": "stop"}. Reconnect instead.
{"error": "unable to start backend"}The transcription service could not start. Contact support if this persists.
{"error": "engine_not_responding"}The transcription service stopped responding. Contact support if this persists.
{"error": "unauthenticated"}Binary audio was received before the token was authenticated.
{"error": "license_missing_entitlement"}On-prem license does not include the realtime entitlement.

WebSocket Close Codes

CodeReasonDescription
4400missing_language?language= parameter was not provided.
4400invalid_language?language= was provided but is not available for your organization.
4402no_subscription_foundNo active realtime subscription found for this token's organization.
4403invalid_s2t_tokenToken is invalid, deleted, or not a realtime-type token.
4403unauthenticatedNo token provided and no {"action": "start"} with a key field.
4444server_shutdownServer is performing an emergency shutdown. Reconnect immediately.
4451license_missing_entitlementOn-prem license does not include realtime.