Skip to main content
Ambient streaming opens a WebSocket on GET /ws/stream after you create a session. Unexpected closes usually come from auth, frame format, keep-alives, or ending the stream in the wrong order. Closing the socket alone does not end the ambient session or start note generation.

Common causes

  • Opening /ws/stream before create succeeds, or after the session leaves CREATED (handshake returns FailedPrecondition).
  • Bad handshake auth (wrong Sec-WebSocket-Protocol order or headers).
  • Binary frames, non-JSON payloads, or multiple JSON objects in one frame.
  • No audio for 25 seconds while the stream is active, or no KEEP_ALIVE while paused.
  • Missing RU9G, or calling REST end without the documented end sequence.

Fix

1

Confirm Create and Session State

Create the ambient session first and store ambient_session_id. Open /ws/stream only while status is CREATED. Reconnect with the same ID only while status stays CREATED. Otherwise the handshake returns FailedPrecondition.
2

Authenticate the Handshake

In the browser, set Sec-WebSocket-Protocol to SukiAmbientAuth,<sdp_suki_token>,<ambient_session_id> (token before session ID). Non-browser clients use the documented Ambient WebSocket upgrade headers.
3

Send JSON Text Frames in Order

Send one UTF-8 JSON object per text frame. Order per segment: START_TIME โ†’ Base64 LINEAR16 PCM in AUDIO / data โ†’ optional EVENT โ†’ final AUDIO with "data": "RU9G". Do not send binary audio frames.
4

Keep the Connection Alive

While audio is flowing, send audio at least every 25 seconds. While paused, send {"type":"EVENT","event":"KEEP_ALIVE"} at least every 5 seconds. Ambient supports pauses of up to 30 minutes when keep-alives continue.
5

End in Order

After the last PCM chunk, send RU9G, close the WebSocket, then call REST end. Then poll status before you retrieve notes.
Do not send Dictation-style AUDIO_END on ambient /ws/stream. Use RU9G. See Ambient streaming wire format.

Next steps

End ambient after streaming - RU9G, close socket, then REST end Empty notes after end session - Poll status before content APIs WAV header streamed as audio - Strip RIFF headers before Base64 PCM Build an ambient streaming client - End-to-end create, stream, and retrieve Dictation WebSocket handshake - Different endpoint and wire format
Last modified on September 29, 2026