I've built an IVR system and I cannot achieve how agents can see real callers numbers, not the proxy number (aka Twilio's number):
$response->enqueue('commercial', ['waitUrl' => 'https://xxxxxxxion.com/playStory']);
$call = $client->calls->create(
'+407xxxxxxx15',
'+403xxxxxxx56',
array("url" => "https://xxxxxxxx.com/queues.php?type=commercial", 'timeout' => 15, 'record' => true, "statusCallback" => "https://xxxxxxxxx.com/notify.php", "callerId" => $_REQUEST['From'])
);
I have tried an alternative with "callerId" => $_REQUEST['From'] to get the Caller ID at the end of the call, but this parameter doesn't appear nowere.
With SIP calls is simple because I can set From parameter directly in the method call:
$call = $client->calls->create(
'sip:xxxxxxx.sip.us1.twilio.com',
$_REQUEST['From'], //here I set real Caller ID for Agent to see
Tried also with call forwarding, but cannot put the callers into a queue, or, at least to have a waitUrl for on-hold audio - the part I really need in this story.
Twilio developer evangelist here.
With Twilio you can only set the From parameter, the caller ID, of an outbound call, the call you are making using the REST API, to a number you have either bought with Twilio or verified that you own.
The only way to forward on the original caller ID is to use <Dial> to connect the calls, but you say you need wait music.
One alternative you could use is to perform a call whisper that reads out the number that the agent is about to be connected to, using <Say>, and then connecting them to the queue.
Let me know if that helps at all.
Related
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.
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.
The code below intercepts a call in progress and transfer the call to a new number (This piece works as expected).
The question is:
Should I mark the original call as "completed"
How do I do this?
$call_sid = $_SESSION['CallSid'];
$sid = 'xxxxxxxxxxxxxxxxxxxxxxx';
$token = 'xxxxxxxxxxxxxxxxxxxxxxx';
$twilio = new \Twilio\Rest\Client($sid, $token);
$call = $twilio->calls($call_sid)->update(['twiml' => '<Response><Say>Redirecting to Buba</Say><Dial callerId="+18888880592">+14888068886</Dial></Response>']);
//TODO cancel this CALL SID. Status=completed??
print($call->to);
The Twilio call legs are kept up via Twilio Markup Language (TwiML). If you modify one call leg which appears to be what you are doing, if there is another call leg (no conference involved) that is part of that call, that leg will begin processing any TwiML after the <Dial> that originally connected the two parties. If there is no TwiML after the <Dial>, Twilio will hangup that call leg, so no action required on your side.
You should be able to see this behavior in your call logs.
I'm trying to create a phone system where a caller gets enqueued, and ideally, the system will then call out to an agent, who would then pickup and then modify the call to bridge the top of the queue.
What I've accomplished thus far is the dialing loop, where a user calls in, and it dials agents in sequence, until someone picks up, or gives the user the option to leave a message or stay on the line while hearing it ring. And a simple enqueue with hold music.
I just can't seem to figure out how to combine these two systems.
The closest I've found is this post, and it's helpful, but it glosses over how to call out once the caller is enqueued.
Unfortunately, the only Twilio documentation I've found thus far tells me how to dial into the queue, which isn't what I want out of this system. I want this system to place a caller in a queue with hold music, while the system then dials agent numbers until an agent picks up.
Any and all help is much appreciated.
Thanks.
Edit:
Solution
index.php
This is the general IVR tree that the caller initially hits.
<Say>This hits your general IVR tree</Say>
<Say>As the last action, since the caller hasn't pressed anything and should be enqueued, redirect the caller to EnqueueCaller.php</Say>
<Redirect>./EnqueueCaller.php</Redirect>
Since PHP is a preprocessor, there's no real way to sleep or timeout the dialing of the call. The redirect in the IVR tree is necessary so the Agents aren't being dialed when the user is still in the IVR tree.
EnqueueCaller.php
This is where the Caller gets redirected once the IVR tree has finished and the user has chosen to wait for an agent. The call actually happens before the Enqueue, since PHP loads first before the TwiML xml is read (I think?). But since there's an inherent delay when calling, the caller will always be enqueued before an agent can pick up (I hope).
<Enqueue waitUrl="wait_file.xml">name_of_queue</Enqueue>
$call = $client->account->calls->create($from, $to, "http://example.com/DialQueueHandler.php", array( "StatusCallback" => "DialQueueEventHandler.php" );
DialQueueHandler.php
This simply bridges the agent and whoevers at the top of the queue.
<Say>Connecting to caller now.</Say>
<Dial><Queue>name_of_queue</Queue></Dial>
DialQueueEventHandler.php
This script houses the logic for what happens when the dialed agent state changes (answered, complete, initiated, ringing) from $_REQUEST['CallStatus']. In my case, I dialed a single agent from the enqueue script, and in this script, either continue dialing the next agents via setting of a flag.
switch($_REQUEST['CallStatus'] {
case 'answered':
case 'completed':
$next = false;
break;
default:
$next = true;
break;
}
if($next) { $call = $client->account->calls->create($from, $nextAgentNumber, "http://example.com/DialQueueHandler.php", array( "StatusCallback" => "DialQueueEventHandler.php?agentOffset=$num" ); } //same line from EnqueueCaller.php, and track where we are in agent array.
If the call is not answered or completed, then dial the next agent. Otherwise when the call is picked up by an agent, the DialQueueHandler.php file gets hit and the call becomes bridged.
Jeff, I'm Megan from Twilio.
You can utilize the workflowSid attribute of <Enqueue> to configure a Task which initiates the call flow to an available agent using TaskRouter. There is a TaskRouter quickstart in PHP and I think given where you've gotten so far, you could pick up on the third part.
Let me know if you find this to be helpful.
I want to modify the live callStatus of twilio using it's REST API. I have listed all the available queue phone number and want to modify callStatus from queued to call in-progress or ringing.How do i get this?.
Twilio evangelist here.
You can use the REST API to dequeue a specific call waiting in a queue. To do this you make a POST request to the CallSid you want to redirect, but you have to do it through the Members resource. As part of that HTTP request, you pass in a Url parameter. Doing that tells Twilio to redirect that call out of the queue, make an request to that Url and then start executing the TwiML returned.
$member = $client->account->queues->get('QU5ef8732a3c49700934481addd5ce1659')->members->get("CA5ef8732a3c49700934481addd5ce1659");
$member->update(array(
"Url" => "http://demo.twilio.com/docs/voice.xml",
"Method" => "POST"
));
Now, to make this request you need to know the SID of the Queue you want to work with and the CallSid of the Queue Member you want to redirect.
Lets walk through getting those two values.
Locating a Queue SID
There are any number of ways to get a Queues SID. If you use the REST API to create Queues then your app could save the Queue SID each time it creates a new Queue:
$queue = $client->account->queues->create("newqueue", array());
echo $queue->sid; //save the sid in a db or some other store
or you can use the REST API to list all of your Queues. For example, here I am using REST API to get the list of Queue resources, loop over them and print the current average wait time:
// Loop over the list of queues and echo a property for each one
foreach ($client->account->queues as $queue) {
echo $queue->average_wait_time;
}
If you wanted to find a specific Queue by using its Friendly Name, you could modify this to loop to look at the *friendly_name* parameter of each Queue.
// Loop over the list of queues and echo a property for each one
foreach ($client->account->queues as $queue) {
echo $queue->friendly_name;
}
In this case I'm simply printing out the Friendly Name of each Queue.
Locating the CallSid
Once you have the Queue SID you next need to get the CallSid of the call you want to redirect. There are different ways to do this.
You could use the Members resource to list all of the calls waiting in that Queue:
foreach ($client->account->queues->get('QU5ef8732a3c49700934481addd5ce1659')->members as $member) {
echo $member->CallSid;
}
Each member resource gives you some information about that member, including the CallSid.
If you didn't know the specific calls CallSid and wanted to locate the call based on something like the callers phone number, you can use the Calls resource:
$call = $client->account->calls->getIterator(0, 50, array(
"Status" => "in-progress",
"From" => "+15555555555"));
$callsid = $call->CallSid;
Here I am asking Twilio to return me a Call resource whose From phone number is +15555555555" and whose status is "in-progress", and then grabbing that Calls CallSid.
Redirecting the Queued Caller
Now that I have both the Queue SID and the CallSid I can redirect the caller out of the Queue and to another experience:
$member = $client->account->queues->get('QU5ef8732a3c49700934481addd5ce1659')->members->get("CA5ef8732a3c49700934481addd5ce1659");
$member->update(array(
"Url" => "http://demo.twilio.com/docs/voice.xml",
"Method" => "POST"
));
Hope that helps.