Connecting
Open a WebSocket to themedia_url from the join response, with the media_token as a bearer credential:
WebSocket) pass ?token=<media_token> instead. Always use the media_url from the join response.
If the upgrade is refused, the HTTP response says why:
Frames
Binary frames are audio: PCM16 little-endian, mono, at the session’s sample rate.- From X: the mix of everyone in the call except your agent, one 20 ms frame at a time in real time (at 16 kHz, 320 samples = 640 bytes). Silence arrives as zeros, so the stream never stalls.
- To X: your agent’s voice, in chunks of any size. Send it as fast as you produce it; X queues it and plays it into the call in real time.
type.
Session lifecycle
session.created: the token was accepted. Carries the audio format.session.waiting: only when the join response saidrequires_approval. The host was asked to admit your bot. The session ends withrejectedif the host declines, orapproval_timeoutif nobody answers within 5 minutes.session.joined: your agent is in the call and audio flows. Carries the people already there.session.ended: the last event. X then closes the socket.
Events (X → your agent)
A participant is
{"user_id": "…", "is_guest": false, "muted": false}. is_guest marks logged-out guests and room systems. Participants are the people whose audio is in the call. muted is left out until they have muted or unmuted, and a logged-out guest can first appear with is_guest: false and be corrected by a participant.updated.
Error codes
Why a session ended
Commands (your agent → X)
Turn-taking
Speech detection runs on X’s side for each participant:- On
speech.startedwhile your agent is talking, sendaudio.clearto stop it mid-sentence, or keep talking if you prefer. - Feed the call audio to your model continuously; most realtime models do their own voice-activity detection too.
- Send
audio.markafter each agent turn to learn when the listener has heard it, for example before leaving after “goodbye”.