Skip to main content
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       └───────────────┘                  └──────────────┘
  1. You create an inbound SIP trunk — OpenCX gives you a SIP endpoint + credentials.
  2. You point your PBX at that endpoint.
  3. When a call comes in, OpenCX routes it to the right AI agent based on the dialed number or a SIP header.
  4. 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"
}

Configure your PBX

In your PBX or SIP provider, create a trunk pointing to the OpenCX SIP endpoint:
SettingValue
SIP Server / Registrarsip_endpoint from the response
Usernameauth_username from the response
Passwordauth_password from the response
TransportUDP (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:
  1. SIP header — If X-OPENCX-AGENT-ID is set, that agent is used directly.
  2. Phone number assignment — The dialed number is matched against agent inbound number assignments.
  3. Trunk phone number — Matched against the trunk’s phone number list.
  4. 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.

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.

Agent SIP Configuration

Wire everything together — assign which phone numbers route to which agent, and which outbound trunk each agent uses to dial out.

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.