
Scope: inbound calls only. A caller dials a Vobiz number and is answered by the AI agent.
app.py, requirements.txt, .env.example).
How it works
Vobiz does not proxy the audio. The SIP INVITE is handed to OpenAI, which terminates the media directly with the caller. Your application server only performs control-plane work over HTTPS and a WebSocket - it never handles RTP.<Stream> are not used in this integration, and audio resampling is not required.
Requirements
Network requirements
OpenAI publishes the following media CIDR blocks. Any firewall between Vobiz and OpenAI must permit bidirectional UDP with them:
Regional endpoints
Step 1: Create the origination URI
Console: SIP → Inbound → Origination URIs (console.vobiz.ai/app/sip/in/uri)
Substitute your own Project ID, found at platform.openai.com → Settings → Project → General.
API equivalent
API equivalent
id, which you pass as primary_uri_uuid when creating the trunk. transport is not settable on Create Origination URI - select TLS in the console.Step 2: Create the inbound trunk
Console: SIP → Inbound → Trunks (console.vobiz.ai/app/sip/in/trunks)API equivalent
API equivalent
Step 3: Assign the phone number
Attach the DID that callers will dial to the trunk from Step 2.204 No Content. See Assign Number to Trunk.
Step 4: Register the OpenAI webhook
platform.openai.com → Settings → Webhooks → Create
Copy the signing secret (
whsec_…) shown once at creation. If it is lost, delete the webhook and recreate it.
Step 5: Configure the service
Environment variables
The repo ships a.env.example. Copy it with cp .env.example .env and fill in your values:
.env
- Variable names are case-sensitive and must be uppercase.
- Names must not contain spaces.
OPENAI WEBHOOK_SECRETis not a valid key and is silently ignored bypython-dotenv, which surfaces later as a signature-verification failure. OPENAI_PROJECT_IDmust be identical to the user part of the Origination URI. A mismatch routes the INVITE to a different project, and the webhook never fires.- Your Vobiz
AUTH_IDandAUTH_TOKENare only needed for the provisioning calls in Steps 1-3. The service itself talks to OpenAI, not to the Vobiz API.
Dependencies
The repo’srequirements.txt:
requirements.txt
Step 6: Handle the call
Three actions are required whenrealtime.call.incoming arrives. The excerpts below are from app.py in the sample repo.
Verify the webhook signature
400 on failure. OpenAI signs each delivery with webhook-id, webhook-timestamp and webhook-signature headers.
Accept the call
Returning200 to the webhook does not accept the call. Acceptance is a separate REST call:
Open the control WebSocket
response.create to make the agent speak first:
Enable caller transcription (optional)
Caller-side transcription is off by default. Enable it after the socket opens:conversation.item.input_audio_transcription.completed, and agent speech as response.output_audio_transcript.done. Both carry a transcript field.
Transferring to a human agent
Escalation uses SIP REFER, issued by OpenAI and routed by the Vobiz trunk.Give the agent a transfer tool
Issue the REFER when the tool fires
Listen forresponse.function_call_arguments.done, then:
- The target must be reachable and able to receive an INVITE.
- An endpoint that can place calls is not necessarily able to receive them. A registered SIP user requires an active contact binding in the registrar; without one, the INVITE cannot be delivered and the call clears instead of transferring.
tel:targets take E.164 form, for exampletel:+919888888888.
Other call controls
Running the service
Development
Production
- Terminate HTTPS with a valid certificate - OpenAI does not deliver webhooks over plain HTTP.
- Keep
SKIP_SIGNATURE_VALIDATION=false. - Gunicorn workers do not share memory. Any per-call state must live in shared storage such as Redis if it is read outside the worker that accepted the call.
Verifying the integration
Webhook delivery
platform.openai.com → Settings → Webhooks → Send test event, selectingrealtime.call.incoming. A correctly configured service returns 200.
Test events carry an empty data object and no live SIP session, so an accept attempt returns 404 call_id_not_found. The service should acknowledge this with 200 rather than an error - repeated 5xx responses count against the endpoint’s delivery health.
Live call
Dial the assigned DID. The agent answers within a few seconds and speaks the configured greeting.Behaviour reference
Useful CDR fields
Next steps
- Clone the sample service: vobiz-ai/Vobiz-Openai-Realtime.
- Explore the OpenAI Realtime API documentation.
- Review SIP trunk configuration and origination URIs.
- Inspect call quality and routing in the CDR reference.