LiveKit + BulkVS: inbound IP based, outbound registration

Written on October 09, 2026.

This guide connects Bulk Solutions SIP trunks to LiveKit Cloud using the method that fits each direction. Inbound calls use IP-based authentication: Bulk sends the INVITE to your LiveKit SIP URI. Outbound calls use the username and password from a Bulk registration trunk group: LiveKit answers our digest challenge on each INVITE and never sends a SIP REGISTER.

Inbound: IP-based Outbound: registration credentials (digest) No SIP REGISTER sip.bulkvs.com UDP/TCP 5060 G.711u · G.729a · RFC2833

How the integration works

LiveKit Cloud does not SIP-register to Bulk Solutions. Inbound is routed by host; outbound is authenticated by username and password on the INVITE.

Inbound · IP based

Caller → Bulk → LiveKit

A caller dials your Bulk DID. Our SBCs send the INVITE from one of our signaling IPs to your LiveKit SIP URI. A LiveKit inbound trunk that allows those IPs, plus a dispatch rule, places the caller in a room or hands the call to an agent.

Outbound · registration credentials

LiveKit → Bulk → PSTN

Your application calls LiveKit CreateSIPParticipant. LiveKit sends the INVITE to sip.bulkvs.com. Bulk challenges with 401/407, LiveKit answers with your registration trunk username and password, and we terminate the call on the PSTN.

Shared SIP settings

ItemValue
SIP proxy / SRVsip.bulkvs.com
SIP port5060 (UDP and TCP)
CodecsG.711u (PCMU), G.729a, T.38 pass-through where available
DTMFRFC2833 and inband (G.711u)
Bulk signaling IPsx.x.x.x
Find the real IPs at Portal -> Interconnection -> Interconnection Instructions
Inbound authenticationIP-based (Bulk host pointed at your LiveKit SIP URI)
Outbound authenticationDigest username/password from a Bulk registration trunk group (no SIP REGISTER)

Values to collect before you start

Have these ready from both portals. Replace the examples with your own project and numbers.

LiveKit SIP URI
LiveKit Cloud → Settings → Project. Example: sip:YOURSUBDOMAIN.sip.livekit.cloud
LiveKit SIP host
Same host without the scheme: YOURSUBDOMAIN.sip.livekit.cloud
Your Bulk DID
Example used below: 3109060901 / +13109060901
Bulk registration credentials
Username and password from your Bulk SIP registration trunk group (outbound only, see below)
LiveKit CLI (optional)
lk cloud auth after installing the LiveKit CLI
Use the SIP URI from project settings, not the WebSocket project URL (*.livekit.cloud without .sip). Sending INVITEs to the wrong host returns 404 No trunk found.

Inbound setup (IP based)

Route calls that arrive on your Bulk DID into LiveKit rooms or voice agents.

  1. Create a LiveKit inbound trunk

    In LiveKit Cloud go to Telephony → SIP trunks → Create new trunk, choose Inbound, then paste:

    {
      "name": "Bulk inbound",
      "numbers": [
        "+13109060901",
        "13109060901"
      ],
      "allowedAddresses": [
        "x.x.x.x",
        "x.x.x.x"
      ]
    }

    allowedAddresses lists the Bulk signaling IPs, one per line. Each x.x.x.x entry is a placeholder: replace it with one of the signaling IPs from Portal -> Interconnection -> Interconnection Instructions, and add one entry per IP listed there. Inbound calls can arrive from any of them.

    Include both number formats. Bulk sends the request URI as 1NXXNXXXXXX (example 13109060901). LiveKit often matches E.164 with a plus. Listing both avoids a trunk miss.

    Do not set a SIP username or password on this inbound trunk. Bulk inbound IP authentication does not send digest credentials.

    allowedAddresses: this field may need to be enabled on your LiveKit project by LiveKit support. If the dashboard rejects it, create the trunk with numbers only and ask LiveKit to turn on IP allowlisting.
  2. Create a LiveKit dispatch rule

    A trunk alone is not enough. A dispatch rule tells LiveKit which room to create. In Telephony → Dispatch rules:

    {
      "name": "Bulk inbound dispatch",
      "rule": {
        "dispatchRuleIndividual": {
          "roomPrefix": "call-"
        }
      }
    }

    To send every inbound call to a LiveKit agent, add roomConfig.agents and set agentName to your worker name.

  3. Point the Bulk DID at LiveKit

    In the Bulk Solutions portal:

    1. Interconnection → Host → Add your LiveKit SIP host: YOURSUBDOMAIN.sip.livekit.cloud, port 5060. Prefer the hostname over a frozen A-record IP. LiveKit Cloud addresses can change.
    2. If your portal screen only accepts IPv4, add the current resolved addresses and contact Bulk support so we can attach the FQDN for you.
    3. Interconnection → Trunk Group → Add and assign that host to the trunk group.
    4. Inbound → DIDs → Manage and set your telephone number to that trunk group.
    5. Wait 2–3 minutes for the host and trunk group to propagate to all Bulk SBC nodes.

    Inbound calls are sent from one of our signaling IPs to your LiveKit host with request URI 1NXXNXXXXXX.

    Do not assign a LiveKit DID to a SIP registration trunk group. A registration trunk only delivers inbound calls to the IP that last registered, and LiveKit Cloud never registers.
  4. Optional: pin inbound to the US LiveKit region

    If you want signaling to stay in the United States, use:

    YOURSUBDOMAIN.us.sip.livekit.cloud

Outbound setup (registration credentials)

Use the Bulk registration trunk username and password on a LiveKit outbound trunk. LiveKit sends an INVITE to sip.bulkvs.com and answers the digest challenge. No REGISTER is sent, and no LiveKit IP addresses need to be added to your Bulk account.

  1. Create a Bulk registration trunk group

    In the Bulk portal go to Interconnection → Trunk Group - Manage → SIP Registration Trunk Group → Create.

  2. Copy the Bulk credentials

    Go to Interconnection → Trunk Group - Manage and open the registration trunk group. Copy the username and password. Keep them private; they authorize calls on your account.

  3. Create a LiveKit outbound trunk

    In LiveKit Cloud go to Telephony → SIP trunks → Create new trunk, choose Outbound:

    {
      "name": "Bulk registration outbound",
      "address": "sip.bulkvs.com",
      "numbers": [
        "+13105551000"
      ],
      "authUsername": "YOUR_BULK_TRUNK_USERNAME",
      "authPassword": "YOUR_BULK_TRUNK_PASSWORD",
      "headers": {
        "X-Challenge": "1"
      }
    }

    Replace the placeholders with the Bulk trunk credentials. Address must be the hostname sip.bulkvs.com, not a single SBC IP. Save the trunk ID (ST_…) for API calls.

    When Bulk replies to the INVITE with a 401 or 407 challenge, LiveKit resends it with digest credentials from authUsername / authPassword.

  4. Place a call from LiveKit

    Create a SIP participant. Example CLI payload:

    {
      "sip_trunk_id": "ST_xxxxxxxxxxxx",
      "sip_call_to": "+13105551212",
      "room_name": "outbound-test",
      "participant_identity": "bulk-test",
      "wait_until_answered": true
    }

    Bulk accepts destinations as 1NXXNXXXXXX@sip.bulkvs.com or NXXNXXXXXX@sip.bulkvs.com.

Caller ID rules

Set LiveKit numbers / sip_number to a number on your Bulk account in one of these formats. Any other caller ID format is rejected:

FormatExample
10 digits3109060901
11 digits13109060901
E.164+13109060901

E911

Emergency calling uses the same outbound trunk. Caller ID must be a provisioned 10-digit, 11-digit, or +E.164 number.

PurposeSend the call to
Emergency911@sip.bulkvs.com
Verify the address currently in the 911 database922@sip.bulkvs.com or 933@sip.bulkvs.com
Do not use 911 for connectivity tests. Use 922 or 933 to confirm the address on file, then place a live 911 call only when required.

Test plan

Inbound · IP based

Bulk → LiveKit

  1. Dial your Bulk DID from a mobile phone.
  2. Open LiveKit Cloud → Telephony → Calls.
  3. Confirm an INVITE arrived, a SIP participant was created, and a room named call-… exists.
  4. Confirm two-way audio with G.711u or G.729a.
Outbound · digest

LiveKit → Bulk

  1. Run CreateSIPParticipant to a number you control.
  2. If Bulk returns 401/407 and then the call connects, digest auth is working.
  3. Answer the call and confirm caller ID is your Bulk DID.
  4. Send DTMF if your app uses menus (RFC2833).
  5. Optionally call 922@sip.bulkvs.com to verify E911 data.

Troubleshooting

SymptomWhat to check
No INVITE in LiveKitBulk host, trunk group, and DID assignment. Wait for 2–3 minute propagation. Confirm the host is the project SIP URI and the DID is on the IP trunk group, not a registration trunk group.
404 No trunk foundNumber format mismatch. Add both +1NXXNXXXXXX and 1NXXNXXXXXX to the inbound trunk. Confirm you used the SIP URI, not the LiveKit WebSocket URL.
Inbound 403 / ignoredLiveKit allowedAddresses is missing one or more of our signaling IPs (see Portal -> Interconnection -> Interconnection Instructions), or the INVITE was sent to the wrong project subdomain.
Inbound works, then later failsThe Bulk host was a single resolved LiveKit IP that changed. Switch the host to the LiveKit FQDN.
Outbound 401 / 407 repeating, or 403 from BulkWrong authUsername / authPassword on the LiveKit outbound trunk, credentials copied from the wrong trunk group, or the registration trunk group has not been created. Re-copy the credentials from Interconnection → Trunk Group - Manage.
Outbound still rejected with correct credentialsBulk may require an active registration before accepting digest INVITEs on some accounts. Send the Call-ID to support so we can review the SIP ladder.
Outbound rejected caller IDFrom number is not 10-digit, 11-digit, or +1 E.164.
Call connects with no audioConfirm codec negotiation includes G.711u or G.729a, and that no firewall on your side blocks SIP media.
SIP 405 on REGISTERExpected. LiveKit does not accept or send REGISTER; this setup does not need it.

Need help?

If you get stuck on either side of the trunk, send us the DID, LiveKit SIP URI, trunk group name, approximate call time, and a Call-ID. We can pull the SIP ladder from our network.

Bulk Solutions support
Phone: 855-906-0901 or 310-906-0901
Email: support@bulkvs.com
Portal: interconnection, trunk groups, and DIDs

Related guides: LiveKit IP-based guide · LiveKit registration guide
LiveKit Cloud documentation for trunks and dispatch rules: docs.livekit.io/telephony