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

Telephony and SIP

Choose a SIP connection or an application audio bridge for phone calls.

Choose your API to see its connection steps and session events.

Choose a telephony connection

A phone call can reach GPT-Live through a SIP trunk or through an application that relays audio. Choose the path that fits your existing phone system and where your application needs to process audio.

Connection Audio and application responsibilities
Direct SIP The provider exchanges call audio with OpenAI. Your application handles webhooks, session configuration, call decisions, and business logic.
Server audio bridge Your application relays provider or room audio to GPT-Live over WebSocket. It manages both connections, event translation, playback, and call lifecycle.

A provider’s connection to your application and your application’s connection to OpenAI are separate. For example, a caller can join a room through SIP while an agent in that room connects to GPT-Live over WebSocket.

Using Twilio, Telnyx, LiveKit, or Daily/Pipecat? See GPT-Live partner integrations for provider-specific guides.

Direct SIP

Direct SIP keeps call audio on the provider-to-OpenAI media path. SIP signaling uses TLS, and GPT-Live requires SRTP for call audio. Your backend still owns the incoming-call decision, session configuration, authorization, and business logic.

Use a sideband connection when your backend needs to receive session events or send commands. It attaches to the existing conversation while SIP carries the audio. Assign one handler to each action so that duplicate webhook deliveries or events observed on multiple connections don’t execute tools twice.

Handle an inbound call

Confirm that GPT-Live SIP support is enabled for your project and that your provider’s SIP trunk is routed to that project before using this flow.

Receive the incoming call

Configure your project’s webhook endpoint for live.transport.incoming. Verify the webhook signature and deduplicate deliveries, then accept or reject the call.

The webhook identifies a SIP call with data.type: "sip" and provides data.session_id. Use that session ID unchanged for every Live call action. Treat data.sip_headers as untrusted caller metadata, not authorization.

Existing integrations may still receive the deprecated live.call.incoming event, which has no data.type. During migration, handle both names and retain the old subscription until legacy deliveries and retries have drained. The same pending call can also emit a Realtime webhook; assign one handler to the accept/reject decision rather than accepting through both APIs.

Accept or reject the call

Apply your application’s authorization and routing rules. To accept the call, send an authenticated POST /v1/live/sessions/{session_id}/accept request with a top-level session object:

{
  "session": {
    "type": "live",
    "model": "gpt-live-1",
    "instructions": "You are answering an inbound support call.",
    "audio": { "output": { "voice": "marin" } },
    "delegation": { "type": "client" }
  }
}

Use Authorization: Bearer $OPENAI_API_KEY from your trusted backend for call-control requests. Choose the voice and delegation mode at acceptance. SIP negotiates the audio format, so omit audio.format. The example selects client delegation; your backend must handle delegated work. See Delegation and tools for client and Responses configurations.

A successful acceptance returns 200 OK with an empty body after session initialization. Handle HTTP errors before treating the call as accepted.

To reject the call, send POST /v1/live/sessions/{session_id}/reject with a SIP status, such as { "status_code": 486 } for busy. The status must be an integer from 300 through 699. The first accept or reject decision wins; a later competing decision returns decision_already_made.

Attach your backend

After acceptance, connect a sideband WebSocket at wss://api.openai.com/v1/live/sessions/{session_id}/attach. Use the accepted session ID and the same project authentication and connection headers. Do not send session.start again.

SIP carries the call audio. Use the sideband for transcripts, delegation, tools, commands, and reflected audio. Choose one owner for each side effect, even if multiple connections observe an event.

Observe keypad events

The sideband receives transport.dtmf.received when the caller presses a key and transport.dtmf.send after a hosted tool successfully sends a tone. Both are notifications only. The event field contains one of 0–9, *, #, or A–D.

Transfer or end the call

To transfer the call, send POST /v1/live/sessions/{session_id}/refer with { "target_uri": "sip:agent@example.com" } for your destination. To hang up, send POST /v1/live/sessions/{session_id}/hangup with no request body. Both return 200 OK with an empty body on success.

Keep the sideband open until session.closed supplies final usage, then release application resources. If the connection drops first, record finalization as incomplete. See Usage and graceful close for finalization and close reasons.

Place an outbound call

Call a phone number through your SIP provider with Create session. Your provider handles the phone network connection while GPT-Live carries the conversation.

Outbound SIP calling must be enabled for your organization. It is available through the Live API, not the Realtime API call-creation endpoint.

Configure your trunk

Use a trunk that supports TLS signaling, Opus audio, and SDES-SRTP media. Enable Opus and SRTP in your provider’s settings before placing a call.

Supply the trunk configuration with each request:

Field Value
transport.destination The phone number to call, in E.164 format, such as +14155550123. SIP URI destinations aren’t supported.
transport.trunk.provider_url A provider endpoint such as sips:sip.example.com:5061. The default port is 5061; ;transport=tcp is optional.
transport.trunk.auth.type digest for SIP Digest authentication.
transport.trunk.auth.username Your provider’s SIP username.
transport.trunk.auth.password Your provider’s SIP password.
transport.trunk.caller_number The caller phone number to send to your provider, in E.164 format.

The provider endpoint must use sips: for TLS signaling. Don’t include credentials, paths, URI headers, or other URI parameters in the URL. Local hostnames and literal private or local IP addresses are rejected. Keep your OpenAI API key and SIP credentials on your server.

Create the session

Send POST /v1/live/sessions with your session configuration and transport.type: "sip". Choose the voice and delegation mode when creating the session. Omit audio.format because SIP negotiates the audio format.

This example uses curl and jq. Set OPENAI_API_KEY, SIP_USERNAME, and SIP_PASSWORD in your server environment, and replace the example provider endpoint and phone numbers with your own values. The example selects client delegation; your backend must handle delegated work.

jq -n \
  --arg username "$SIP_USERNAME" \
  --arg password "$SIP_PASSWORD" \
  '{
    "session": {
      "model": "gpt-live-1",
      "instructions": "Help the user schedule an appointment.",
      "audio": { "output": { "voice": "marin" } },
      "delegation": { "type": "client" }
    },
    "transport": {
      "type": "sip",
      "destination": "+14155550123",
      "trunk": {
        "provider_url": "sips:sip.example.com:5061",
        "auth": {
          "type": "digest",
          "username": $username,
          "password": $password
        },
        "caller_number": "+14155550100"
      }
    }
  }' | curl https://api.openai.com/v1/live/sessions \
    -H "Authorization: Bearer $OPENAI_API_KEY" \
    -H "Content-Type: application/json" \
    --data-binary @-

The request returns 200 OK after the session initializes:

{
  "session": { "id": "live_123" },
  "transport": { "type": "sip" }
}

This response doesn’t mean the call has been answered. It contains no SDP or trunk credentials. Preserve session.id unchanged for the sideband connection and call controls. You don’t need an incoming-call webhook or an accept request for an outbound call.

Monitor and end the call

Attach your backend to wss://api.openai.com/v1/live/sessions/{session_id}/attach using your OpenAI API key. Don’t send session.start again. The sideband connection carries conversation events, delegated work, and call progress while SIP carries the audio.

Event Meaning
transport.ringing The provider reports ringing or early media.
transport.answered The call has been answered and media is established.
transport.failed Call setup failed after session initialization. Inspect error.code and error.message.

Each call-progress event includes event_id and session_id. Attach immediately after creation: the sideband only replays events from the preceding 3 seconds, so a later attachment can miss earlier call progress. Replayed events retain their original event IDs. Deduplicate events by event_id.

Use the same transfer and hangup actions as for inbound calls. Keep the sideband open for session.closed and final usage as described in Usage and graceful close.

Handle limits and errors

Outbound SIP requests have a 1 MiB body limit. Ringing is limited to 3 minutes, and a connected call is limited to 2 hours. These limits aren’t configurable in the creation request.

A 403 response with outbound_sip_not_enabled means outbound calling isn’t enabled for your organization. Invalid session configuration is returned on the creation request. Transport setup failures can return 502, and initialization timeouts return 504. After creation succeeds, monitor transport.failed for asynchronous setup failures.

Each creation request places a new call. X-Client-Request-Id doesn’t deduplicate requests. Don’t automatically retry after an ambiguous timeout or connection failure: a retry can place another call.

Server audio bridges

Use the GPT-Live WebSocket connection when your application receives an audio stream from a phone provider or an agent framework. The application authenticates both connections, translates their event envelopes, and relays audio in both directions.

GPT-Live supports raw G.711 ÎĽ-law and A-law audio at 8 kHz over WebSocket. When the provider stream uses the same codec, sample rate, and channel count, your application can forward the raw audio bytes without converting them to PCM. Preserve audio order and wrap the audio bytes in the message format required by each connection.

Have your bridge manage queued audio, interruptions, and call termination. Account for audio buffered by the provider when handling playback. See Managing sessions for the Live session lifecycle and Migrate to GPT-Live for changes to turn-taking and playback control.

Keep the provider’s call or room identifier alongside the OpenAI session ID so you can trace a conversation across both systems.

Next steps with GPT-Live