Skip to main content
Authentication is the standard Authorization: Bearer header, or ?api_key=<key> in the URL. The OpenAI SDK derives this URL from the same client you configured for REST — a working example is in Migrate from OpenAI.

Events

The endpoint speaks the Realtime GA event names (response.output_audio.delta and the rest of the GA set) — what current openai packages emit, even though the Node module path still says beta. Supported client events: session.update, transcription_session.update, conversation.item.create, conversation.item.delete, input_audio_buffer.append / commit / clear, response.create, response.cancel. conversation.item.truncate is accepted and does nothing — it cuts a previous assistant message’s audio, and none is retained server-side — so it is the one client event that sends no acknowledgement back. Any other event type comes back as an unknown_event_type error. One response at a time per session: a second response.create while one is running returns the response_already_active error.

Audio formats

Output formats: pcm16, wav, mp3, opus — as a string ("mp3") or the GA object form ({"type": "audio/mp3", "rate": 32000}). audio/pcmu and audio/pcma are rejected explicitly. Both spellings reset the rate when they carry no rate of their own — to that format’s default (audio/pcm → 24000, wav and mp3 → 44100, opus → 48000), not to what the session was using before — so set rate explicitly when you switch formats mid-session. session.updated echoes the resulting output and input format — rate included — so you can read back what the session settled on. Supported sample rates per codec are in Audio formats.

Voice and speed

voice is a Fish voice ID, accepted both at the legacy top-level session.voice and at the GA session.audio.output.voice position; session events echo it at the GA position. speed follows the same two-position rule and the REST endpoint’s 0.25–4.0 range — out of range returns an invalid_speed error event instead of synthesizing.

Turn detection

Turn detection is yours to drive: send input_audio_buffer.commit to end an utterance. Any turn_detection with a type — server_vad, semantic_vad, or anything else, in either the GA or the legacy top-level position — is refused with unsupported_turn_detection rather than accepted and ignored, and session.created reports "turn_detection": null. Likewise, an output_modalities that omits "audio" is refused: this socket always produces audio.

Transcription

Transcription works over the same socket: input_audio_buffer.append base64 audio, then input_audio_buffer.commit — the transcript arrives as conversation.item.input_audio_transcription.completed, and a failed transcription arrives as the matching conversation.item.input_audio_transcription.failed (the buffered audio is kept, so you can retry). The socket returns the transcript text only — for word timestamps use POST /v1/audio/transcriptions. Both official ways of opening a dedicated transcription session work: send transcription_session.update, or connect with ?intent=transcription in the URL. Either way the session object comes back as realtime.transcription_session in transcription_session.created / transcription_session.updated. With ?intent=transcription and no model in the URL, the session defaults to fish-audio/transcribe-1 rather than a TTS model.

Limits

Session limits — text and audio caps per conversation item, item counts, frame size — are in the limits table.

Migrate from OpenAI

A runnable Realtime example with the official SDK.

Compatibility

The full contract: mappings, limits, and explicit refusals.