OpenAI’s GPT-Live documentation describes two ways to connect a telephone call to a voice agent: a direct SIP connection between a telephony provider and OpenAI, or a server audio bridge that relays audio through an application. The documentation covers both inbound call handling and outbound dialing through a SIP provider, but it does not establish a consumer phone-calling feature or universal availability.

In a post on X, @imjustnewatai reported that OpenAI had added direct phone calling to the GPT-Live documentation. The linked Telephony and SIP documentation is more specific: a team must provide the telephony connection, backend logic, credentials, event handling, and—in some configurations—an audio relay.

Screenshot showing GPT-Live documentation’s direct SIP and server audio bridge choices.
Screenshot showing GPT-Live documentation’s direct SIP and server audio bridge choices.

Image credit: @imjustnewatai on X

Two ways to connect a phone call to GPT-Live

The central architecture choice is whether the telephone provider sends call audio directly to OpenAI or whether the application handles the audio stream itself.

Connection pattern

Audio path

What the application must manage

Direct SIP

The provider exchanges call audio with OpenAI. SIP signaling uses TLS and call media uses SRTP.

Webhooks, authorization, session configuration, call decisions, business logic, and optional sideband controls

Server audio bridge

The application relays provider or room audio to GPT-Live over WebSocket and sends audio back.

Authentication for both connections, event translation, audio ordering, playback, interruptions, and the call lifecycle

Direct SIP is the simpler media path when a provider can connect its trunk to OpenAI and the application mainly needs to make authorization and business decisions. The backend still matters: it decides whether an inbound call is accepted, configures the session, handles tools or delegated work, and can monitor or control the call.

A server audio bridge is more appropriate when the application already receives audio from a phone provider, room, or agent framework and needs to relay or otherwise handle that stream before or while sending it to GPT-Live. In this design, the application owns both connections and must translate the event formats on each side.

OpenAI’s documentation also lists partner paths for LiveKit, Twilio, Telnyx, and Daily/Pipecat. Those integrations have their own setup instructions, credentials, and package-version requirements. A pre-existing Realtime integration should not be assumed to work with GPT-Live automatically.

How an inbound GPT-Live call works

An inbound integration begins before the model speaks. The project must have GPT-Live SIP support enabled, and the provider’s SIP trunk must be routed to that project.

When a call arrives, the application receives a live.transport.incoming webhook. The backend should verify the webhook signature and deduplicate deliveries before making a call decision. The event identifies a SIP call with data.type: "sip" and supplies a data.session_id.

That session ID is important because the application must use it unchanged for subsequent Live actions. The documentation also warns that SIP headers are caller metadata, not authorization. A phone number or other value in those headers should not by itself grant access to an account, tool, or protected workflow.

The backend then applies its own routing and authorization rules. It can accept the call with an authenticated POST /v1/live/sessions/{session_id}/accept request or reject it with the corresponding /reject endpoint. The acceptance request supplies the Live model and startup configuration, such as instructions, voice, and delegation mode. SIP negotiates the media format, so the acceptance configuration should omit audio.format.

A successful acceptance returns an empty response after session initialization. The application should handle HTTP errors before treating the call as accepted. The first accept-or-reject decision wins; a competing later decision is rejected as decision_already_made.

After acceptance, the backend can attach a sideband WebSocket at:

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

The sideband connection does not carry the primary SIP audio path. Instead, it gives the backend access to session events, transcripts, delegated work, tools, commands, and reflected audio. The application should not send session.start again after attaching.

A production handler also needs an ownership rule for side effects. Duplicate webhook deliveries or events observed through multiple connections should not cause a tool, transfer, or other action to run twice.

A sideband can also report DTMF events, which represent keypad input. The documentation describes received tones and tones sent after a hosted tool succeeds as notifications; the event value can be a digit, *, #, or one of A through D.

The backend can transfer an active call with the POST /v1/live/sessions/{session_id}/refer action and end it with the POST /v1/live/sessions/{session_id}/hangup action. The sideband should remain open until session.closed provides final usage information. If the connection disappears first, the application should record finalization as incomplete.

How outbound calling works

For an outbound call, the application creates a Live session with transport.type: "sip" and supplies the destination and trunk configuration. The SIP provider handles the connection to the phone network while GPT-Live conducts the conversation after the call is established.

The documentation says outbound SIP calling must be enabled for the organization. It is available through the Live API, not the Realtime API call-creation endpoint. The documentation does not specify which organizations receive that enablement or whether the feature is available in every region.

The provider trunk must support:

  • TLS for SIP signaling

  • Opus audio

  • SDES-SRTP media

The request configures SIP Digest authentication with the provider’s username and password. The destination must be a phone number in E.164 format, such as +14155550123; SIP URI destinations are not supported for the outbound destination field. The trunk configuration also includes a provider endpoint using a sips: URL and the caller number to send to the provider.

Credentials should remain on the server. Apart from the documented optional ;transport=tcp parameter, the provider URL must not contain credentials, paths, URI headers, or other URI parameters. The documentation also says that local hostnames and literal private or local IP addresses are rejected.

A simplified outbound request has this shape:

{
  "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": "SIP_USERNAME",
        "password": "SIP_PASSWORD"
      },
      "caller_number": "+14155550100"
    }
  }
}

The response includes a Live session ID, but a successful session-creation response does not mean the person has answered. It also does not contain SDP or trunk credentials. The backend should preserve the returned session.id and use it for the sideband connection and later call controls.

Unlike the inbound flow, an outbound call does not require an incoming-call webhook or a separate accept request. The provider reports progress through the session events instead.

Monitoring ringing, answer, and failure events

The backend should attach the sideband WebSocket immediately after creating an outbound session. The documentation says the connection replays only the preceding three seconds of events, so a late attachment can miss earlier call-progress notifications.

The main transport events are:

  • 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. The backend should inspect the error code and message.

Each call-progress event includes an event_id and session_id. Replayed events retain their original IDs, allowing the application to deduplicate events by event_id.

The returned session ID also remains the handle for later operations. The backend can transfer an active call with the refer action and end it with hangup.

What a server audio bridge must do

A server audio bridge changes the responsibility boundary. Instead of letting the provider exchange audio directly with OpenAI, the application receives the provider or room audio, connects to GPT-Live over WebSocket, and relays audio in both directions.

GPT-Live supports raw G.711 μ-law and A-law audio at 8 kHz over WebSocket. If the provider uses the same codec, sample rate, and channel count, the bridge may forward the raw audio bytes without converting them to PCM. It still has to wrap those bytes in the message format expected by each connection.

The bridge must preserve audio order and handle more than simple forwarding. It needs logic for queued audio, interruptions, playback that has already been buffered by the provider, and call termination. It should also keep the provider’s call or room identifier alongside the OpenAI session ID so the team can trace a conversation across both systems.

This route gives a team more control over the media path, but it also creates more operational responsibility. Authentication, event translation, audio timing, interruption behavior, and cleanup all become application concerns rather than provider-to-OpenAI plumbing.

Limits and failure cases to design for

The documentation lists several constraints that affect retries and production workflows:

  • Outbound SIP requests have a 1 MiB request-body limit.

  • Ringing is limited to three minutes.

  • A connected call is limited to two hours.

  • Those time limits are not configurable in the session-creation request.

  • A 403 response with outbound_sip_not_enabled means outbound calling is not enabled for the organization.

  • Invalid session configuration is returned during creation.

  • Transport setup failures can return 502, while initialization timeouts can return 504.

  • Setup can also fail asynchronously through transport.failed after session creation has succeeded.

The retry behavior deserves particular attention. Each session-creation request places a new call, and X-Client-Request-Id does not deduplicate those requests. The documentation therefore advises against automatically retrying after an ambiguous timeout or connection failure, because a retry could place a second call.

A backend should also record enough session state to investigate incomplete calls, especially when a sideband connection ends before session.closed supplies final usage.

What the documentation establishes

The documentation describes a developer-facing way to connect GPT-Live to telephone systems through direct SIP or an application-managed audio bridge. It provides concrete API flows for inbound acceptance and rejection, outbound provider-mediated dialing, sideband monitoring, transfers, hangups, DTMF notifications, and media requirements.

It does not establish that OpenAI has launched a general consumer phone-calling feature, that every organization can place outbound calls, or that the service is available in every region. Pricing, regulatory requirements, call-quality measurements, latency results, and transcription accuracy are not specified in the supplied documentation.

For a product team evaluating the option, the practical next step is to confirm organization enablement and provider compatibility, then choose the media architecture. Direct SIP reduces application-managed audio plumbing, while a server bridge offers more control over an existing voice stack at the cost of additional event and media handling. Either way, the phone provider, GPT-Live session, and application backend remain distinct parts of the system.

Sources