Skip to content
For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Primary navigation
Theme

Sideband WebSocket

WS/v1/live/sessions/{session_id}/attach

Attach your backend server to an existing Live session with your OpenAI API key. For example, when your frontend connects over WebRTC, use this WebSocket to handle events and control the session from your backend.

Connection

wss://api.openai.com/v1/live/sessions/{session_id}/attach

session_id: string required · path

The ID of the existing session to attach to. Use the session ID returned when the session was created or accepted.

Authorization: Bearer $OPENAI_API_KEY required · header

Use your OpenAI API key from your backend server. Keep this key on your server; never expose it in frontend code.

Attaching does not create a session. The sideband first replays events from the preceding 3 seconds, including conversation events, call-progress events, and reflected input and output audio, then continues with new events. Older events are not replayed, so attach promptly. Replayed events retain their original event_id when present; deduplicate those events by event_id. Reflected audio events do not have an event_id. The primary connection carries live media. Do not send session.start or session.input_audio.append on this WebSocket.

Inputs

Client events

For a session using Responses delegation, update its tool choice. The delegation type cannot change. There is no required first message after attaching.

Example client eventsession.update
{
  "type": "session.update",
  "event_id": "update_1",
  "session": {
    "delegation": {
      "type": "responses",
      "responses": {
        "tool_choice": "required"
      }
    }
  }
}
All client events

Outputs

Server events

A configuration update is acknowledged with session.updated. Attaching alone does not generate a new session.updated event, but a recent one may be replayed. After replay, you receive new session events as they occur.

Example server event · excerptsession.updated
{
  "type": "session.updated",
  "event_id": "event_updated_1",
  "client_event_id": "update_1",
  "session": {
    "id": "live_123",
    "expires_at": 1788307200,
    "status": "active",
    "model": "gpt-live-1"
  }
}
All server events

Client events

session.update

Update the delegation settings or transcript triggers of an active Live session. The server acknowledges accepted changes with session.updated.

session: SessionUpdateConfig { delegation, triggers }

Sparse delegation and trigger updates. Omitted settings retain their values. The delegation type cannot change. Model, frontend instructions, audio, and startup input are immutable.

type: "session.update" (default: "session.update")

The Live client event type. Always session.update.

event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

session.input_audio.mute

Mute audio input to the Live model without closing the session. The server acknowledges with session.input_audio.muted.

type: "session.input_audio.mute" (default: "session.input_audio.mute")

The Live client event type. Always session.input_audio.mute.

event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

session.input_audio.unmute

Resume audio input to a Live model after muting it. The server acknowledges with session.input_audio.unmuted. An active audio fixture still pauses inference until playback finishes.

type: "session.input_audio.unmute" (default: "session.input_audio.unmute")

The Live client event type. Always session.input_audio.unmute.

event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

session.output_audio.fixture.play

Play one complete audio fixture through the session output. Send this event over the primary WebSocket or a server sideband. Audio must be raw mono PCM16 little-endian at 24 kHz, regardless of the session audio format, and at most 30 seconds. The entire payload is validated before model speech is interrupted and input is muted. Only one fixture can be active. fixture.playing acknowledges acceptance and fixture.played reports server mixer drain. These notifications are not exact transport-media boundaries. Input arriving during playback is dropped and not replayed.

audio: string

Base64-encoded raw mono PCM16 audio, little-endian, at 24 kHz. Do not include a WAV or other container header.

minLength1
maxLength1920000
type: "session.output_audio.fixture.play" (default: "session.output_audio.fixture.play")
event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

session.instructions.append

Append developer instructions to the Live conversation while it is running, optionally associating them with an existing client delegation. Rejected while an audio fixture is active. These instructions remain in conversation history through compaction and are included in future backend delegations. For external audio, describe content already delivered so the assistant does not repeat it.

content: string

Instruction text to append, limited to 500 tokens. This is a plain string, not an array of content parts.

delegation_id: string or null

Required, nullable. Set null for general session context, or use the ID from session.delegation.created for an existing client delegation. Non-null IDs are not accepted with Responses delegation.

minLength1
type: "session.instructions.append" (default: "session.instructions.append")

The Live client event type. Always session.instructions.append.

event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

session.thinking.append

Provide silent reasoning or progress context to the Live model, optionally for an existing client delegation. Rejected while an audio fixture is active.

content: string

Silent reasoning or progress context, limited to 500 tokens. It does not directly request speech, but can influence later speech and is not a secrecy boundary.

delegation_id: string or null

Required, nullable. Set null for general session context, or use the ID from session.delegation.created for an existing client delegation. Non-null IDs are not accepted with Responses delegation.

minLength1
type: "session.thinking.append" (default: "session.thinking.append")

The Live client event type. Always session.thinking.append.

event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

session.commentary.append

Provide context the Live model can communicate to the user, optionally for an existing client delegation. Rejected while an audio fixture is active.

content: string

Speakable context for the Live model, limited to 500 tokens. Use this for a result the model should communicate; use session.thinking.append for silent context.

delegation_id: string or null

Required, nullable. Set null for general session context, or use the ID from session.delegation.created for an existing client delegation. Non-null IDs are not accepted with Responses delegation.

minLength1
type: "session.commentary.append" (default: "session.commentary.append")

The Live client event type. Always session.commentary.append.

event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

decision.create

Evaluate the configured questions using the current conversation and Decision inputs. Reusing an event_id is rejected for the lifetime of the session.

event_id: string
minLength1
maxLength256
type: "decision.create" (default: "decision.create")

decision.item.create

Append an input item for future decisions without starting an evaluation or changing Live voice context.

item: Message { content, role, id, type } or Message { content, role, id, type } or Message { content, role, id, type } or 5 more
type: "decision.item.create" (default: "decision.item.create")
event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

decision.item.delete

Delete an input item from future decisions without starting an evaluation or changing Live voice context.

item_id: string
minLength1
type: "decision.item.delete" (default: "decision.item.delete")
event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

response.item.create

Add an input item to the Live session’s Responses backend. Requires Responses delegation; use response.create to request a response.

item: EasyInputMessage { content, role, phase, type } or Message { content, role, status, type } or ResponseOutputMessage { id, content, role, 3 more } or 30 more

An input item to append to the Responses backend conversation, such as a user message or a function tool result.

type: "response.item.create" (default: "response.item.create")

The Live client event type. Always response.item.create.

event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

response.create

Request a response from the Live session’s Responses backend, or continue a delegated response waiting for tool results. Requires Responses delegation.

type: "response.create" (default: "response.create")

The Live client event type. Always response.create.

event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

session.close

Request that the Live session close. The terminal session.closed event contains the close reason and final usage.

type: "session.close" (default: "session.close")

The Live client event type. Always session.close.

event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

transport.dtmf.send

Send one DTMF keypress to the SIP trunk through a Live sideband connection. This command is supported only for SIP calls. A successful send emits transport.dtmf.sent on sideband. If you provide event_id, the success notification includes it as client_event_id; a failure includes it as error.client_event_id. Send separate events for multiple keypresses.

event: string

The DTMF key to send: one of 0–9, A–D, *, or #.

pattern^[0-9A-D*#]$
minLength1
maxLength1
type: "transport.dtmf.send" (default: "transport.dtmf.send")
event_id: optional string or null

Optional client identifier for correlating this command with a server event's client_event_id or error.client_event_id.

maxLength512

Server events

transport.ringing

The outbound SIP provider leg is ringing or providing early media. Delivered only to sideband observers.

event_id: string
session_id: string

The canonical Live session ID.

type: "transport.ringing" (default: "transport.ringing")

transport.answered

The outbound SIP provider leg answered and media is established. Delivered only to sideband observers.

event_id: string
session_id: string

The canonical Live session ID.

type: "transport.answered" (default: "transport.answered")

transport.failed

An asynchronous outbound SIP setup failure. Delivered only to sideband observers.

error: object { code, message, type, param }
event_id: string
session_id: string

The canonical Live session ID.

type: "transport.failed" (default: "transport.failed")

session.started

Returned when a Live session has started. Contains the resolved session configuration, including server defaults.

event_id: string

The unique ID of the Live server event.

session: SessionResource { id, expires_at, model, 9 more }

The resolved Live session configuration and server-assigned session metadata.

type: "session.started" (default: "session.started")

The event type, always session.started.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.updated

Returned when a Live session update is accepted. Contains the resolved session configuration after the update.

event_id: string

The unique ID of the Live server event.

session: SessionResource { id, expires_at, model, 9 more }

The resolved Live session configuration and server-assigned session metadata.

type: "session.updated" (default: "session.updated")

The event type, always session.updated.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.input_audio.muted

Acknowledges a session.input_audio.mute command. An independent input mute sends silence to the model and preserves sideband audio reflection. Fixture playback does not emit this event.

event_id: string

The unique ID of the Live server event.

type: "session.input_audio.muted" (default: "session.input_audio.muted")

The event type, always session.input_audio.muted.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.input_audio.unmuted

Acknowledges a session.input_audio.unmute command, removing the independent input mute. An active audio fixture still pauses inference until playback finishes. Fixture playback does not emit this event.

event_id: string

The unique ID of the Live server event.

type: "session.input_audio.unmuted" (default: "session.input_audio.unmuted")

The event type, always session.input_audio.unmuted.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.output_audio.fixture.playing

The existing playback path has accepted the validated audio fixture. This acknowledgment does not identify when the listener receives the first sample. The optional client_event_id echoes the play command.

event_id: string

The unique ID of the Live server event.

type: "session.output_audio.fixture.playing" (default: "session.output_audio.fixture.playing")
client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.output_audio.fixture.played

The complete audio fixture has drained from the server mixer and normal inference has resumed. Transport buffers may still contain audio; this event does not prove listener-side completion. The optional client_event_id echoes the play command. This event is not emitted for canceled or failed playback.

event_id: string

The unique ID of the Live server event.

type: "session.output_audio.fixture.played" (default: "session.output_audio.fixture.played")
client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.instructions.appended

Returned when a session.instructions.append command is accepted into the Live session timeline. Acknowledges the appended instructions without guaranteeing that the model has acted on them.

end_ms: integer

The end of this event on the Live session timeline, in milliseconds from the beginning of the session. For appended context, this can equal start_ms.

event_id: string

The unique ID of the Live server event.

start_ms: integer

The start of this event on the Live session timeline, in milliseconds from the beginning of the session.

type: "session.instructions.appended" (default: "session.instructions.appended")

The event type, always session.instructions.appended.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.thinking.appended

Returned when a session.thinking.append command is accepted into the Live session timeline. Acknowledges the added reasoning context without guaranteeing any spoken output.

end_ms: integer

The end of this event on the Live session timeline, in milliseconds from the beginning of the session. For appended context, this can equal start_ms.

event_id: string

The unique ID of the Live server event.

start_ms: integer

The start of this event on the Live session timeline, in milliseconds from the beginning of the session.

type: "session.thinking.appended" (default: "session.thinking.appended")

The event type, always session.thinking.appended.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.commentary.appended

Returned when a session.commentary.append command is accepted into the Live session timeline. Acknowledges the added commentary without guaranteeing exact wording or completed audio playback.

end_ms: integer

The end of this event on the Live session timeline, in milliseconds from the beginning of the session. For appended context, this can equal start_ms.

event_id: string

The unique ID of the Live server event.

start_ms: integer

The start of this event on the Live session timeline, in milliseconds from the beginning of the session.

type: "session.commentary.appended" (default: "session.commentary.appended")

The event type, always session.commentary.appended.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.output_audio.delta

An audio chunk generated by the Live model. Decode and play primary WebSocket chunks in delivery order using the configured session audio format. Sideband connections receive reflected output audio with timestamps.

delta: string

Base64-encoded raw audio. Primary WebSocket events use the session's configured format; reflected sideband events use mono PCM16LE at 24 kHz.

type: "session.output_audio.delta" (default: "session.output_audio.delta")

The event type, always session.output_audio.delta.

end_ms: optional integer

Exclusive session-relative end in milliseconds. Required on reflected sideband events; omitted on the primary WebSocket. Dropped output frames leave gaps between reflected ranges.

start_ms: optional integer

Inclusive session-relative start in milliseconds. Required on reflected sideband events; omitted on the primary WebSocket.

session.input_transcript.delta

A transcript fragment for user input audio in the Live session. Accumulate fragments in delivery order; these events do not define complete turns or include a transcript-done event.

delta: string

The transcript text fragment for the audio in this time range. Append fragments in delivery order to build the transcript.

end_ms: integer

The end of this event on the Live session timeline, in milliseconds from the beginning of the session. For appended context, this can equal start_ms.

event_id: string

The unique ID of the Live server event.

start_ms: integer

The start of this event on the Live session timeline, in milliseconds from the beginning of the session.

type: "session.input_transcript.delta" (default: "session.input_transcript.delta")

The event type, always session.input_transcript.delta.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.output_transcript.delta

A transcript fragment for assistant output audio in the Live session. Accumulate fragments in delivery order; these events do not define complete turns or include a transcript-done event.

delta: string

The transcript text fragment for the audio in this time range. Append fragments in delivery order to build the transcript.

end_ms: integer

The end of this event on the Live session timeline, in milliseconds from the beginning of the session. For appended context, this can equal start_ms.

event_id: string

The unique ID of the Live server event.

start_ms: integer

The start of this event on the Live session timeline, in milliseconds from the beginning of the session.

type: "session.output_transcript.delta" (default: "session.output_transcript.delta")

The event type, always session.output_transcript.delta.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.delegation.created

Returned when the Live model delegates work to your application, Responses, or Decisions. Contains delegation metadata and the position on the session timeline where the work was delegated.

delegation: object { id, target, type, response_id }

The delegated work identifier and destination. This object contains metadata, not the task text.

event_id: string

The unique ID of the Live server event.

offset_ms: integer

The position on the Live session timeline where the delegation was created, in milliseconds from the beginning of the session.

type: "session.delegation.created" (default: "session.delegation.created")

The event type, always session.delegation.created.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

decision.event

A Decision API event for a Live delegation or transcript trigger. For a trigger, source_event_id identifies the transcript delta that caused this evaluation.

delegation_id: string or null

The Live delegation ID, or null for a transcript trigger.

event: object { decision, type }
decision: Decision { answers, model, usage }

The native Decision API response, including its model, ordered answers, and token usage.

type: "decision.completed" (default: "decision.completed")
event_id: string

The unique ID of this Live server event.

source_event_id: string or null

The event_id of the transcript delta that fired this trigger, or null for a delegation.

source_event_type: "session.input_transcript.delta" or "session.output_transcript.delta" or null
trigger_id: string or null

The Live-assigned ID of this trigger firing, or null for a delegation.

type: "decision.event" (default: "decision.event")

decision.item.created

An input item was appended for future decisions.

event_id: string

The unique ID of the Live server event.

item: Message { id, content, role, type } or Message { id, content, role, type } or Message { id, content, role, type } or 5 more
type: "decision.item.created" (default: "decision.item.created")
client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

decision.item.deleted

An input item was removed from future decisions.

event_id: string

The unique ID of the Live server event.

item_id: string
type: "decision.item.deleted" (default: "decision.item.deleted")
client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

response.event

A streaming Responses API event from a backend delegated to by the Live session. Use the outer delegation_id to associate the nested stream with its Live delegation.

event: map[unknown]

The nested Responses streaming event. Dispatch on its type field. Response lifecycle snapshots omit input and clear instructions, tools, and output to keep messages small; consume granular output events for the generated content.

event_id: string

The unique ID of the Live server event.

type: "response.event" (default: "response.event")

The event type, always response.event.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

delegation_id: optional string or null

The Live delegation associated with the nested Responses event. May be null or omitted when the event cannot be correlated with a delegation.

session.usage.updated

Reports cumulative Live audio usage and, when available, the most recent context-window usage. Delegated Responses token usage is reported separately in response.event events.

event_id: string

The unique ID of the Live server event.

type: "session.usage.updated" (default: "session.usage.updated")

The event type, always session.usage.updated.

usage: SessionUsage { seconds }

The cumulative Live audio usage so far.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

context_window: optional object { usage_ratio }

The latest measured Live context-window usage. Omitted when the context limit is unknown.

usage_ratio: number

The latest active context token count divided by the Live model context limit. Can decrease after compaction and may lag between measured audio frames.

session.closed

Returned after the Live session finishes finalizing, with the close reason, final session snapshot, and cumulative audio usage. A connection closing without this event does not confirm successful finalization.

event_id: string

The unique ID of the Live server event.

reason: "close_requested" or "expired" or "content" or 2 more

Why the Live session ended: close_requested for an application close or hangup request, expired for the session duration limit, content for a safety filter, remote_hangup for a graceful remote disconnect, or connection_lost for an unexpected primary or upstream disconnection.

session: SessionResource { id, expires_at, model, 9 more }

The resolved Live session configuration and server-assigned session metadata.

type: "session.closed" (default: "session.closed")

The event type, always session.closed.

usage: SessionUsage { seconds }

The final cumulative Live audio usage after session finalization.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

error

Reports an error in the Live session, such as an invalid client command. Use error.client_event_id, when present, to identify the command that caused the error.

error: Error { code, message, type, 2 more }

Details of the Live error and the client command that caused it, when known.

event_id: string

The unique ID of the Live server event.

type: "error" (default: "error")

The event type, always error.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

info

An informational notice about the Live session, such as the event permissions applied to a frontend data channel.

code: string

A machine-readable code for the notice, such as data_channel_permissions.

event_id: string

The unique ID of the Live server event.

message: string

A human-readable explanation of the Live session notice.

type: "info" (default: "info")

The event type, always info.

client_event_id: optional string

The event_id of the client command associated with this server event, when supplied.

session.input_audio.append

Input audio received from the primary transport and reflected to a Live sideband connection before model-input muting.

audio: string

Base64-encoded raw mono PCM16LE at 24 kHz received from the primary transport, reflected to the sideband before model-input muting. This server event uses the same audio key as the client command, but is not an acknowledgment of it.

type: "session.input_audio.append" (default: "session.input_audio.append")

The event type, always session.input_audio.append.

transport.dtmf.received

A SIP DTMF keypress received from the caller. Delivered only to sideband observers.

event: string
pattern^[0-9A-D*#]$
minLength1
maxLength1
event_id: string
type: "transport.dtmf.received" (default: "transport.dtmf.received")

transport.dtmf.sent

A SIP DTMF keypress successfully sent to the SIP trunk. Delivered only to sideband observers; this is not a client command.

event: string
pattern^[0-9A-D*#]$
minLength1
maxLength1
event_id: string
type: "transport.dtmf.sent" (default: "transport.dtmf.sent")
client_event_id: optional string

The event_id of the client command, when supplied.