session.update.
1
Update the base URL and API key
- OpenAI SDK
- Raw WebSocket
If you are using the official OpenAI SDK, point the client at the Boson endpoint and supply your Boson API key:
2
Choose a model
Use If neither the URL nor the first
higgs-realtime in place of gpt-realtime. As on OpenAI, the ?model= query parameter in the connection URL selects the model; you can also set (or override) it in session.update:session.update names a model, the update fails with an error.3
Review your session config and prompts
- Check the compatibility notes below: a few OpenAI session fields are inert or rejected here, and
output_modalitiesmust be exactly one modality. - Revisit your system prompt: instructions written to patch quirks of another model usually aren’t needed — start from a short, direct prompt and add back only what proves necessary.
OpenAI Realtime API Compatibility
The event protocol is compatible with OpenAI’s GA Realtime API: most OpenAI Realtime clients work by changing the endpoint towss://api.boson.ai/v1/realtime and supplying a Boson API key. The differences are listed below, roughly in the order a migrating client will hit them.
Connection and lifecycle
Connection and lifecycle
- WebSocket only. OpenAI’s WebRTC and SIP transports are not available — no
/v1/realtime/callsendpoints, nooutput_audio_buffer.*events, no DTMF events. WebRTC support is in progress. - Model selection works as on OpenAI. The
?model=query parameter selects the model;session.modelin asession.updateoverrides it. If neither is set, the firstsession.updatefails. Usehiggs-realtimein place ofgpt-realtime. session.createdacknowledges your firstsession.update. OpenAI emitssession.createdimmediately on connect; here the server sends nothing until you sendsession.update. Don’t wait forsession.createdbefore configuring the session.conversation.createdis never emitted.- Realtime sessions only.
session.typeis always"realtime"; OpenAI’s transcription-only sessions ("type": "transcription") are not supported. - Ephemeral keys:
POST /v1/realtime/client_secretsworks the same way (expires_after.seconds, 10–7200, default 600), but asessionobject in the request body is ignored — configure the session over the WebSocket after connecting. Keys are prefixedbai-eph-rather thanek_.
Session configuration
Session configuration
output_modalitiesmust be exactly one of["audio"]or["text"]— mixed output is not supported.- Audio formats:
audio/pcmacceptsrate8000 / 16000 / 24000 / 48000 (OpenAI: 24000 only), andaudio/opusis available as an extension.audio/pcmuworks as on OpenAI;audio/pcma(G.711 A-law) is not supported. - Voices: OpenAI voice names (
alloy,marin,cedar, …) don’t exist here — use"default", a Boson preset, or a customvoice_<id>(see Voices). Non-default voices are validated atsession.updatetime, so an OpenAI voice name fails the update. - Input transcription: set
transcription.modeltohiggs-stt-3.1; OpenAI transcription models are not available.languageworks as on OpenAI; OpenAI’sprompt,keywords,languages, anddelaytranscription options are ignored. - Tools:
functiontools only. MCP tools ("type": "mcp"), tool approvals, and themcp_*events are not supported. temperatureis accepted at the session level (default0.7) — an extension over OpenAI’s GA schema.- Turn detection:
server_vadandsemantic_vadboth exist, with differences: theserver_vadthreshold defaults to0.55(OpenAI:0.5), andturn_detection.min_speech_duration(minimum speech length in seconds before a segment starts, default0.125) is an extension.create_response,interrupt_response, andeagernessare accepted but have no effect — a response is always generated on end of turn, and barge-in always interrupts.idle_timeout_msis rejected with an error if set. - Rejected session fields (fail the
session.updateif set):include,prompt,tracing. truncationsupports the"auto"/"disabled"string forms only (noretention_ratioobject), and the mechanism differs — see Context management below.
Events
Events
input_audio_buffer.appendaccepts at most 1 MiB of base64 audio per event (OpenAI: 15 MiB) — stream microphone audio in small chunks.conversation.item.createsupports text content only:input_audioandinput_imagemessage contents are skipped, andsystem-role messages are rejected. User messages useinput_textcontent and assistant messages usetextcontent (OpenAI’soutput_texttype is not recognized).function_callandfunction_call_outputitems work as on OpenAI.- Input transcription arrives only as
conversation.item.input_audio_transcription.completed— the.delta,.failed, and.segment(diarization) events are never emitted. - Also never emitted:
conversation.item.done,rate_limits.updated, andinput_audio_buffer.timeout_triggered. Don’t gate client logic on receiving them. - Extra event types not in OpenAI’s schema:
response.output_audio_transcript.length,conversation.context.summarized,session.idle_timeout, andsession.max_duration_reached. Make sure your client tolerates unknown event types rather than failing on them.
Responses
Responses
response.donereportsstatus"completed"or"cancelled"only, and itsusageandstatus_detailsfields are currently alwaysnull(OpenAI populates per-response token usage). Responsemetadatais echoed onresponse.createdonly, not onresponse.done.
Context management
Withtruncation: "auto" (default), long conversations are summarized in the background before they exceed the model’s context window: older messages are condensed into a summary item (originals stay retrievable) and the server emits conversation.context.summarized with the affected summarized_item_ids. Set truncation: "disabled" to opt out. This differs from OpenAI’s Realtime API, which drops old messages instead of summarizing them — and note that conversation.context.summarized is not an OpenAI event type, so make sure your client tolerates it rather than failing on unknown events (the official OpenAI SDK may not surface or parse it).
Session limits
Session limits are enforced server-side and cannot be changed viasession.update:
- Max session duration: the server sends
session.max_duration_reached(carryingmax_duration_sec) and closes when a session reaches its wall-clock cap. - Idle timeout: after 5 minutes without detected user speech, the server sends
session.idle_timeout(carryingseconds_idle) and closes. - Quota refusals: if the account’s billing entitlement is refused mid-session, the server sends an
errorevent with the upstream message (type: "insufficient_quota") and closes the WebSocket with code4429.