Search code examples
twilio

How can we transfer an outbound Twilio voice call to another number without dropping?


  • A makes outbound call to B
  • A wants to transfer the call to C without dropping B
  • A then wants to hang up leaving B and C on the call

I have read all similar questions here on SO. The developer evangelist has said to use conference calls from the start or look for and modify the child leg of a call.

Conference calls:

  • A creates conference (and joins it implicitly)
  • A dials B with webhook that responds with instructions to join same conference
  • A and B are in the conference
  • A wants to add C which is defined by TwiML at a URL -- not supported
  • A wants to hang up at this point leaving B and C on the conference call

Modifying the child leg doesn't work as it seems (as of at least June 2021) that there is no call sid created for the receiving party ("B" here) of a direct call. Modifying the direct call with new TwiML for instance changes the instructions for the caller ("A" here), dropping the receiving party (B) from the call.

Is there a way to accomplish A calls B then A transfers B to C without dropping B and then A hangs up (not dropping B or C)?


Solution

  • Twilio developer evangelist here.

    I think this question and the comments headed off in a roundabout way that wasn't exactly how to solve the initial problem. Here is what I think the real question is and some options for how to solve it:

    Question: In a two party call between participants A and B, where A dialled B, how do I send new TwiML to caller B to redirect them?

    In this scenario I am guessing that A has placed the call to B using Twilio Client or the Twilio Voice SDK. And that you have a TwiML application that returns TwiML to <Dial> caller B. To ensure you get the CallSid for caller B's leg you can use <Number> (or <Client> or <Sip>) to provide a statusCallback URL, like so:

    <Response>
      <Dial>
        <Number statusCallback="WEBHOOK_URL">CALLER_B_NUMBER</Number>
      </Dial>
    </Response>
    

    In the parameters of the webhook request for the status callbac you will receive a CallSid, which identifies the outbound leg of the call to B, as well as a ParentCallSid which identifies the initial leg of the call that A is connected to.

    You can then use this CallSid to update the call using the Calls resource and redirect caller B to new TwiML.

    As a note, this will drop caller A, unless you provide further TwiML after the <Dial> or in the response to a webhook to the URL action attribute. For example:

    <Response>
      <Dial>
        <Number statusCallback="WEBHOOK_URL">CALLER_B_NUMBER</Number>
      </Dial>
      <Say>Caller B either hung up or you successfully transferred them away.</Say>
    </Response>
    

    Or

    <Response>
      <Dial action="/after-outbound-dial">
        <Number statusCallback="WEBHOOK_URL">CALLER_B_NUMBER</Number>
      </Dial>
    </Response>
    

    And then return this in /after-outbound-dial:

    <Response>
      <Say>Caller B either hung up or you successfully transferred them away.</Say>
    </Response>
    

    The request to the action URL will include a parameter for DialCallStatus to let you know what the outcome of the call was so that you can return different results based on whether it was answered, busy, no-answer, etc.

    Alternatives

    We discussed in the comments using a conference to perform this action. While a conference is more expensive, it can give a much better experience to the person being transferred. In the case I describe above, transferring caller B will be an abrupt change from talking to caller A to whatever TwiML is next. Using a conference call and dialling a 3rd partner, C, into the call can allow for a warm transfer where caller A can introduce C and also fill in C on what is happening with caller B before dropping.

    This does only apply in the case where your transfer is between people. If you need to transfer B to something automated, like a post call survey, then my answer above will suffice. It's just worth considering the conference in case there are warm transfer scenarios you want to explore in the future.