1
votes

I am having alot of trouble wrapping my brain around how to transfer an inbound call using Twilio. The idea is:

  1. Call Comes In
  2. Call is Connected to A Receptionist
  3. Receptionist Greets and Dials Extension - Presses #.
  4. Caller is transferred to the specified # / sip device.

I have implemented a portion of this flow. I used conference tag on the initial call in to force the caller into a room with hold music, and as that call comes in I dial the receptionist and then have the receptionist join the conference. This works perfectly.

What I cant figure out is how to grab the input from the receptionists phone and then act on it. For example, if the receptionist pushes #200* (or something to that effect), I want extension 200 dialed, and the caller in the conference put back on hold until the transferred party answers (all of which should be easy once I can grab the input and act upon it).

Any help on this is appreciated.

Thanks.

1
Have you checked out the tutorials on transfers here? twilio.com/docs/voice/tutorials/warm-transferphilnash
I have but the example is flawed in a number of ways. 1 it assumes the user is using the twilio client (we're using physical SIP phones), 2 the examples jump around from Laravel to Node.JS and so on - we're implementing using nothing but straight PHP - so the example of warm transfers is confusing at best. Thats why I posted the question here.MediaGiantDesign
Ok, so all your users are using SIP phones, even the receptionist? When you direct a call into them are you using <Dial><Sip> or are they just registering to a SIP trunk?philnash
Yes. All users currently are using SIP phones. Although we arent initiating the calls using Dial in twiml. Instead, when a caller calls in our app responds with twiml which creates a conference room and throws them into it. Our app at the same time, using the Twilio API, initiates a call to the receptionist with an end point that pushes the connected receptionist into the conference as well. The receptionists entry allows for startconferenceonenter as well as endconferenceonexit - so when they disconnect the call ends.MediaGiantDesign

1 Answers

2
votes

Twilio developer evangelist here.

Thanks for the extra detail in the comments. Your receptionist is dialed into a conference to deal with the incoming call using startConferenceOnEnter to stop the hold music and make the connection. This is a good start.

You say you also have endConferenceOnExit for the receptionist. I would remove that because in order to achieve this we are going to want to remove the receptionist from the conference and leave the caller in it while we sort out the transfer.

So, instead you're going to want to add hangupOnStar to your receptionist's TwiML. When the receptionist hits * the call with either request the action attribute for the original <Dial> or, if that is not present, will continue to the next TwiML verb after <Dial>. Either way, this is where you want to include a <Gather input="dtmf">. This will start Twilio listening for keypad tones.

Your receptionist can then dial the extension to connect to and press # to finish (the default finishOnKey. This will send a webhook to the action attribute of the <Gather> with the Digits in the body of the request. You can then pick those Digits out and initiate a new call to the user with that extension. When that call connects you can then drop them into the original conference.

So, that should look a bit like:

Receptionist TwiML:

<Response>
  <Dial hangupOnStar="true">
    <Conference startConferenceOnEnter="true" endConferenceOnExit="false">CALLERS_CONFERENCE_ID</Conference>
  </Dial>
  <Gather action="/transfer" input="dtmf" finishOnKey="#">
    <Say>Please enter the extension you want to dial</Say>
  </Gather>
</Response>

Then the /transfer action should, in pseudo code, do something like:

/transfer

def transfer
  extension = params["Digits"]
  twilioClient.calls.create( to: getNumberFromExtension(extension), from: TWILIO_NUMBER, url: "https://example.com/connect" )
  return "<Response><Hangup/></Response>" # this hangs up the receptionist
end

Finally, the /connect endpoint referenced in the new call above should return TwiML to drop the new caller into the conference:

<Response>
  <Dial>
    <Conference startConferenceOnEnter="true" endConferenceOnExit="true">CALLERS_CONFERENCE_ID</Conference>
  </Dial>
</Response>

You could even make the /connect endpoint the same as the original receptionist TwiML, which would allow the next person on the call to also transfer out by pressing * and dialling another extension.

Let me know if this helps at all.