Skip to main content
Put your number on a Twilio Elastic SIP trunk, with LiveKit running your agent. Twilio carries out the transfer itself, so your agent leaves the call before the caller reads their card. Read Connect your phone system first for how the handoff works and what every setup needs.

Create the trunk

Your number must be on an Elastic SIP trunk, not Programmable Voice (why). Connect a trunk to LiveKit with LiveKit’s Twilio guide, then set these on it:
cURL
Set the Origination URI to sip:<your-livekit-sip-host>;transport=tls, using your LiveKit SIP host. With Secure Trunking on, Twilio refuses any unencrypted call.
Never turn on trunk recording, because it records the whole call, card entry included. Record with LiveKit Egress instead, which can’t capture card entry because the caller’s audio leaves the room at the transfer.

Create the LiveKit inbound trunk

One inbound trunk takes both new calls and returning callers, so list your number and the return user from your returnTarget, and turn on media encryption.
Add a dispatch rule that sends calls on this trunk to your agent.

Transfer the caller

When the caller is ready to pay, create the voice session with your returnTarget, then cold transfer the caller to its dialUri.
Pass dialUri exactly as returned. If creating the session or the transfer fails, offer the caller the checkout link instead. Your agent leaves the call only once your carrier accepts the transfer.

Recognize returning callers

When the payment is done, Natural asks Twilio to transfer the caller to your returnTarget. The caller arrives in a new room, addressed to pay-return instead of your phone number, and LiveKit puts that address in the caller’s sip.trunkPhoneNumber attribute. Use the caller’s own number, in sip.phoneNumber, to find the conversation, and accept the match only if you handed that caller to Natural within the last 30 minutes, the longest a payment call can run, since caller ID alone can be faked.
Before offering anything, read the session’s payment.outcome, and if it’s paid, don’t offer another transfer. If the caller’s number is withheld or matches no conversation, greet them as a new caller.

Why not Programmable Voice

A number on Programmable Voice (TwiML or a Twilio voice app) can’t hand a phone caller to Natural without staying on the call. Twilio’s <Refer> only works on calls that arrived over SIP, so a caller from the phone network can only be connected with <Dial>, which bridges the caller through your app. Your app then stays on the line and can record or stream the call while the caller reads their card.

Test it

Place a test call in Sandbox and run the go-live checks.