Put caller on hold twilio version=1.5 - twilio

I'm trying to implement hold calls functionality with Twilio api.
What is the best way in 2018 without TaskRouter to put caller on hold?
I've been tried to use enqueue and conference but failed.
Maybe someone have the example of code for this. Thanks for helping!

Twilio developer evangelist here.
There is actually a direct way to place a caller on hold in a conference call with Twilio. Using the participants resource you can place a participant on hold by updating the resource, setting Hold to true. You can set a URL to play hold music by updating the HoldUrl at the same time.
See below for an example in PHP:
use Twilio\Rest\Client;
$sid = "your_account_sid";
$token = "your_auth_token";
$twilio = new Client($sid, $token);
$participant = $twilio->conferences("conference_sid")
->participants("participant_sid")
->update(array(
"hold" => True,
"holdUrl" => "http://www.myapp.com/hold"
)
);
Let me know if that helps at all.

Related

Listen live calls on Twilio

I'm trying to create an interactive dashboard that shows Twilio calls with the ability to listen to any ongoing calls. Is it possible? And what is the best approach I should take?
I saw two methods on the documentation which are Twiml Voice: and Twiml Voice: . Conference doesn't suit with my scenario because incoming calls are not ringing. And I couldn't find a way to listen to voice Streams on the documentation.
Note: Currently inbound calls are handled by Twilio function and WebSocket and outbound calls are handled by Twilio JavaScript SDK.
Thanks in advance.
If you want to listen to a live Voicecall you could try the Stream as IObert suggests. Or, you must use the Conference feature and add yourself as a "Coach." Don't be put off by the name Conference. Think of it as a Voicecall with many more helpful features. You can create a conference from an outbound call like this:
string accountSid = "ACxxxxxx";
string authToken = "xxxxx";
TwilioClient.Init(accountSid, authToken);
var voiceresponse = new VoiceResponse();
var say = new Say("Setting up your conference.");
var dialConference = new Dial();
dialConference.Conference(
name: "Your Conference"
startConferenceOnEnter: true,
endConferenceOnExit: true
);
voiceresponse.Append(say);
voiceresponse.Append(dialConference);
var twiml = voiceresponse.ToString();
var call = CallResource.Create(
twiml: new Twilio.Types.Twiml(twiml),
to: new Twilio.Types.PhoneNumber("E164 Number to Dial"),
from: new Twilio.Types.PhoneNumber("E164 Your Twilio Number")
);
Then once you have a conference started, you can add the second call from either an inbound or outbound call. With an inbound call, use Twiml to send the call to the conference. With an outbound call, use the REST API to add a Conference Participant.
From the client side, using the Twilio Javascript Client, you would then connect your device to the Conference with the correct Conference Twiml parameters which is explained here:
https://www.twilio.com/docs/voice/sdks/javascript/twiliodevice#deviceconnectconnectoptions
const device = new Device(token);
let call = await device.connect({
params: {
To: 'Your Conference'
}
});
I use a slightly different method...I use a button on the client that when you click it makes an outbound call to the "coach" using the Conference Participant REST API. The coach answers and is added with mute = true. The "coach" uses the Twilio Client for WebRTC but the same process will work with a "regular" phone line with a phone number. Using the Twilio Client in this way allows the coach to listen on their computer speakers which is convenient.
The harder part is you will need to keep track of which calls are active on the client side. Otherwise, you won't have an accurate list of which calls or conferences are active. Repeatedly polling the Twilio REST API for active calls is not recommended by Twilio and is super slow compared to using the webhooks to notify of call status changes.

Gathering speech during outbound twilio voice call

I am trying to create a voice call from twilio to a number using programmable voice.
I also intend to gather recipient's speech transcribed. However, the documentation contains examples and tutorials only for inbound voice calls.
This is what I have tried-
Initiating voice call:
client.calls
.create({
twiml: `<Response><Gather input="speech" action="https://ngrok-url-for-my-local-server/voice" method="POST" speechTimeout="5"><Say>Hey there, How are you?</Say><Pause length="4" /></Gather></Response>`,
to: toPhoneNumber,
from: myPhoneNumber,
})
.then((call) => {
console.log(call.sid)
console.log(call)
})
.catch((e) => {
console.log(e)
})
Code in handler for gathering speech-
const VoiceResponse = twiml.VoiceResponse
const res = new VoiceResponse()
res.gather()
console.log(res.toString())
However I am not getting anything useful in the console.
Can anybody point me to a useful tutorial or example or tell me what I should do ?
You need to first make the call and then modify the call to gather.
When you make the call using the new VoiceResponse() call you will be returned a SID for the call. Next, use that SID to modify a call that is in progress by redirecting to the Twiml to gather the digits.
You will have three legs:
Make the outbound call (you provided this code in your questions).
Modify the active outbound call by using the call's SID to redirect to a Gather twiml.
After the gather has finished tell the call what do to using the action parameter of the gather. Here is an example.
If you are trying to go for a conference bridge type feature where you press * to move into an admin type menu, you will need a more complex solution involving a conference call.

Conf call: Wait for first person to respond, then connect second person

Basic case: System will call person A. If person A picks up the phone it will call person B and the 2 will be connected.
I read several answers here such as https://stackoverflow.com/a/20976996/1907888 but it's still unclear.
Would the following work? It would call PERSON_A if person responds it will connect to conference then call PERSON_B and connect to same conference? Do I need to start the conference first?
$response = new VoiceResponse();
$dial = $response->dial('PERSON_A');
if($dial->conference('Room 1234')) {
$dial = $response->dial('PERSON_B');
$dial->conference('Room 1234');
}
Twilio developer evangelist here.
When you control calls with Twilio there are two mechanisms by which it works. There is the Twilio REST API which your application can use to make things happen, like start or change a call. Then there are webhooks, which are HTTP requests that Twilio makes to your application when things change in a call, like someone dialling your Twilio number, entering data on the phone, or an person answering an outbound call. You respond to webhooks with TwiML, a subset of XML, with instructions for what to do with the call next.
In this case, you want to place a call to person A to start with. For this, you will need the REST API to make that call. When person A answers the phone, Twilio will then make a webhook request to your application to find out what to do next. It is at this point that you can both call person B, again using the REST API, and place person A into a conference call, by responding with TwiML.
So, your initial outbound REST API call should look a bit like this:
use Twilio\Rest\Client;
// Find your Account Sid and Auth Token at twilio.com/console
// and set the environment variables. See http://twil.io/secure
$sid = getenv("TWILIO_ACCOUNT_SID");
$token = getenv("TWILIO_AUTH_TOKEN");
$twilio = new Client($sid, $token);
$call = $twilio->calls
->create($personANumber, // to
$yourTwilioNumber, // from
["url" => "http://example.com/conference.php"]
);
The URL you send when you place the call will be where Twilio sends the webhook request. So, in response to example.com/conference.php in this case, you will need to dial another person and respond with TwiML to direct person A into the conference call.
This time, instead of sending a URL, you can actually send TwiML in the REST API response. Something like this:
use Twilio\Rest\Client;
use Twilio\TwiML\VoiceResponse;
// Find your Account Sid and Auth Token at twilio.com/console
// and set the environment variables. See http://twil.io/secure
$sid = getenv("TWILIO_ACCOUNT_SID");
$token = getenv("TWILIO_AUTH_TOKEN");
$twilio = new Client($sid, $token);
$twiml = new VoiceResponse();
$dial = $twiml->dial();
$dial->conference("Conference Name");
$call = $twilio->calls
->create($personBNumber, // to
$yourTwilioNumber, // from
["twiml" => $twiml->toString()]
);
echo $twiml.toString();
In this case, I have used the same TwiML for both legs of the call, because they are both entering the same conference. You could respond with different TwiML based on what's happening.
Let me know if that helps at all.

Get phone number with twilio conference participant sid

How can I get a conference participant's phone number using the Twilio API? I am using the official Twilio PHP Library.
Hello Twilio Developer Evangelist here. 👋
What you can do is to fetch all active participants with a snippet like this (you can find more details in the docs for the conference participants.
<?php
// Update the path below to your autoload.php,
// see https://getcomposer.org/doc/01-basic-usage.md
require_once '/path/to/vendor/autoload.php';
use Twilio\Rest\Client;
// Find your Account Sid and Auth Token at twilio.com/console
// DANGER! This is insecure. See http://twil.io/secure
$sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
$token = "your_auth_token";
$twilio = new Client($sid, $token);
$participants = $twilio->conferences("CFXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
->participants
->read(array(), 20);
foreach ($participants as $record) {
print($record->callSid);
// "CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
Now, when you did this you'll see that the participant record does not include the phone number of the participant. But what it includes is the call_sid. The call sid helps you to identify the caller and retrieve call details.
There you have two options (I described something similar just recently here).
1. Persist the call information when you route callers into the conference
What you could do when you route people into the conference is to persist their numbers and call sids in your application. This way you could have a registry with all the people that entered your conference and access their phone numbers quickly when you need them.
2. Make another API call to get the call details and caller number
When you have the call SID what you can always do is to fetch the call details one by one.
<?php
$call = $twilio->calls("CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
->fetch();
print($call->from);
The first approach saves you API calls with the cost of maintaining your own persistence layer. The second approach makes more API calls but it is easier to set up.
As always, it depends on the situation.
I hope that helps. :)

Hold, unhold feature for Twilio call which is already running

I've a Twilio call already routed to an agent via TaskRouter(Task, Reservation is already created, Agent has accepted the call) and now an agent needs Hold, unhold feature for the same Twilio call.
Can someone please provide best practice for this?
Can we do this by en-queuing a call to Workflow?if yes then, how should we redirect same call to the same agent for Un-hold feature?
Please let me know if anyone has code snippet available. I'm using PHP for this
You can handle this one of a few ways but the basic process is:
First, provide Twilio some TwiML that places the call into "hold" then
when you're ready, use the CallSid of the call and the REST API to redirect the live call.
<?php
// Get the PHP helper library from twilio.com/docs/php/install
require_once('/path/to/twilio-php/Services/Twilio.php'); // Loads the library
// Your Account Sid and Auth Token from twilio.com/user/account
$sid = "YOUR_ACCOUNT_SID";
$token = "YOUR_AUTH_TOKEN";
$client = new Services_Twilio($sid, $token);
// Get an object from its sid. If you do not have a sid,
// check out the list resource examples on this page
$call = $client->account->calls->get("CALL_SID");
$call->update(array(
"Url" => "http://demo.twilio.com/docs/voice.xml",
"Method" => "POST"
));
echo $call->to;
To actually handle the "hold" you can use the <Enqueue> verb as you guessed, placing the call into a call queue. Then when you are ready, redirect that call back out of the queue to a new experience.
Or you can use <Play> and set the loop attribute to zero, which tell Twilio to loop audio indefinitely. And again, redirect the call when you are ready to remove the hold.

Resources