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.
~15m
With an existing PBX
sip…
sip.sendexa.co
5060/61
UDP · TCP · TLS
Digest
+ optional IP ACL
Authentication
Authorization: Basic <token>. Auth guide →Prerequisites
- Active business account with SIP Trunking enabled (Preview)
- Dashboard API token for REST (Authentication)
- Sufficient balance for outbound termination tests
- 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
Create a SIP trunk
POST /v1/sip/trunks with credentials, codecs, transport preference, and optional IP allowlist.
Configure your PBX / SBC
Point a SIP trunk or peer at sip.sendexa.co using the issued username and password. Prefer TLS 5061.
Place an outbound test call
Dial an E.164 destination through the trunk. Confirm ring, answer, two-way audio, and hangup.
Assign a DID for inbound
POST /v1/sip/numbers to attach a number and set primary/failover SIP URIs for origination.
Verify CDR
GET /v1/sip/cdr and confirm duration, direction, hangup cause, and billed minutes.
Step 1 — Create a trunk
A trunk is the logical SIP account that authenticates your PBX, holds capacity limits, and owns origination destinations for attached numbers.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | required | Human-readable label shown in the dashboard and CDR filters. |
| auth.username | string | required | SIP digest username (3–64 chars, alphanumeric and _-). Must be unique per account. |
| auth.password | string | required | SIP digest password (min 12 characters). Returned only at creation — store immediately. |
| ipAllowlist | string[] | optional | CIDR list of source IPs allowed to signal. Strongly recommended for production. |
| codecs | string[] | optional | Allowed codecs. Default: ["PCMU","PCMA","G729","opus"]. Order is preference. |
| transport | string | optional | Preferred transport: "udp" | "tcp" | "tls". Default "tls". Your PBX may still use others if allowed. |
| maxConcurrentCalls | integer | optional | Simultaneous call cap for this trunk. Default depends on account plan (often 10–100). |
| origination.primaryUri | string | optional | Default SIP URI for inbound DIDs that do not override destination. |
| origination.failoverUri | string | optional | Tried if the primary URI fails (timeout, 5xx, or connection refused). |
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
curl -X GET 'https://api.sendexa.co/v1/sip/trunks' \-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN'
{"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
| Setting | Value |
|---|---|
| Registrar / Proxy / Host | sip.sendexa.co |
| Port (UDP/TCP) | 5060 |
| Port (TLS) | 5061 |
| Outbound proxy | sip.sendexa.co (same host) |
| Username / Auth ID | Your trunk auth.username |
| Password | Your trunk auth.password |
| Realm / Domain | sendexa.co |
| From domain | sendexa.co (or your verified domain) |
| Register | Optional — static IP ACL trunks often skip REGISTER |
| DTMF | RFC 2833 / telephone-event (preferred) |
Registration vs IP authentication
Sample PBX snippets
Minimal examples to reach the edge. Full production configs (NAT, SRTP, codecs) are covered in Trunk Configuration.
; Sendexa SIP trunk — Asterisk PJSIP[sendexa-auth]type=authauth_type=userpassusername=cc_trunk_prodpassword=S3cure-Long-Secret!realm=sendexa.co[sendexa-aor]type=aorcontact=sip:sip.sendexa.co:5061;transport=tlsqualify_frequency=60[sendexa-endpoint]type=endpointcontext=from-sendexadisallow=allallow=ulaw,alaw,g729,opusoutbound_auth=sendexa-authaors=sendexa-aorfrom_domain=sendexa.codirect_media=nortp_symmetric=yesforce_rport=yesrewrite_contact=yesmedia_encryption=sdestransport=transport-tls[sendexa-identify]type=identifyendpoint=sendexa-endpointmatch=sip.sendexa.co[sendexa-registration]type=registrationoutbound_auth=sendexa-authserver_uri=sip:sip.sendexa.co:5061;transport=tlsclient_uri=sip:cc_trunk_prod@sip.sendexa.coretry_interval=60; Omit registration if using static IP ACL only
Step 4 — Outbound test call (termination)
- From an extension on your PBX, dial a known good mobile in E.164 (include country code, e.g.
+233…). - Confirm your dialplan routes that call via the Sendexa trunk / gateway, not another provider.
- Expect normal ringback. On answer you should have two-way audio.
- Hang up cleanly and note the approximate duration for CDR checks.
SIP signaling path: your PBX INVITE → sip.sendexa.co → carrier → handset.
One-way audio checklist
rtp_symmetric, disable SIP ALG on the firewall, ensure UDP RTP ports (typically 10000–20000 on your side) are open, and prefer Sendexa media relay (direct_media=no) behind NAT.Step 5 — Assign a DID (origination)
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).
| Field | Type | Required | Description |
|---|---|---|---|
| number | string | required | E.164 DID you own on Sendexa, e.g. +233302123456. |
| trunkId | string | required | Target trunk ID returned from POST /v1/sip/trunks. |
| destination.primaryUri | string | required | SIP URI that receives inbound calls for this DID. Overrides trunk default if set. |
| destination.failoverUri | string | optional | Secondary URI if primary is unreachable. |
| destination.timeoutSeconds | integer | optional | Seconds to wait for 18x/200 from primary before failover (default 20). |
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}}'
{"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
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
| Direction | Port / Protocol | Purpose |
|---|---|---|
| Outbound + Inbound | 5060/udp, 5060/tcp | SIP signaling |
| Outbound + Inbound | 5061/tcp | SIP over TLS |
| Outbound + Inbound | RTP UDP (dynamic) | Media (Sendexa may relay) |
| Outbound | 443/tcp | REST API api.sendexa.co |
Go-live checklist
Need capacity or number inventory?
maxConcurrentCalls.