Sending call to multiple clients via conference participants REST API - twilio

I am trying to switch our old call flow to the conference and I have ported most of the features to the conference. I am trying to handle incoming calls in cases where I have to ring to multiple agents and disconnect the call after one of them.
Right now I am doing something along the lines of::
Cutomer calls :: call is sent to webhook -> Get list of all active agents and send the twiml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Client>
<Identity>jane</Identity>
<Parameter name="FirstName" value ="Jane"/>
<Parameter name="LastName" value ="Doe" />
</Client>
<Client>
<IdentityHarry</Identity>
<Parameter name="FirstName" value ="Jane"/>
<Parameter name="LastName" value ="Doe" />
</Client>
</Dial>
</Response>
This way I can ring both ( or more) clients and call drops after the first agent answers.
How I achieve something like this with conference?
What I want is:: ->
Customer calls:: call is captured into webhook =>
customer is dropped into the conference call with some music.
- Dial to clients :: (harry, jane) and connect them to the call.
Is there a way I can do this with via rest api to conference participants api?

Yes, you can do this with the REST API. Your webhook should respond with:
<Response>
<Dial>
<Conference waitUrl="YOUR_HOLDING_MUSIC">YOUR_ROOM_NAME</Conference>
</Dial>
</Response>
The only thing about using the REST API is that it doesn't perform the same as multiple <Client> elements. That is, when someone answers the phone, you have to cancel all the other calls. To do this, you will need to store the call SIDs that are created when you call the API, use status callbacks to know when a participant has connected, and then when you get the first status callback, cancel the other calls. So, something like this to make the calls and get the call sids:
def call_conference(client_name):
client = Client(account_sid, auth_token)
participant = client.conferences('YOUR_ROOM_NAME') \
.participants \
.create(
status_callback='https://myapp.com/events',
status_callback_event=['answered'],
from_='YOUR_TWILIO_NUMBER',
to='client:' + client_name
)
return participant.sid
clients = ["jane", "harry"]
participants = map(call_conference, clients)
Then, when that status callback event fires, filter the call sid from the list of sids you have and cancel the other calls.

Related

Twilio call forwarding one after another - how to disconnect if person picks up the call

<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say> Connecting call to Pinto </Say>
<Dial record ="record-from-answer" timeout="10" hangupOnStar ="true">
<Number>XXXXXXXX</Number>
</Dial>
<Say> Pinto is not picking up the call, now connecting call to Management </Say>
<Dial record ="record-from-answer" timeout="10" hangupOnStar ="true">
<Number>XXXXXXXX</Number>
</Dial>
<Say> No one is picking up right now. Please text us at +12022171828 </Say>
</Response>
Above is the call forwarding flow for one after another.
What I'm looking here is,
If 1st user attended the call, then it should not initiate the call to 2nd number and also it should not say text message which is at last line
If 1st user disconnected, then redirect call to 2nd number - if 2nd number not picking up the call then it should say text message which is at last line
if 1st user disconnected, then redirect call to 2nd number - if 2nd number picked up the call then it should not say text message which is at last line
Also I want to Implement Transcribe & Transcribe call back by using TwiML.
So, please help me like how we need to do with that?
To carry out this flow, you cannot perform the entire thing in one TwiML response. Instead, you will need to provide the <Dial> element with URL in the action attribute so that once the first call completes, Twilio makes a webhook to find out what to do next.
So, your first TwiML response should look like:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say> Connecting call to Pinto </Say>
<Dial record="record-from-answer" timeout="10" hangupOnStar="true" action="/complete">
<Number>XXXXXXXX</Number>
</Dial>
</Response>
Above I've added action="/complete" to the <Dial> and this means we need an application to be able to respond to HTTP requests to /complete as well. We also need this to be an application and not a static response as we need to work out whether the call was answered or not and decide on what to do next and what TwiML to respond with.
We can do this because one of the parameters that Twilio sends to the action URL is DialCallStatus. This parameter can be "completed", "busy", "no-answer", "failed" or "canceled" and this tells you what happened in that first call.
So, in your case, you will want to check the DialCallStatus and if it is "completed" then you do not need to return the next <Say> and <Dial>. If, however, the DialCallStatus is one of the other statuses, you do want to return the next <Say> and <Dial>. That <Dial> should include another action URL that makes the same choice at the end of the second <Dial>.
I'm not sure what language you are building with, but a pseudo-code idea of this would look like this:
post '/complete' do
if params["DialCallStatus"] != "completed"
return "<Response><Hangup/></Response>"
else
return "<Response><Say>Pinto is not picking up the call, now connecting call to Management</Say><Dial ....></Response>"
end
end

Can I associate a Twilio recording with the child called that initiated it?

So here's my issue:
I initiate a Twilio call via the API
When the call is picked up, Twilio reaches out to my Twiml server and gets a response containing the following (notice the "record" parameter of the Dial verb):
<Dial callerId="555-555-5555" record="record-from-ringing">
<Number statusBallbackEvent="completed" statusCallbackMethod="POST" statusCallback="https://myCallback.com">
555-555-5556
</Number>
</Dial>
The call gets placed and is recorded correctly, but the value of Call Sid for the recording is always the Sid of the parent call. This can be problematic if I use multiple Dial verbs during the course of one call.
Is there a way to figure out which child call initiated the recording?
To grab your child call SID, I'd recommend using an action URL in the verb that originates it. A request to this action URL would return the 'DialCallSid' parameter in Twilio's response:
https://www.twilio.com/docs/api/twiml/dial#attributes-action-parameters
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/dial_callstatus.xml -->
<Response>
<Dial action="/handleDialCallStatus.php" method="GET">
415-123-4567
</Dial>
<Say>I am unreachable</Say>
</Response>
You could then store or use that SID however you would like.
Please let me know if this helps at all.

How can I handle reaching voicemail using Twilio's <dial> verb

I know that on making a call Twilio can detect an answering machine, and react differently.
However if I use the <dial> verb, there's no obvious place to add this feature, even though it's essentially the same thing.
My intended flow is:
Customer enters their phone number
Twilio calls Customer and plays a voice message
Twilio dials an agent number, likely a mobile
If the Agent picks up, connect the customer to the agent
If the Agent busies the call or does not answer, call will likely go to Agent's voicemail.
Terminate call to Agent
Record voicemail from Customer
Email voicemail to Agent
From the official docs on the <Dial> verb (emphasis mine):
This is the simplest case for Dial. Twilio will dial 415-123-4567. If someone answers, Twilio will connect the caller to the called party. If the caller hangs up, the Twilio session ends. If the line is busy, if there is no answer, or if the called party hangs up, <Dial> exits and the <Say> verb is executed for the caller before the call flow ends.
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/simple_dial.xml -->
<Response>
<Dial>415-123-4567</Dial>
<Say>Goodbye</Say>
</Response>
Placing a <Record> verb after the <Say> verb sounds like what you are looking for. You can change the timeout from the default value of 30s like this:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial timeout="9001">415-123-4567</Dial>
<Say>Please leave a message</Say>
<Record action="/process_new_voicemail" />
</Response>
I am sure this is late, but hopefully it helps some one out. It sounds like you may just need to screen the call.
Basically, you can ask the "agent" that you dialed to accept the call and hang up if you do not receive input.
I am not sure what language you are using, but here is a great php/Laravel tutorial to explain:
https://www.twilio.com/docs/tutorials/walkthrough/ivr-screening/php/laravel
The key part is here:
$dialCommand = $response->dial(
['action' => route('agent-voicemail', ['agent' => $agent->id], false),
'method' => 'POST']
);
$dialCommand->number(
$numberToDial,
['url' => route('screen-call', [], false)]
);
Notice that the dial command uses the 'action' to specify a location that is sent a POST request should the call end i.e POST to /agent-voicemail.
Then, the number is dialed along with a 'url' parameter this is the location that will be requested after the agent has picked up but before connecting the two parties.
The /screen-call route then asks the agent to accept the call, if no input is received it hangs up and will make a POST request to the initial setup /agent-voicemail route.
This method will handle your scenario because if it goes to voicemail no input will be received and the call will end.

Announcing the name of participant joining the Conference

I am building a simple conference using Twilio where a conference is started by Agent using Twilio client and a contact is called and added to this conference. Just before adding this contact to conference, we would like to announce the name of the contact in the conference room (for ex: <Say>Now Joining Sam Carter </Say>). The name of the person is figured out based on their phone number from database.
When a call is connected, the following TwiML is executed which connects the contact to the conference:
<Dial callerId="+1415xxxxxxx" record="true" action="/my/action/url">
<Conference endConferenceOnExit="true" >ConferenceRoom1</Conference>
</Dial>
Is there any way to play a message into conference just before <DIAL> verb is executed. If i write <SAY> verb before <DIAL> then it plays message to the contact, not in the CONFERENCEROOM1.
Are there any events like onConferenceEnter, which can be used to fire another TwiML whenever some participant enters the conference? Please suggest what would be the best way to achieve this behavior.
The short answer to the question is that it can't be done through a Twiml Event however it can be done with a kind of hack using their REST API.
The question has already been asked on SO and the answer is available here:
Use Say verb to all Conference participants
Incase the question/answer is ever deleted/removed i've pasted it below:
Here's something that should resemble a good end-to-end solution.
First, the user dials in and you go through the standard prompts to get the PIN for the conference room and their name.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather action="/conference/pin" finishOnKey="#">
<Say>Please the conference pin number followed by the pound key.</Say>
</Gather>
</Response>
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>Say your name and then press the pound key.</Say>
<Record action="/conference/name" finishOnKey="#" />
</Response>
Now, once you have the user's pin and recording, two things will happen; the response from the post to /conference/name will contain the verb, placing the user in the room:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference>{conference ID}</Conference>
</Dial>
</Response>
...and, asynchronous to that, it will use the REST API to initiate a new call back into the conference room.
POST /2010-04-01/Accounts/{AccountSid}/Calls
From = {your conference phone number}
To = {your conference phone number}
SendDigits = wwww{conference PIN}#
Url = /conference/announce?name={name ID}
Now, the next bit gets confusing. Twilio will now be talking to your callback URL for the incoming end of the call, and the URL you specified above for the outgoing end of the call. Your incoming call handler will need to detect that the conference line is calling back into itself and behave differently; it will first need to respond with simple TwiML that allows the outgoing end of the call to enter the pin for the conference room.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather action="/conference/announce-pin" finishOnKey="#" />
</Response>
The SendDigits parameter of the POST will provide the digits that bit of TwiML is expecting. That action should then respond by conferencing in the new call.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference>{conference ID}</Conference>
</Dial>
</Response>
The last piece of the puzzle is the TwiML emitted by the URL you specified in the POST. That's the markup that will run once the loopback call is added to the conference.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play>/conference/name-recordings/{name ID}</Play>
<Say>has joined the call.</Say>
<Hangup />
</Response>
That markup runs, plays the caller's name and a message into the conference room, and then hangs up.
For benefit of others, this is how I have implemented this behavior :
An agent has started the conference using Twilio client and he is already in conference. As soon as a participant is about to join the same conference, using REST API, modify the URL of the live conference call.
TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN);
Map<String, String> filter = new HashMap<String, String>();
filter.put("From", "client:AGENT1");
filter.put("Status", "in-progress");
CallList callList = account.getCalls(filter);
Call agentsCall = null;
for (Call inProgressCall : callList) {
agentsCall = inProgressCall;
break; //return the first one only..there shouldn't be more
}
Map<String, String> agentsCallParams = new HashMap<String, String>();
agentsCallParams.put("Url", "http://myserver.com/twiml/agentmessage.xml");
agentsCallParams.put("Method", "GET");
agentsCall.update(agentsCallParams);`
The above code snippet will update the twiml of existing call as below.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>Now joining {name of the participant}</Say>
<Dial>
<Conference>Conference1</Conference>
</Dial>
</Response>
The above Twiml will update the call to play the message in <SAY> verb and then put the agent back into the conference.
Now, make the participant join the same conference by returning the below Twiml:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference>Conference1</Conference>
</Dial>
Hope this helps !!!

Use Say verb to all Conference participants

I'm setting up a pretty simple conference call system, where the user enters a PIN and is connected to a conference associated with that. I'm also setting it up so they record their name before entering the room.
My plan is to take the recording URL, then get the list of participants and make the REST API call to each caller modifying their call to to the Say "Now entering", then Play the recording url. I think I'm going to have to send them back into the room after that as well, I'm not sure.
I think that modifying each call will take them out of the Conference room, which is not ideal. Is there an easier way to use Say/Play to all members of a conference built into the REST API?
As of July 13th 2018, Twilio now allows you to send a POST request to the Conference (to announce something to the whole conference) or Conference Participant (to announce something to a single caller) resources with an AnnounceUrl property that links to either:
a WAV or MP3 audio file, or
a TwiML document that uses the <Say /> and/or <Play /> verbs.
Along with that property, you can also specify an AnnounceMethod property that lets you specify whether to GET or POST (the default) that URL.
A good place to send the aforementioned POST to play back your recorded name might be in a status callback that's set when you use the <Conference /> verb to put each user into the conference, like so:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference statusCallback="/conference/join-callback"
statusCallbackEvent="join">
{conference ID}
</Conference>
</Dial>
</Response>
The old workaround remains below for posterity.
Someone on the Twilio forums was interested in the very same question, and the answer is currently that there isn't a direct REST API call for that.
What you'll need to do is, when a participant joins the conference, you'll use the REST API to make Twilio dial back in to your application. You can choose how to detect that you're calling into your own conference however you like (for example, comparing the outbound and inbound phone numbers for equality); once you've detected that, you can join that call directly to the conference and use the TwiML <Say /> and <Play /> verbs to play back the introduction for everybody.
It's a little bit convoluted, but this way you won't be removing each participant from the conference (preventing them from hearing each other for a moment) and then rejoining them.
Here's something that should resemble a good end-to-end solution.
First, the user dials in and you go through the standard prompts to get the PIN for the conference room and their name.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather action="/conference/pin" finishOnKey="#">
<Say>Please the conference pin number followed by the pound key.</Say>
</Gather>
</Response>
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>Say your name and then press the pound key.</Say>
<Record action="/conference/name" finishOnKey="#" />
</Response>
Now, once you have the user's pin and recording, two things will happen; the response from the post to /conference/name will contain the <Conference> verb, placing the user in the room:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference>{conference ID}</Conference>
</Dial>
</Response>
...and, asynchronous to that, it will use the REST API to initiate a new call back into the conference room.
POST /2010-04-01/Accounts/{AccountSid}/Calls
From = {your conference phone number}
To = {your conference phone number}
SendDigits = wwww{conference PIN}#
Url = /conference/announce?name={name ID}
Now, the next bit gets confusing. Twilio will now be talking to your callback URL for the incoming end of the call, and the URL you specified above for the outgoing end of the call. Your incoming call handler will need to detect that the conference line is calling back into itself and behave differently; it will first need to respond with simple TwiML that allows the outgoing end of the call to enter the pin for the conference room.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather action="/conference/announce-pin" finishOnKey="#" />
</Response>
The SendDigits parameter of the POST will provide the digits that bit of TwiML is expecting. That action should then respond by conferencing in the new call.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference>{conference ID}</Conference>
</Dial>
</Response>
The last piece of the puzzle is the TwiML emitted by the URL you specified in the POST. That's the markup that will run once the loopback call is added to the conference.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play>/conference/name-recordings/{name ID}</Play>
<Say>has joined the call.</Say>
<Hangup />
</Response>
That markup runs, plays the caller's name and a message into the conference room, and then hangs up.

Resources