Skip to main content
Sayna auto-provisions the LiveKit SIP trunk + dispatch rule as soon as you populate the sip configuration and provide LIVEKIT_API_KEY / LIVEKIT_API_SECRET. All you need to do on the carrier side is tell Twilio where to send calls.
TL;DR – Create/choose a Twilio Elastic SIP trunk, add Sayna’s SIP domain/IP to the Origination list as a SIP URI (e.g., sip:sip.sayna.ai;transport=tcp), and make sure Twilio’s source IP ranges are present in SIP_ALLOWED_ADDRESSES.

Prerequisites

  1. sip block configured in Sayna (room_prefix, allowed_addresses, optional hooks).
  2. Public DNS record or static IP that routes to your Sayna deployment (Load balancer, ingress, etc.).
  3. LiveKit credentials so Sayna can create the trunk + dispatch rule automatically.
  4. Twilio account with Elastic SIP Trunking enabled.
Sayna creates the LiveKit resources (names sayna-{prefix}-trunk / sayna-{prefix}-dispatch) so you do not need to follow LiveKit’s manual steps from their quickstarts. Focus on the Twilio console configuration only.

Step 1 — Expose Sayna’s SIP endpoint

  • Pick a hostname such as sip.yourcompany.com that resolves to the Sayna service running with SIP enabled.
  • Ensure TCP 5060/5061 reaches Sayna (or whatever port your reverse proxy exposes for SIP traffic).
  • Add Twilio’s regional egress IP ranges to SIP_ALLOWED_ADDRESSES so Sayna accepts their traffic. Twilio lists these ranges in the Elastic SIP Trunking IP access control documentation — copy the ranges for every region you plan to use.
Example env vars:
export SIP_ROOM_PREFIX="sip-"
export SIP_ALLOWED_ADDRESSES="54.172.60.0/23,34.203.250.0/23,52.40.51.128/25" # Twilio us-east-1 + us-west-2
export SIP_HOOKS_JSON='[{"host":"sip.yourcompany.com","url":"https://backend.yourcompany.com/sip/events"}]'
Once Sayna boots, it provisions the LiveKit trunk/dispatch and you’ll see log lines similar to:
INFO Successfully provisioned SIP resources: trunk=sayna-sip--trunk, dispatch=sayna-sip--dispatch

Step 2 — Create or select a Twilio trunk

  1. In the Twilio Console, navigate to Elastic SIP Trunking → Trunks.
  2. Create a new trunk or open an existing one dedicated to Sayna.
  3. Give it a meaningful name (e.g., SaynaBridge).
You do not need to configure Termination for this integration unless you want Sayna to place outbound PSTN calls via Twilio. We only care about Origination (Twilio → Sayna).

Step 3 — Configure origination URI

Twilio needs to know where to send inbound SIP INVITE requests. Use the domain/IP where Sayna listens for SIP traffic.
  1. Inside the trunk, go to the Origination tab.
  2. Click Add new Origination URI.
  3. Set SIP URI to the Sayna address with TCP enforced:
    sip:sip.yourcompany.com;transport=tcp
    
  4. (Optional) Specify a Friendly Name like “Sayna Primary”.
  5. Leave the weight/priority defaults unless you have multiple Sayna regions.
  6. Save the trunk.
Twilio supports TLS/SRTP as well, but Sayna currently expects TCP. Keep the ;transport=tcp suffix in the URI to avoid UDP-only failures.
Behind the scenes Twilio now dials sip.yourcompany.com whenever the trunk’s phone numbers receive a call. Sayna detects the room_prefix, routes the call into the auto-provisioned LiveKit room, and forwards events/webhooks per your SIP configuration.

Step 4 — Map numbers to the trunk

  1. Still in the Twilio Console, open Phone Numbers → Manage → Active numbers.
  2. Assign the desired DID(s) to the trunk you configured.
  3. Test by dialing the number and watching Sayna logs—the connection should hit the SIP trunk and trigger your WebSocket workflow.

Operational checklist

  • Allowed addresses – keep Twilio IP ranges current; Twilio occasionally adds regions.
  • Health checks – monitor Sayna logs for Failed to provision SIP resources to catch LiveKit credential issues early.
  • Recording + hooks – configure livekit.enable_recording and SIP_HOOKS_JSON in Sayna if you want downstream webhooks when Twilio callers join/leave.
  • Twilio failover – add a backup Origination URI (secondary Sayna region) with lower priority if you run multi-region fleets.

Troubleshooting

SymptomLikely causeFix
Twilio calls immediately failOrigination URI unreachable or wrong transportVerify DNS resolves to Sayna, firewall allows TCP 5060/5061, and URI uses ;transport=tcp.
Twilio 403/603 responsesSayna rejected IPAdd the relevant Twilio IP range/CIDR to SIP_ALLOWED_ADDRESSES.
Sayna logs “SIP room_prefix is required”SIP env vars incompleteSet SIP_ROOM_PREFIX (and other SIP vars) before starting Sayna.
Calls reach Sayna but never hit LiveKitLiveKit credentials missing or invalidEnsure LIVEKIT_API_KEY/LIVEKIT_API_SECRET are configured so auto-provisioning can join the room.
LiveKit room created but no downstream hooks fireSIP_HOOKS_JSON empty or host mismatchPopulate hooks with the domains you expect in sip.h.to headers.
  • SIP configuration – field-by-field breakdown of Sayna’s SIP options (room prefix, hooks, auto-provisioning).
  • Twilio guide – reference article that inspired this flow (follow only the Twilio console steps; Sayna handles the LiveKit pieces).