Origination & Termination
How calls enter and leave the Sendexa SIP edge: map DIDs to SIP URIs for inbound service, dial out to the PSTN with authenticated trunks, configure failover, and understand CLI presentation rules.
Origination
PSTN callers dial your DID; Sendexa INVITEs your PBX or SBC at a SIP URI.
Termination
Your PBX INVITEs sip.sendexa.co with an E.164 destination; we complete to the PSTN.
Failover hunt
Primary and secondary destinations with timeouts for resilient inbound service.
CLI & attestation
Present verified caller IDs; STIR/SHAKEN on supported international routes.
DID→SIP
Origination
SIP→PSTN
Termination
sip…
sip.sendexa.co
POST
/v1/sip/numbers
Authentication
Authorization: Basic <token>. Auth guide →Call directions
A public telephone number (DID) hosted on Sendexa rings. We receive the PSTN call and create a SIP dialog toward your infrastructure.
→ carrier interconnect
→ Sendexa edge
→ INVITE sip:user@your-pbx:5061
→ your IVR / queue / agent
Direction in CDR:
An agent or application on your PBX places a call. Your system sends an authenticated SIP INVITE to Sendexa with a routable destination.
→ your PBX / SBC
→ INVITE sip:+233…@sip.sendexa.co
→ Sendexa + carriers
→ called party handset
Direction in CDR:
Origination — DID to SIP URI
Each DID is assigned to a trunk and given one or two destination URIs. When the number is called, Sendexa builds an INVITE with the DID as the Request-URI user (or To header, depending on profile) so your dialplan can match the called number.
| Field | Type | Required | Description |
|---|---|---|---|
| number | string | required | E.164 DID on your account, e.g. +233302123456. |
| trunkId | string | required | Trunk that owns billing context and optional default destinations. |
| destination.primaryUri | string | required | Full SIP URI. Examples: sip:233302123456@pbx.example.com:5061;transport=tls or sip:ivr@10.0.0.5:5060 |
| destination.failoverUri | string | optional | Tried when primary is unreachable or times out. |
| destination.timeoutSeconds | integer | optional | Primary hunt timeout before failover (default 20, max 60). |
| destination.headers | object | optional | Optional custom SIP headers added to the outbound INVITE toward your PBX (e.g. X-Sendexa-DID). |
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:233302123456@pbx.example.com:5061;transport=tls","failoverUri": "sip:233302123456@backup.example.com:5061;transport=tls","timeoutSeconds": 20,"headers": {"X-Sendexa-Trunk": "TRK-8c1e2b9a-4d3f-41a0-9e7c-12ab34cd56ef"}}}'
Typical INVITE shape (illustrative):
INVITE sip:233302123456@pbx.example.com:5061;transport=tls SIP/2.0Via: SIP/2.0/TLS sip.sendexa.co:5061;branch=z9hG4bK...From: <sip:+233555539152@sip.sendexa.co>;tag=...To: <sip:+233302123456@sip.sendexa.co>Contact: <sip:edge@sip.sendexa.co:5061;transport=tls>Call-ID: 5f2a...@sip.sendexa.coCSeq: 100 INVITEMax-Forwards: 70P-Asserted-Identity: <sip:+233555539152@sip.sendexa.co>Content-Type: application/sdpContent-Length: ...v=0o=- 0 0 IN IP4 ...s=Sendexa SIPc=IN IP4 ...t=0 0m=audio ... RTP/AVP 0 8 18 101a=rtpmap:0 PCMU/8000a=rtpmap:8 PCMA/8000a=rtpmap:18 G729/8000a=rtpmap:101 telephone-event/8000
- From / PAI — original caller ID when available
- To / Request-URI user — your DID (match in dialplan)
- SDP — media toward Sendexa relay or direct as configured
Inbound failover behaviour
| Primary response | Next step | CDR note |
|---|---|---|
| 100/180/183 then 200 | Media established on primary | destinationUri = primary |
| Connection refused / TLS fail | Immediate failover | failoverUsed = true |
| No response until timeout | Failover after timeoutSeconds | failoverUsed = true |
| 480 / 503 / 500 | Failover | hangupCause may reflect final leg |
| 486 Busy Here | No failover (subscriber busy) | status = busy |
| 404 / 484 | No failover (routing error on PBX) | status = failed |
| Both fail | Caller cleared with network error | status = failed |
Termination — SIP to PSTN
Outbound calls are pure SIP toward sip.sendexa.co. There is no separate REST “create call” for trunking (use the Voice API for programmable outbound). Your PBX is the call controller.
| Format | Example | Accepted? |
|---|---|---|
| E.164 with + | +233555539152 | Yes — preferred |
| E.164 digits only | 233555539152 | Yes |
| Local leading 0 | 0555539152 | Maybe — if account locale set; prefer E.164 |
| With trunk prefix | 9+233555539152 | Strip prefix on PBX before send |
| SIP URI user | sip:+233555539152@sip.sendexa.co | Yes |
# Request-URI examples your PBX may sendINVITE sip:+233555539152@sip.sendexa.co:5061;transport=tls SIP/2.0INVITE sip:233555539152@sip.sendexa.co SIP/2.0# Authorization: Digest username="cc_trunk_prod", realm="sendexa.co", ...# From / PAI should present a DID you are allowed to use as CLI
- Set outbound caller ID to a Sendexa DID assigned to your account (or an explicitly authorised CLI).
- Prefer
P-Asserted-Identityand a matchingFromuser part in E.164. - Unverified or spoofed CLIs may be rewritten, rejected with 403, or sent with reduced attestation.
- Privacy:
Privacy: idrequests restricted presentation where the destination network supports it.
STIR / SHAKEN
Attestation on supported routes
For destinations that participate in STIR/SHAKEN (notably the United States and other adopting markets), Sendexa can sign outbound Identity headers when:
- Your account is enabled for signed termination on that route
- The presented CLI is a number you fully control (full attestation A)
- Or partial knowledge yields attestation B / gateway C as appropriate
Ghana domestic and many regional African routes do not require STIR/SHAKEN today; normal CLI validation still applies. Attestation level, when present, is recorded on the CDR (attestation field).
Dialplan patterns
[outbound-sendexa]; 00 + country... internationalexten => _00X.,1,Set(CALLERID(num)=+233302123456)same => n,Set(CALLERID(name)=My Company)same => n,Dial(PJSIP/+${EXTEN:2}@sendexa-endpoint,60,tT)same => n,Hangup(); Local Ghana mobile 0XXXXXXXXX → +233exten => _0XXXXXXXXX,1,Set(CALLERID(num)=+233302123456)same => n,Dial(PJSIP/+233${EXTEN:1}@sendexa-endpoint,60)same => n,Hangup(); Already E.164exten => _+X.,1,Set(CALLERID(num)=+233302123456)same => n,Dial(PJSIP/${EXTEN}@sendexa-endpoint,60)same => n,Hangup()
Number lifecycle
Billing & direction
Best practices
- Always normalise to E.164 before leaving your SBC
- Set both primary and failover URIs for every production DID
- Use OPTIONS monitoring from your SBC toward Sendexa and vice versa
- Keep CLI inventory documented — only present numbers you own
- Log
Call-IDon your side and match to SendexacallId/sipCallIdin CDR