While building a Voice AI payment flow with Vapi, Twilio Voice, Twilio Conference, and Twilio Pay, we ran into an interesting call lifecycle problem.
The setup was designed so the customer could complete a secure payment through Twilio Pay and then continue with the same Vapi assistant, all within what feels like a single ongoing phone call.
Behind the scenes, the call is more complex:
- Customer leg enters Twilio Conference
- Vapi assistant joins as an SIP participant in the conference
- For payment, the customer leg is temporarily redirected to Twilio Pay
- After payment, the customer leg is returned to the conference
To make this work, the customer conference leg used `endConferenceOnExit: false`.
That was necessary. Otherwise, the conference would end as soon as the customer leg was redirected to Twilio Pay.
But it created an edge case.
While the customer is in the payment completion flow, Vapi is alone in the conference. So Vapi’s silence timeout must be long enough to avoid ending the assistant while the customer is entering card details.
We kept the silence timeout at 180 seconds. This can vary by use cases.
But if the customer actually hung up, Vapi still stayed alone in the conference, heard silence, and waited until the 180-second timeout before ending the call. We didn’t want that.
We first tried relying on Twilio conference callbacks, but they were not reliable enough. The backend received Vapi SIP participant callbacks, but not always the customer/conference exit event we needed.
So we added a backend watchdog that periodically checks the customer call status via Twilio REST API.
If the customer call is still active, nothing happens.
And If the customer is gone and no payment is active, the backend sends the control message to Vapi to exit the SIP leg immediately.
This avoids leaving the assistant alone in the conference for 180 seconds after a real customer hangup.