Skip to content

LiveKit Outbound

Route outbound calls from LiveKit onto the PSTN via SignalWire.

How It Works

  1. LiveKit initiates a SIP call to a SignalWire SIP Address
  2. SignalWire executes the assigned SWML script
  3. The connect verb bridges the call to the destination PSTN number
  4. The callee receives a call from your SignalWire phone number

SWML Script

yaml
version: 1.0.0
sections:
  main:
    - connect:
        answer_on_bridge: true
        from: "+1XXXXXXXXXX"
        to: "%{call.to.replace(/^sip:/i, '').replace(/@.*/, '')}"
  • Replace +1XXXXXXXXXX with your SignalWire outbound phone number
  • The to expression strips the SIP prefix and domain from the dialed address, extracting the raw E.164 number

Setup Steps

1. Create the SWML Script

Create a SWML script in your SignalWire Dashboard using the configuration above.

2. Add a SIP Address

In SignalWire:

  1. Go to SIP → SIP Addresses
  2. Create a new SIP Address
  3. Assign the SWML script to it
  4. Note the unique SIP domain (e.g., your-space.sip.signalwire.com)

3. Get Auth Credentials

Contact SignalWire Support to obtain the app password for your SIP Address. This is required for LiveKit's trunk configuration.

4. Create LiveKit Outbound SIP Trunk

In LiveKit:

  1. Go to SIP → Outbound Trunks
  2. Set the Address to your SignalWire SIP domain
  3. Add your SignalWire phone number(s) under Numbers
  4. Set Auth Username to your SignalWire phone number
  5. Set Auth Password to the Support-provided password
  6. Set Transport to 3 (TLS)
  7. Save the trunk

5. Initiate Calls

Use LiveKit's API to create a SIP Participant, which triggers an outbound call through the trunk.

Optional: Add Call Recording

To record outbound calls, create a second SWML script that calls record_call, then reference it via the confirm parameter in your main script:

yaml
# record.yaml
version: 1.0.0
sections:
  main:
    - record_call:
        stereo: true
        format: mp3

# main.yaml
version: 1.0.0
sections:
  main:
    - connect:
        answer_on_bridge: true
        from: "+1XXXXXXXXXX"
        to: "%{call.to.replace(/^sip:/i, '').replace(/@.*/, '')}"
        confirm: https://your-server.com/record.yaml

Troubleshooting

  • If calls fail to route, verify the SIP domain and auth credentials with SignalWire Support
  • Check that transport: 3 is set in the LiveKit trunk — SignalWire requires TLS
  • The to expression in the SWML must correctly strip the SIP URI to an E.164 number

SignalWire Developer Documentation