Reference
Realtime message reference
Every frame the realtime WebSocket accepts and emits, plus close codes and limits.
The realtime WebSocket uses a deliberately small protocol. Audio from the client travels as binary frames; everything else, in both directions, is a JSON text frame with a type field.
/v2/realtime/wsAuthenticated with a short-lived session tokenConnection parameters
All configuration is passed as query parameters when opening the socket. Use the same values you declared when minting the token.
| Parameter | Required | Default | Notes |
|---|---|---|---|
token | yes | none | Session token from POST /v2/realtime/token. Connect before expires_at. |
sample_rate | no | 16000 | Sample rate of the PCM16 audio you send, 8000 to 48000 Hz. |
model | no | whisper-voicekit-realtime-pro | whisper-voicekit-realtime-pro or whisper-voicekit-realtime. |
language_code | no | automatic | One of en, en_au, en_uk, en_us, es, de, fr, pt, it. Omit for automatic multilingual transcription. |
medical_mode | no | false | Medical vocabulary tuning. Applies when the language is en, es, de, or fr; ignored otherwise. |
Passing a language_code outside the supported set fails the session with an error event followed by a close.
Client to server
| Message | Frame type | Purpose |
|---|---|---|
| Audio chunk | binary | Raw pcm_s16le mono audio at the declared sample rate. |
{"type": "stop"} | text | Flush pending transcripts, finalize the session, and trigger the done close handshake. |
These are the only two frames the session accepts. Other text frames are ignored, so there is no mid-session configuration: settings are fixed by the query parameters for the life of the session.
Server to client
| Message | When | Purpose |
|---|---|---|
ready | once, after connect | The session is live; start sending audio. |
transcript | continuously | Partial and final transcripts for each turn of speech. |
reconnect | at the session cap | The 55 minute cap was reached; open a new session to continue. |
error | on failure | The session could not start or continue; a close follows. |
done | once, at the end | Final frame before the server closes the socket. |
ready
{ "type": "ready" }Sent once the session is accepted and transcription is running. Audio sent before ready is not guaranteed to be processed, so buffer locally until it arrives.
transcript
{
"type": "transcript",
"text": "so the quarterly numbers look",
"end_of_turn": false,
"formatted": false,
"words": [
{ "text": "so", "start": 1200, "end": 1330, "confidence": 0.99 },
{ "text": "the", "start": 1330, "end": 1420, "confidence": 0.98 }
]
}| Field | Type | Notes |
|---|---|---|
text | string | Transcript of the current turn so far, or the full turn when final. |
end_of_turn | boolean | false for partials, true when the turn is complete. |
formatted | boolean | true on the restatement of a finished turn with punctuation and casing applied. Replace the raw final turn with it. |
words | array | Word objects with text, start, end (milliseconds), and confidence (0 to 1). |
reconnect
{ "type": "reconnect", "message": "Session limit reached." }Sent when the session reaches its 55 minute cap. The server finalizes the session and closes; mint a fresh token and open a new session to continue streaming.
error
{ "type": "error", "message": "Unsupported realtime language." }| Message | Cause |
|---|---|
Realtime transcription is unavailable. | The service is temporarily unable to accept realtime sessions. |
Unsupported realtime language. | The language_code is outside the supported set. |
Could not start realtime transcription. | The session failed to start; retry with backoff. |
done
{ "type": "done" }The last frame of every session that ends normally. After done the server closes the connection; no further messages follow.
Close codes
| Close code | Meaning |
|---|---|
4401 | The token is missing, expired, or not a realtime session token. Mint a new token. |
4400 | The model query parameter is unknown or not a realtime model. |
1000 | Normal closure after the done message. |
Session limits and billing
- Sessions are capped at 55 minutes. At the cap you receive
reconnectand the session is finalized; open a new session to continue. - Connect before the token's
expires_at; a token can be minted with a lifetime of 60 to 3600 seconds. - Billing is metered per second of connection time at the model's session-hour rate, from the moment the session is accepted until the socket closes.