SIP Trunking
Preview
SIP

Getting Started

Provision a trunk, secure it with credentials and IP ACLs, point your PBX or SBC at sip.sendexa.co, and complete your first inbound and outbound test calls.

Time to first call

~15m

With an existing PBX

SIP host

sip…

sip.sendexa.co

Ports

5060/61

UDP · TCP · TLS

Auth

Digest

+ optional IP ACL

Prerequisites

Sendexa account
  • Active business account with SIP Trunking enabled (Preview)
  • Dashboard API token for REST (Authentication)
  • Sufficient balance for outbound termination tests
Your infrastructure
  • PBX, SBC, or softswitch (Asterisk, FreeSWITCH, 3CX, etc.)
  • Public IP or NAT with correct SIP ALG / port mapping
  • Outbound firewall open to sip.sendexa.co:5060 and 5061
  • Optional: public SIP URI reachable for inbound DIDs

Setup workflow

1

Create a SIP trunk

POST /v1/sip/trunks with credentials, codecs, transport preference, and optional IP allowlist.

2

Configure your PBX / SBC

Point a SIP trunk or peer at sip.sendexa.co using the issued username and password. Prefer TLS 5061.

3

Place an outbound test call

Dial an E.164 destination through the trunk. Confirm ring, answer, two-way audio, and hangup.

4

Assign a DID for inbound

POST /v1/sip/numbers to attach a number and set primary/failover SIP URIs for origination.

5

Verify CDR

GET /v1/sip/cdr and confirm duration, direction, hangup cause, and billed minutes.

Step 1 — Create a trunk

POST
/v1/sip/trunks

A trunk is the logical SIP account that authenticates your PBX, holds capacity limits, and owns origination destinations for attached numbers.

FieldTypeRequiredDescription
namestring
required
Human-readable label shown in the dashboard and CDR filters.
auth.usernamestring
required
SIP digest username (3–64 chars, alphanumeric and _-). Must be unique per account.
auth.passwordstring
required
SIP digest password (min 12 characters). Returned only at creation — store immediately.
ipAllowliststring[]optionalCIDR list of source IPs allowed to signal. Strongly recommended for production.
codecsstring[]optionalAllowed codecs. Default: ["PCMU","PCMA","G729","opus"]. Order is preference.
transportstringoptionalPreferred transport: "udp" | "tcp" | "tls". Default "tls". Your PBX may still use others if allowed.
maxConcurrentCallsintegeroptionalSimultaneous call cap for this trunk. Default depends on account plan (often 10–100).
origination.primaryUristringoptionalDefault SIP URI for inbound DIDs that do not override destination.
origination.failoverUristringoptionalTried if the primary URI fails (timeout, 5xx, or connection refused).
Bash
curl -X POST 'https://api.sendexa.co/v1/sip/trunks' \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN' \
-d '{
"name": "Contact Centre Trunk",
"auth": {
"username": "cc_trunk_prod",
"password": "S3cure-Long-Secret!"
},
"ipAllowlist": ["203.0.113.10/32"],
"codecs": ["PCMU", "PCMA", "opus"],
"transport": "tls",
"maxConcurrentCalls": 30,
"origination": {
"primaryUri": "sip:inbound@pbx.example.com:5061;transport=tls",
"failoverUri": "sip:inbound@backup.example.com:5061;transport=tls"
}
}'

Step 2 — Confirm the trunk

GET
/v1/sip/trunks
Bash
curl -X GET 'https://api.sendexa.co/v1/sip/trunks' \
-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN'
response.json
{
"success": true,
"code": "OK",
"data": {
"trunks": [
{
"trunkId": "TRK-8c1e2b9a-4d3f-41a0-9e7c-12ab34cd56ef",
"name": "Contact Centre Trunk",
"status": "active",
"sipHost": "sip.sendexa.co",
"ports": { "udp": 5060, "tcp": 5060, "tls": 5061 },
"auth": { "username": "cc_trunk_prod", "realm": "sendexa.co" },
"ipAllowlist": ["203.0.113.10/32"],
"codecs": ["PCMU", "PCMA", "opus"],
"transport": "tls",
"maxConcurrentCalls": 30,
"activeCalls": 0,
"createdAt": "2026-07-12T10:15:22.441Z"
}
],
"total": 1
}
}

Step 3 — Point your PBX at Sendexa

Connection parameters
SettingValue
Registrar / Proxy / Hostsip.sendexa.co
Port (UDP/TCP)5060
Port (TLS)5061
Outbound proxysip.sendexa.co (same host)
Username / Auth IDYour trunk auth.username
PasswordYour trunk auth.password
Realm / Domainsendexa.co
From domainsendexa.co (or your verified domain)
RegisterOptional — static IP ACL trunks often skip REGISTER
DTMFRFC 2833 / telephone-event (preferred)

Sample PBX snippets

Minimal examples to reach the edge. Full production configs (NAT, SRTP, codecs) are covered in Trunk Configuration.

pjsip_sendexa.conf
; Sendexa SIP trunk — Asterisk PJSIP
[sendexa-auth]
type=auth
auth_type=userpass
username=cc_trunk_prod
password=S3cure-Long-Secret!
realm=sendexa.co
[sendexa-aor]
type=aor
contact=sip:sip.sendexa.co:5061;transport=tls
qualify_frequency=60
[sendexa-endpoint]
type=endpoint
context=from-sendexa
disallow=all
allow=ulaw,alaw,g729,opus
outbound_auth=sendexa-auth
aors=sendexa-aor
from_domain=sendexa.co
direct_media=no
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
media_encryption=sdes
transport=transport-tls
[sendexa-identify]
type=identify
endpoint=sendexa-endpoint
match=sip.sendexa.co
[sendexa-registration]
type=registration
outbound_auth=sendexa-auth
server_uri=sip:sip.sendexa.co:5061;transport=tls
client_uri=sip:cc_trunk_prod@sip.sendexa.co
retry_interval=60
; Omit registration if using static IP ACL only

Step 4 — Outbound test call (termination)

  1. From an extension on your PBX, dial a known good mobile in E.164 (include country code, e.g. +233…).
  2. Confirm your dialplan routes that call via the Sendexa trunk / gateway, not another provider.
  3. Expect normal ringback. On answer you should have two-way audio.
  4. Hang up cleanly and note the approximate duration for CDR checks.

SIP signaling path: your PBX INVITE sip.sendexa.co → carrier → handset.

Step 5 — Assign a DID (origination)

POST
/v1/sip/numbers

Attach a purchased or inventory number to your trunk and define where inbound INVITEs should be sent. Numbers must already be available on your Sendexa account (order via dashboard or sales).

FieldTypeRequiredDescription
numberstring
required
E.164 DID you own on Sendexa, e.g. +233302123456.
trunkIdstring
required
Target trunk ID returned from POST /v1/sip/trunks.
destination.primaryUristring
required
SIP URI that receives inbound calls for this DID. Overrides trunk default if set.
destination.failoverUristringoptionalSecondary URI if primary is unreachable.
destination.timeoutSecondsintegeroptionalSeconds to wait for 18x/200 from primary before failover (default 20).
Bash
curl -X POST 'https://api.sendexa.co/v1/sip/numbers' \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN' \
-d '{
"number": "+233302123456",
"trunkId": "TRK-8c1e2b9a-4d3f-41a0-9e7c-12ab34cd56ef",
"destination": {
"primaryUri": "sip:inbound@pbx.example.com:5061;transport=tls",
"failoverUri": "sip:inbound@backup.example.com:5061;transport=tls",
"timeoutSeconds": 20
}
}'
response.json
{
"success": true,
"code": "NUMBER_ASSIGNED",
"message": "DID assigned to trunk for origination.",
"data": {
"numberId": "DID-4f91aa20-22c1-4e0b-9c3a-77b1e0d9a001",
"number": "+233302123456",
"trunkId": "TRK-8c1e2b9a-4d3f-41a0-9e7c-12ab34cd56ef",
"destination": {
"primaryUri": "sip:inbound@pbx.example.com:5061;transport=tls",
"failoverUri": "sip:inbound@backup.example.com:5061;transport=tls",
"timeoutSeconds": 20
},
"status": "active",
"assignedAt": "2026-07-12T10:40:11.102Z"
}
}

Step 6 — Verify CDR

GET
/v1/sip/cdr
Bash
curl -G 'https://api.sendexa.co/v1/sip/cdr' \
-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN' \
--data-urlencode 'trunkId=TRK-8c1e2b9a-4d3f-41a0-9e7c-12ab34cd56ef' \
--data-urlencode 'from=2026-07-12T00:00:00Z' \
--data-urlencode 'to=2026-07-13T00:00:00Z' \
--data-urlencode 'limit=20'

Full field reference is in CDR & Reporting.

Firewall & network

DirectionPort / ProtocolPurpose
Outbound + Inbound5060/udp, 5060/tcpSIP signaling
Outbound + Inbound5061/tcpSIP over TLS
Outbound + InboundRTP UDP (dynamic)Media (Sendexa may relay)
Outbound443/tcpREST API api.sendexa.co

Go-live checklist

Trunk created and status is active
SIP credentials stored in PBX secret store
IP allowlist matches your egress public IPs
TLS preferred; certificate validation enabled
Outbound test call: ring, answer, two-way audio
DID assigned with primary + failover SIP URIs
Inbound test from mobile to DID reaches your IVR/queue
CDR shows correct direction, duration, and hangup cause
maxConcurrentCalls sized for peak + headroom
Monitoring/alerts on trunk registration or call failures