oai-events.
The assistant’s behavior — instructions, model, voice, tools, transcription and interruption settings — is configured on the assistant itself. The WebRTC connection carries media and events only.
Use WebRTC for browser and mobile clients. For a server-side integration that streams PCM audio, use the conversation WebSocket instead.
How a call is set up
- The browser creates an
RTCPeerConnectionthat relays through Telnyx TURN, adds the microphone track, theoai-eventsdata channel and, for an avatar or camera, a video transceiver. It waits for ICE gathering to complete. - The browser sends the SDP offer to the application server.
- The application server forwards the offer to
POST /v2/ai/assistants/{assistant_id}/callswith its Telnyx API key. The API key never reaches the browser. - Telnyx starts a conversation with the assistant and returns the SDP answer.
- The application server returns the answer to the browser, which applies it.
- Media and the data channel connect. The conversation, including the assistant’s greeting, starts once the
oai-eventsdata channel opens.
Migrate an existing avatar client
Replace the avatar WebSocket connection and its signaling frames with the call setup above. Do not sendavatar.session.ready, avatar.webrtc.offer, avatar.ice_candidate, avatar.webrtc.answer, or avatar.media.ready over the data channel. Mid-call renegotiation uses the separate webrtc.offer and webrtc.answer events described below.
The greeting starts when the data channel opens, rather than waiting for the previous avatar.media.ready playback acknowledgement. Handle rejected media-element play() promises and provide a user action to start playback. An open data channel does not establish that the browser is playing the media; autoplay restrictions can prevent the user from hearing the beginning of the greeting.
Configure ICE servers
Telnyx relays the call’s media only through Telnyx TURN, and Telnyx TURN relays only between Telnyx addresses. Configure the client to relay through Telnyx TURN withiceTransportPolicy: "relay". Direct connections and third-party TURN servers do not connect.
turn.telnyx.com on UDP or TCP port 3478. TCP on port 3478 is not an HTTPS/443 fallback. If a firewall or VPN blocks both transports, the call cannot connect even when HTTPS requests succeed. Handle ICE gathering and connection failures in the client, and release local media tracks when setup fails.
Create the offer
Add the tracks and the data channel before creating the offer, then wait for ICE gathering to complete: Telnyx does not accept trickled candidates, so the offer must carry them.
All m-lines must share one transport (
a=group:BUNDLE), as browsers do by default.
Create the call
The application server forwards the offer with its Telnyx API key:
Send the offer as a
multipart/form-data body with an sdp field, or as a raw application/sdp body. The multipart form also accepts an optional session field to pass dynamic variables for this conversation:
201 Created with the SDP answer as an application/sdp body. Return the answer to the browser unchanged.
Every request to the relay starts a call billed to the Telnyx account. Authenticate and authorize the browser’s user before forwarding the offer, and rate-limit calls per user.
Errors
Errors return a JSON error object witherror.code:
Exchange events on the data channel
Theoai-events data channel carries the same JSON events as the conversation WebSocket, with these differences:
Every other event works as on the WebSocket, including speech detection and transcripts, text turns, interruption and barge-in,
response.cancel, tool calls and vision frames. Keep each serialized message below 1 MiB and within the connection’s negotiated pc.sctp.maxMessageSize. The SCTP limit can be smaller than the Telnyx event limit. Measure the UTF-8 bytes of the entire JSON string, including any base64 image and metadata, before calling send().
The assistant’s voice must stream PCM at 8, 12, 16, 24 or 48 kHz. Otherwise the call starts with an error event on the data channel:
Show an avatar
Beta: AI Assistant avatars are in beta. See the Avatars guide for configuration, voice compatibility and pricing. When the assistant has savedavatar_settings and the offer includes a video m-line that can receive VP8 (recvonly or sendrecv), the avatar’s video arrives on that video track and its voice on the audio track, already synchronized. Play both. An offer without a receivable video m-line starts a voice-only call, even when the assistant has an avatar. To keep a receivable video m-line, for example to send the camera, without the avatar, create the call with ?avatar=false; a video m-line added during the call then does not start the avatar either.
The data channel reports the avatar’s state with avatar.updated:
A runtime avatar failure also sends an
avatar.error event with error.fatal: false. The conversation continues; the voice switches back on the same audio track automatically.
Send the camera
To let the assistant see the caller, send the camera on the video m-line instead ofrecvonly. Add the camera track before creating the offer, in place of the recvonly transceiver:
sendrecv: the camera goes up and the avatar, if any, comes down on the same m-line. Telnyx samples the camera every 2 seconds into a JPEG of at most 1280 pixels wide, tagged camera, and buffers it for the vision tool. The assistant needs the vision tool and a vision-capable model; buffered frames do not trigger responses on their own. Image frames sent on the data channel are buffered the same way.
For camera or screen snapshots sent as image events, reduce JPEG quality or image dimensions until the complete message fits both data-channel limits. Reducing quality or dimensions can make small text and fine detail harder to interpret. These message-size limits apply to image events, not to the native camera RTP track described above.
Send only while the data channel is open, monitor bufferedAmount to avoid accumulating stale snapshots, and handle send() exceptions. If a frame cannot fit or be sent, surface the failure in the application’s camera-sharing UI; reducing the image and retrying are client responsibilities. A successful send() queues the message locally and does not confirm that the assistant has used the image.
Add video during a call
A call that started without a video m-line can add one. Add the transceiver, set the new offer as the local description, wait for ICE gathering, and send it on the data channel as awebrtc.offer event. Telnyx replies with a webrtc.answer event; apply it with setRemoteDescription:
error event instead:
End the call
Close the peer connection to end the call. Telnyx ends the conversation as soon as theoai-events data channel closes. When a client disappears without closing, for example after a network loss, Telnyx ends the conversation within seconds once media stops arriving.