Use the GPT Realtime API via SIP
This document refers to the Microsoft Foundry (classic) portal.🔍 View the Microsoft Foundry (new) documentation to learn about the new portal.
Supported models
The GPT real-time models are available for global deployments in East US 2 and Sweden Central regions.gpt-4o-mini-realtime-preview(2024-12-17)gpt-4o-realtime-preview(2024-12-17and2025-06-03)gpt-realtime(2025-08-28)gpt-realtime-mini(2025-10-06)gpt-realtime-mini-2025-12-15(2025-12-15)
Prerequisites
Before you can use GPT real-time audio, you need:- An Azure subscription - Create one for free.
- A Microsoft Foundry resource - Create a Microsoft Foundry resource in one of the supported regions.
- A deployment of the
gpt-4o-realtime-preview,gpt-4o-mini-realtime-preview,gpt-realtime,gpt-realtime-mini, orgpt-realtime-mini-2025-12-15model in a supported region as described in the supported models section in this article.- In the Microsoft Foundry portal, load your project. Select Build in the upper right menu, then select the Models tab on the left pane, and Deploy a base model. Search for the model you want, and select Deploy on the model page.
- Azure role assignment: Cognitive Services User or Cognitive Services Contributor on your resource.
- Python 3.8 or later.
- The following Python packages installed:
openai>=1.0.0(includes webhook support)flask>=2.0.0websockets>=10.0requests
- An account with a SIP trunking provider (for example, Twilio, Vonage, or Bandwidth).
- A phone number purchased from your SIP provider.
Connect to SIP
To connect a phone number to the Realtime API, use a SIP trunking provider (for example, Twilio). A trunking provider is a service that converts your phone call to IP traffic.- Purchase a phone number from your SIP trunking provider.
- Create a webhook for incoming calls using the Azure OpenAI Webhook Service REST API.
- Get the internal ID of your Azure OpenAI resource:
- In the Azure portal, navigate to your resource.
- Select JSON View to find the internal ID.
- Construct your project ID using the format
proj_<internalId>(for example,proj_88c4a88817034471a0ba0fcae24ceb1b). - Configure your SIP trunk to route calls to:
sip:proj_<internalId>@<region>.sip.ai.azure.com;transport=tls
The currently supported regions for SIP are
swedencentral and eastus2.Handling incoming calls
When Azure OpenAI receives SIP traffic associated with your project, your webhook endpoint receives an incoming event message. The event fired for SIP calls is type =realtime.call.incoming like the example shown here.
Accept the call and configure the session
Use the Accept call endpoint to approve the inbound call and configure the real-time session that answers it. Send the same parameters you would send in to a create client secret. You can include any values you would use in asession.update message, but type, model, and instructions are required.
For authorization, you can either use the
api-key header or the Bearer token as shown here. Remember the model name is actually the name of your deployment.- The
call_idfrom therealtime.call.incomingwebhook event Authorization(orapi-key) header
200 OK once the SIP leg is ringing and the real-time session is being established.
Reject unwanted calls
Use the Reject call endpoint to decline an invite when you don’t want to handle the incoming call (for example, from an unsupported country/region code). To control the response sent back to the carrier, supply an optional SIP status code along with the requiredcall_id path parameter. The following example shows a request sending 486, which indicates the system is too busy to take the call.
603 (Decline) to the carrier. A successful request responds with 200 OK after the SIP response is delivered.
Transfer (refer) the call to another endpoint
Transfer an active call using the Refer call endpoint. Provide thecall_id and the target_uri that should be placed in the SIP Refer-To header (for example, tel:+14155550123 or sip:agent@example.com).
200 OK once the REFER is relayed to your SIP provider. The downstream system handles the rest of the call flow for the caller.
Monitor call events and issue session commands
After you accept a call, open a WebSocket connection to the same session to stream events and issue Realtime API commands. To create a WebSocket to an existing call, you must use thecall_id parameter. The model argument isn’t used because it’s configured as part of the JSON when accepting the call. The following example shows a common scenario: issuing a response.create message to instruct the Realtime API system to answer the phone and say hello.
Here’s a sample of a WebSocket request to a specific SIP call:
| Parameter | Type | Description |
|---|---|---|
call_id | string | Identifier from the realtime.call.incoming webhook. |
Authorization: Bearer $TOKEN (or api-key: <your API key>)
The WebSocket behaves exactly like any other Realtime API connection. You can send messages like response.create or session.update to control the call, and listen for server events to track progress.
The following code snippet illustrates how a WebSocket connection is made:
End the session and disconnect
End the session with the Hang up endpoint when your application should disconnect the caller. This endpoint can be used to terminate both SIP and WebRTC real-time sessions.200 OK when it starts tearing down the call.
Sample webhook endpoint
The following code is a Python example of arealtime.call.incoming handler. It accepts the call and then logs all the events from the Realtime API.
Troubleshooting
Webhook signature verification fails
If you receiveInvalidWebhookSignatureError:
- Verify your
OPENAI_WEBHOOK_SECRETenvironment variable matches the secret from webhook creation. - Ensure you’re passing raw request body bytes to
unwrap(), not parsed JSON. - Check that no middleware is modifying the request body before verification.
SIP calls not reaching webhook
- Verify your SIP trunk is configured to route to
<region>.sip.ai.azure.com. - Confirm TLS is enabled (
transport=tlsin SIP URI). - Check that your project ID format is correct:
proj_<32-character-hex-id>.
WebSocket connection fails
- Ensure you’re using
wss://(secure WebSocket), notws://. - Verify the
call_idmatches an accepted call. - Check that your API key or token has access to the resource.
Common SIP status codes
| Code | Meaning | Resolution |
|---|---|---|
| 486 | Busy Here | System overloaded; implement retry logic |
| 603 | Decline | Call explicitly rejected; check your accept/reject logic |
| 408 | Request Timeout | Network issue; verify connectivity to Azure |
Related content
- Use the Realtime API via WebRTC for browser-based applications
- Use the Realtime API via WebSocket for server-to-server scenarios
- Azure OpenAI webhooks for webhook configuration details
- Realtime API reference for complete API documentation