This guide explains how to connect active-call to Twilio Elastic SIP Trunking. Because Twilio uses standard SIP, the integration is almost identical to the Telnyx SIP Trunk integration. No Twilio SDK is required.
Twilio Elastic SIP Trunk
│
SIP/TLS (5061)
│
active-call (Rust)
│
AI Pipeline (ASR → LLM → TTS)
Twilio terminates the PSTN call and forwards it to active-call over SIP. All call intelligence runs inside active-call; Twilio acts purely as the carrier.
Key difference from Telnyx: Twilio Elastic SIP Trunking uses IP authentication for inbound calls — it does not support SIP REGISTER for receiving inbound traffic. For outbound calls, digest authentication (username/password) is used.
- A Twilio account with Elastic SIP Trunking enabled
- A public IP address reachable by Twilio's SIP network
- A TLS certificate (self-signed or CA-signed) for SIPS (recommended)
active-call≥ v0.3.38
- Log in to the Twilio Console.
- Navigate to Elastic SIP Trunking → Trunks → Create new SIP Trunk.
- Give it a descriptive name (e.g.
active-call-trunk).
Twilio sends inbound calls to your server via Origination URIs. Because Twilio uses IP authentication for inbound, no SIP REGISTER is needed.
- In your trunk, go to Origination.
- Add an Origination URI:
Or, if using plain UDP (not recommended for production):
sip:YOUR_PUBLIC_IP:5061;transport=tlssip:YOUR_PUBLIC_IP:5060 - Set the Priority and Weight as required.
- In your trunk, go to Termination.
- Note the Termination SIP URI, e.g.:
yourdomain.pstn.twilio.com - Under Authentication, create a Credential List:
- Add a username/password pair (e.g.
active-call/strongpassword). - These credentials will be used in your
active-call.toml.
- Add a username/password pair (e.g.
- Go to Phone Numbers → Active Numbers.
- Click a number and assign it to your trunk under Voice & Fax → SIP Trunk.
# SIP server bind address
addr = "0.0.0.0"
# Public UDP port (fallback / plain SIP)
udp_port = 5060
# TLS port for SIPS — required for Twilio production
tls_port = 5061
tls_cert_file = "./certs/cert.pem"
tls_key_file = "./certs/key.pem"
# Enable SRTP for encrypted media (recommended when tls_port is active)
enable_srtp = true
# Public IP for SDP/media negotiation
external_ip = "YOUR_PUBLIC_IP"
# RTP port range
rtp_start_port = 12000
rtp_end_port = 42000
# HTTP API port
http_addr = "0.0.0.0:8080"For outbound calls, configure a SIP registration to your Twilio Termination URI:
[[sip_registrations]]
name = "twilio"
username = "active-call" # Credential List username
password = "strongpassword" # Credential List password
server = "yourdomain.pstn.twilio.com"
realm = "yourdomain.pstn.twilio.com"Note: Twilio's Termination URI accepts SIP REGISTER, which keeps the trunk authenticated for outbound dialing.
Configure how active-call handles incoming calls from Twilio:
[handler]
type = "playbook"
default = "greeting.md"Or use a webhook to make the routing decision externally:
[handler]
type = "webhook"
url = "http://localhost:8090/twilio-inbound"
method = "POST"Twilio strongly recommends (and may require) SIPS (SIP over TLS) for production trunks.
openssl req -x509 -newkey rsa:2048 -keyout certs/key.pem \
-out certs/cert.pem -days 365 -nodes \
-subj "/CN=YOUR_PUBLIC_IP"Self-signed certificates work for testing, but Twilio may reject them in strict TLS mode. Use a CA-signed certificate for production.
certbot certonly --standalone -d sip.yourdomain.com
# Then reference:
# tls_cert_file = "/etc/letsencrypt/live/sip.yourdomain.com/fullchain.pem"
# tls_key_file = "/etc/letsencrypt/live/sip.yourdomain.com/privkey.pem"curl -X POST http://localhost:8080/call \
-H "Content-Type: application/json" \
-d '{
"callee": "sip:+18005551234@yourdomain.pstn.twilio.com",
"playbook": "sales.md",
"sip": {
"username": "active-call",
"password": "strongpassword",
"realm": "yourdomain.pstn.twilio.com",
"enableSrtp": true
}
}'enableSrtp is a per-call override. It takes priority over the global enable_srtp config. This lets you dial SRTP calls to Twilio while keeping plain RTP for internal SIP extensions, or vice versa.
API call sip.enableSrtp → overrides everything
Config enable_srtp → global default
Fallback → plain RTP (false)
active-call automatically extracts SIP headers from inbound INVITE requests. You can use them as variables in Playbooks:
# In your Playbook, access SIP headers:
# {{ X-Twilio-CallSid }} — Twilio's unique call identifier
# {{ X-Twilio-ToE164 }} — called number in E.164 format
# {{ X-Twilio-FromE164 }} — caller number in E.164 format- Verify your firewall allows TCP port 5061 (SIPS) and UDP/TCP port 5060 (SIP) from Twilio's IP ranges.
- Twilio's SIP IP ranges are published at: https://www.twilio.com/en-us/help/article/twilio-sip-network
- Check that
external_ipmatches the public IP Twilio can reach. - Ensure the RTP port range (
rtp_start_port–rtp_end_port) is open in your firewall. - If you enabled
enable_srtp = true, confirm Twilio's trunk also has SRTP enabled (Twilio enables it by default on TLS trunks).
- Confirm the Credential List username/password in Twilio matches
username/passwordin your[[sip_registrations]]block. - The
realmfield must match Twilio's Termination SIP URI domain exactly.
- If using a self-signed cert, the CN (Common Name) must match your public IP or domain.
- Check active-call logs for
TLS SIP transport startedto confirm TLS initialized correctly.
| Feature | Twilio Elastic SIP | Telnyx SIP Trunk |
|---|---|---|
| Protocol | Standard SIP | Standard SIP |
| Inbound auth | IP allowlist | SIP REGISTER or IP |
| Outbound auth | Digest (Credential List) | Digest (Credential List) |
| TLS support | Recommended | Optional |
| SRTP support | Supported | Supported |
| SIP REGISTER inbound | ❌ Not supported | ✅ Supported |
- Twilio Elastic SIP Trunking Docs
- Twilio SIP Trunk Origination
- Twilio SIP Trunk Termination
- Telnyx Integration Guide — for comparison
- Configuration Guide — full config reference