FeaturesTemplatesShowcaseTownie
AI
BlogDocsPricing
Log inSign up
emcho
emchohello-transcription
Remix of emcho/hello-mcp
Public
Like
hello-transcription
Home
Code
10
.claude
1
docs
1
frontend
1
routes
2
.gitattributes
.vtignore
CLAUDE.md
README.md
deno.json
H
main.tsx
Branches
1
Pull requests
Remixes
1
History
Environment variables
1
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data โ€“ all from the browser, and deployed in milliseconds.
Sign up now
Code
/
docs
/
guides
/
realtime-sip.md
Code
/
docs
/
guides
/
realtime-sip.md
Search
9/4/2025
Viewing readonly version of main branch: v42
View latest version
realtime-sip.md

Realtime API with SIP

Connect to the Realtime API using SIP.

SIP is a protocol used to make phone calls over the internet. With SIP and the Realtime API you can direct incoming phone calls to the API.

Overview

If you want to connect a phone number to the Realtime API, use a SIP trunking provider (e.g., Twilio). This is a service that converts your phone call to IP traffic. After you purchase a phone number from your SIP trunking provider, follow the instructions below.

Start by creating a webhook for incoming calls, at platform.openai.com. Then, point your SIP trunk at the OpenAI SIP endpoint, using the project ID for which you configured the webhook, e.g., sip:$PROJECT_ID@sip.api.openai.com;transport=tls. To find your $PROJECT_ID, go to your [settings] > General. The page displays the project ID. It should have a proj_ prefix.

When OpenAI receives SIP traffic associated with your project, the webhook that you configured will be fired. The event fired will be a realtime.call.incoming event.

This webhook lets you accept or reject the call. When accepting the call, you'll provide the configuration (instructions, voice, etc) for the Realtime API session. Once established, you can set up a web socket and monitor the session as usual. The APIs to accept, reject, and monitor the call are documented below.

Connection details

URIs used for interacting with Realtime API and SIP:

|SIP URI|sip:$PROJECT_ID@sip.api.openai.com;transport=tls| |Accept URI|https://api.openai.com/v1/realtime/calls/$CALL_ID/accept| |Reject URI|https://api.openai.com/v1/realtime/calls/$CALL_ID/reject| |Refer URI|https://api.openai.com/v1/realtime/calls/$CALL_ID/refer| |Events URI|wss://api.openai.com/v1/realtime?call_id=$CALL_ID|

Find your $CALL_ID in the call_id field in data object present in the webhook. See an example in the next section.

Handle the webhook

The following is an example of a realtime.call.incoming handler. It accepts the call and then logs all the events from the Realtime API.

Python

Python

from flask import Flask, request, Response, jsonify, make_response from openai import OpenAI, InvalidWebhookSignatureError import asyncio import json import os import requests import time import threading import websockets app = Flask(__name__) client = OpenAI( webhook_secret=os.environ["OPENAI_WEBHOOK_SECRET"] ) AUTH_HEADER = { "Authorization": "Bearer " + os.getenv("OPENAI_API_KEY") } call_accept = { "type": "realtime", "instructions": "You are a support agent.", "model": "gpt-4o-realtime-preview-2024-12-17", } response_create = { "type": "response.create", "response": { "instructions": ( "Say to the user 'Thank you for calling, how can I help you'" ) }, } async def websocket_task(call_id): try: async with websockets.connect( "wss://api.openai.com/v1/realtime?call_id=" + call_id, additional_headers=AUTH_HEADER, ) as websocket: await websocket.send(json.dumps(response_create)) while True: response = await websocket.recv() print(f"Received from WebSocket: {response}") except Exception as e: print(f"WebSocket error: {e}") @app.route("/", methods=["POST"]) def webhook(): try: event = client.webhooks.unwrap(request.data, request.headers) if event.type == "realtime.call.incoming": requests.post( "https://api.openai.com/v1/realtime/calls/" + event.data.call_id + "/accept", headers={**AUTH_HEADER, "Content-Type": "application/json"}, json=call_accept, ) threading.Thread( target=lambda: asyncio.run( websocket_task(event.data.call_id) ), daemon=True, ).start() return Response(status=200) except InvalidWebhookSignatureError as e: print("Invalid signature", e) return Response("Invalid signature", status=400) if __name__ == "__main__": app.run(port=8000)

Redirect the call

It's also possible to redirect the call to another number. During the call, make a POST to the refer endpoint:

|URL|https://api.openai.com/v1/realtime/calls/$CALL_ID/refer| |Payload|JSON with one key target_uriThis is the value used in the Refer-To. You can use Tel-URI for example tel:+14152909007| |Headers|Authorization: Bearer YOUR_API_KEYSubstitute YOUR_API_KEY with a standard API key|

Next steps

Now that you've connected over SIP, use the left navigation or click into these pages to start building your realtime application.

  • Using realtime models
  • Managing conversations
  • Webhooks and server-side controls
  • Realtime transcription

Was this page useful?

Go to top
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Product
FeaturesPricing
Developers
DocsStatusAPI ExamplesNPM Package Examples
Explore
ShowcaseTemplatesNewest ValsTrending ValsNewsletter
Company
AboutBlogCareersBrandhi@val.town
Terms of usePrivacy policyAbuse contact
ยฉ 2025 Val Town, Inc.