Connect your existing PBX, contact center, or SIP provider to OpenCX so AI agents can answer and make calls through your phone numbers and infrastructure.
Don’t have your own SIP infrastructure? You don’t need it. OpenCX can provision phone numbers for you directly — just create a phone agent in one API call and you’re done. This guide is for teams that want to bring their own telephony.
How it works
┌─────────────┐ SIP INVITE ┌───────────────┐ routes to ┌──────────────┐
│ Your PBX / │ ─────────────────▶ │ OpenCX SIP │ ──────────────▶ │ AI Phone │
│ SIP Provider│ ◀───────────────── │ Endpoint │ ◀────────────── │ Agent │
└─────────────┘ RTP media └───────────────┘ └──────────────┘
You create an inbound SIP trunk — OpenCX gives you a SIP endpoint + credentials.
You point your PBX at that endpoint.
When a call comes in, OpenCX routes it to the right AI agent based on the dialed number or a SIP header.
For outbound calls, you create an outbound SIP trunk with your provider’s credentials and OpenCX dials out through it.
Prerequisites
Before you start, make sure you have:
An OpenCX API key (find it in Settings → API Keys )
At least one verified phone number (verify numbers in the dashboard or via API)
Your SIP provider credentials (if you want outbound calling)
All examples below use curl. Replace $API_KEY with your API key.
Step 1: Create an AI phone agent
Every call needs an agent to answer it. Create one:
curl -X POST https://api.open.cx/phone \
-H "Authorization: Bearer $API_KEY " \
-H "Content-Type: application/json" \
-d '{
"name": "Support Agent",
"type": "inbound",
"language": "en",
"first_message": "Hi, thanks for calling! How can I help you today?",
"use_org_knowledgebase": true
}'
Save the returned id — you’ll need it in the steps below. We’ll call it $AGENT_ID.
You can also set voice_id (browse options with GET /phone/voices), handoff_phone_number for human escalation, and actionIds to let the agent call your APIs during conversations.
Step 2: Set up inbound calling (receive calls)
Create the inbound trunk
curl -X POST https://api.open.cx/phone/sip/inbound-trunk \
-H "Authorization: Bearer $API_KEY " \
-H "Content-Type: application/json" \
-d '{
"phone_numbers": ["+15551234567"],
"krisp_enabled": true
}'
If you omit phone_numbers, OpenCX uses all your verified numbers automatically.
The response contains everything you need to configure your PBX:
{
"id" : "a1b2c3d4-..." ,
"sip_endpoint" : "sip.opencx.example.com" ,
"auth_username" : "org_abc123" ,
"auth_password" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ,
"phone_numbers" : [ "+15551234567" ],
"krisp_enabled" : true ,
"agent_id_header" : "X-OPENCX-AGENT-ID"
}
In your PBX or SIP provider, create a trunk pointing to the OpenCX SIP endpoint:
Setting Value SIP Server / Registrar sip_endpoint from the responseUsername auth_username from the responsePassword auth_password from the responseTransport UDP (default) or TCP
Route calls to a specific agent
By default, OpenCX routes inbound calls based on the dialed phone number. You can also target a specific agent by setting a SIP header on your PBX:
X-OPENCX-AGENT-ID: <your-agent-id>
This is useful when multiple agents share a phone number.
Assign inbound numbers to the agent
Tell OpenCX which phone numbers should route to your agent:
curl -X PUT https://api.open.cx/phone/sip/agents/ $AGENT_ID /inbound-numbers \
-H "Authorization: Bearer $API_KEY " \
-H "Content-Type: application/json" \
-d '{
"phone_number_ids": ["phone-number-verification-id"]
}'
Use GET /phone/sip/agents/$AGENT_ID/config to see the agent’s current inbound numbers and outbound trunk at any time.
Step 3: Set up outbound calling (make calls)
Create an outbound trunk
Provide your SIP provider’s credentials:
curl -X POST https://api.open.cx/phone/sip/outbound-trunks \
-H "Authorization: Bearer $API_KEY " \
-H "Content-Type: application/json" \
-d '{
"name": "Twilio Outbound",
"host": "sip.twilio.com",
"port": 5060,
"username": "your-sip-username",
"password": "your-sip-password",
"caller_number": "+15551234567",
"transport": "udp"
}'
Save the returned id — we’ll call it $TRUNK_ID.
Assign the trunk to your agent
curl -X PUT https://api.open.cx/phone/sip/agents/ $AGENT_ID /outbound-trunk \
-H "Authorization: Bearer $API_KEY " \
-H "Content-Type: application/json" \
-d '{
"trunk_id": "' $TRUNK_ID '"
}'
Make an outbound call
Now your agent can call out:
curl -X POST https://api.open.cx/phone/outbound-call \
-H "Authorization: Bearer $API_KEY " \
-H "Content-Type: application/json" \
-d '{
"phone_agent_id": "' $AGENT_ID '",
"phone_number": "+15559876543"
}'
The call goes through your SIP provider, using the caller ID you configured on the outbound trunk.
Step 4: Set up call transfers (optional)
Let your AI agent transfer live calls to human teams or other destinations.
Create a transfer destination
curl -X POST https://api.open.cx/phone/sip/transfer-destinations \
-H "Authorization: Bearer $API_KEY " \
-H "Content-Type: application/json" \
-d '{
"name": "Support Team",
"type": "phone",
"value": "+15559999999"
}'
The type can be "phone" (E.164 number) or "sip" (a SIP URI like sip:[email protected] ).
Save the returned id — we’ll call it $DEST_ID.
Assign it to your agent
curl -X POST https://api.open.cx/phone/sip/agents/ $AGENT_ID /transfer-destinations \
-H "Authorization: Bearer $API_KEY " \
-H "Content-Type: application/json" \
-d '{
"destination_id": "' $DEST_ID '"
}'
You can also create and assign in a single call:
curl -X POST https://api.open.cx/phone/sip/agents/ $AGENT_ID /transfer-destinations \
-H "Authorization: Bearer $API_KEY " \
-H "Content-Type: application/json" \
-d '{
"create": {
"name": "Sales Dept",
"type": "sip",
"value": "sip:[email protected] "
}
}'
During a call, the AI agent sees the available destinations by name and can initiate a cold transfer when appropriate. Context is preserved via SIP headers (X-OPENCX-SESSION-ID, X-OPENCX-AGENT-ID, X-OPENCX-CONTACT-ID).
Call routing priority
When a SIP call arrives, OpenCX determines which agent handles it in this order:
SIP header — If X-OPENCX-AGENT-ID is set, that agent is used directly.
Phone number assignment — The dialed number is matched against agent inbound number assignments.
Trunk phone number — Matched against the trunk’s phone number list.
Fallback — The first available agent in the organization.
Managing phone numbers on the trunk
After the initial setup, you can add or remove DIDs without recreating the trunk:
# Add a number
curl -X POST https://api.open.cx/phone/sip/inbound-trunk/phone-numbers \
-H "Authorization: Bearer $API_KEY " \
-H "Content-Type: application/json" \
-d '{ "phone_numbers": ["+15552223333"] }'
# Remove a number
curl -X DELETE https://api.open.cx/phone/sip/inbound-trunk/phone-numbers/+15552223333 \
-H "Authorization: Bearer $API_KEY "
# Sync with all verified numbers (adds new, removes unverified)
curl -X POST https://api.open.cx/phone/sip/inbound-trunk/sync \
-H "Authorization: Bearer $API_KEY "
Full example: end to end
Here’s the complete sequence to go from zero to a working SIP integration:
API = "https://api.open.cx"
AUTH = "Authorization: Bearer $API_KEY "
# 1. Create an agent
AGENT =$( curl -s -X POST $API /phone \
-H " $AUTH " -H "Content-Type: application/json" \
-d '{"name":"Support Agent","type":"inbound","language":"en","first_message":"Hello, how can I help?","use_org_knowledgebase":true}' )
AGENT_ID =$( echo $AGENT | jq -r '.id' )
# 2. Create inbound trunk (uses all verified numbers)
TRUNK =$( curl -s -X POST $API /phone/sip/inbound-trunk \
-H " $AUTH " -H "Content-Type: application/json" \
-d '{"krisp_enabled":true}' )
echo "Configure your PBX with:"
echo $TRUNK | jq '{sip_endpoint, auth_username, auth_password}'
# 3. Create outbound trunk
OUT =$( curl -s -X POST $API /phone/sip/outbound-trunks \
-H " $AUTH " -H "Content-Type: application/json" \
-d '{"name":"My SIP Provider","host":"sip.provider.com","username":"user","password":"pass","caller_number":"+15551234567"}' )
OUT_ID =$( echo $OUT | jq -r '.id' )
# 4. Assign outbound trunk to agent
curl -s -X PUT $API /phone/sip/agents/ $AGENT_ID /outbound-trunk \
-H " $AUTH " -H "Content-Type: application/json" \
-d "{ \" trunk_id \" : \" $OUT_ID \" }"
# 5. Create and assign a transfer destination
curl -s -X POST $API /phone/sip/agents/ $AGENT_ID /transfer-destinations \
-H " $AUTH " -H "Content-Type: application/json" \
-d '{"create":{"name":"Human Support","type":"phone","value":"+15559999999"}}'
# Done! Your agent can now receive, make, and transfer calls.
echo "Agent $AGENT_ID is ready."
API Reference
Inbound Trunk
Let the AI agent answer calls on your existing phone numbers. You point your PBX or SIP provider at OpenCX and incoming calls are handled automatically.
Create Inbound Trunk Provision SIP endpoint + credentials
Get Inbound Trunk Retrieve SIP credentials
Delete Inbound Trunk Remove inbound trunk
Sync Phone Numbers Sync with verified numbers
Add Phone Numbers Add DIDs to trunk
Remove Phone Number Remove a DID
Outbound Trunks
Let the AI agent make calls through your own SIP provider. Provide your provider’s credentials once, then any agent can dial out with your caller ID.
List Outbound Trunks List all outbound trunks
Create Outbound Trunk Create with SIP provider credentials
Update Outbound Trunk Update trunk name
Delete Outbound Trunk Delete outbound trunk
Agent SIP Configuration
Wire everything together — assign which phone numbers route to which agent, and which outbound trunk each agent uses to dial out.
Get Agent Config View inbound numbers + outbound trunk
Set Inbound Numbers Assign inbound numbers
Set Outbound Trunk Assign outbound trunk
Phone Transfer Destinations
Define where the AI agent can transfer live calls — a support team’s phone number, a sales department’s SIP URI, etc. Assign them per-agent to control who can transfer where.
List Destinations List org destinations
Create Destination Create phone or SIP destination
Update Destination Update a destination
Delete Destination Delete a destination
List Agent Destinations See agent’s assigned destinations
Assign to Agent Assign destination to agent
Remove from Agent Unassign from agent