I want to use twilio to test our internal phone system, and make sure calls are routing as they should, since our provider is notoriously bad of notifying us to problems.
I'm can initiate a call from twilio, use the "gather" verb to record speech (to ensure we hit the right queue) and then hang up. Everything works fine. Except that the gather ends up taking over 2 minutes to listen to the whole message from our phone system, charging us for 8 15 second gather chunks. I only need the first 15 seconds, but can't figure out how to hangup sooner. Is there a simple way to limit calls to a specific time?
timeLimit, and timeout both don't apply here, since timeLimit only works inside of a dial verb, and timeout only works for pauses in speech during the gather.
Perhaps just set a timer in your code for 15 seconds or so and then use the POST endpoint at /2010-04-01/Accounts/{AccountSid}/Calls/{CallSid} to cancel the call (using the Status=Completed parameter in order to cancel calls even if they are in progress).
If you use their Ruby SDK, and you make a normal call (not a conference call) then you can use the update method:
client = Twilio::REST::Client.new(account_sid, auth_token)
# fetch all in-progress calls between the two numbers
client.calls.list(from: '+11231231234',
to: '+12312311234',
status: 'in-progress').each do |c| #it's supposed to be just one record, but you can play it safe
c.update(status: 'completed')
end
Updating the status to completed should hangup the call if in-progress.
Updating the status to canceled should hangup the call if ringing/queued.
If you know for sure that the call is in-progress and you know the call sid, then you can use:
client = Twilio::REST::Client.new(account_sid, auth_token)
in_progress_call = client.calls(call_sid).fetch
in_progress_call.update(status: 'completed') if in_progress_call.present?
There is some general information in the official docs. Also snippets are available for the other SDKs.
You can find the source code of the update method here for more details.
Related
I am developing a simple application in C# which
Trigger a call using Twilio
receiver to press * after receiving the call and finish the call after pressing *
Provide the status completed if user pressed * otherwise provide different status.
I was able to make a call but not able to receive the user input Or status, I tried finishOnKey() but that didn't work, and it always provides status as completed. I didn't get much help from Twilio code sample, can someone redirect to correct article or provide the code to accomplish above.
Twilio developer evangelist here.
Once a call is answered successfully, it doesn't matter how the call is finished, the final status it reaches will be "completed". You can see more about Twilio call statuses in this documentation. You can see that the final call statuses could be:
completed: call was answered successfully and then finished
no-answer: Twilio dialled the number but there was no answer before the timeout
busy: Twilio dialled the number but received a busy signal
cancelled: The number was dialled, but the call was then cancelled using the API before answering
failed: the carrier couldn't connect the call
If you are using <Gather> to take the user input, you should ensure you have set the action attribute to a URL in your application. That URL will receive a new webhook request when the user presses a digit. For example:
<Response>
<Gather action="/gather_results" digits="1">
<Say>... your content goes here ...</Say>
</Gather>
</Response>
With the above TwiML a user would only have to press 1 key before the call is moved to the next stage and the webhook '/gather_results'.
The request to the /gather_results endpoint would include a body with a Digits parameter. If the user pressed "*" then the body of the request would include Digits=*, if the user pressed "1" then it would include Digits=1. You could then choose to do whatever you like with those results, including hanging up the call or recording the submitted digits.
Let me know if this helps at all.
I have two available Twilio <client> to receive inbound calls on my website (after caller enters a code) using JS Quickstart and Twilio client PHP library, these calls are recorded and registered on my database.
I've noticed when one <client> hangs up an open inbound call , this call goes to the website of the other <client> I have have 2 registers on my database instead of one.
This is an example:
<?php
//...
//Validating connection status
//$estd is the connection status I get via AJAX
if($estd=="open"){
$call = $twilio->calls($callsid)->update(array("status" => "completed"));
$calla = $twilio->calls($callsid)->fetch();
$parentCall = $calla->parentCallSid; //parent call
$calld = $twilio->calls($parentCall)->update(array("status" => "completed"));
} else if($estd=="pending"){
$call = $twilio->calls($callsid)->update(array("status" => "completed"));
$calla = $twilio->calls($callsid)->fetch();
$parentCall = $calla->parentCallSid; //parent call
$calld = $twilio->calls($parentCall)->update(array("twiml" => '<Response><Dial timeout="20" record="record-from-answer" recordingStatusCallback="https://mywebsite.com/record.php" recordingStatusCallbackEvent="in-progress completed absent"><Client><Identity>the_other_client</Identity><Parameter name="numdoc" value="user_code"/></Client></Dial></Response>'));
}
?>
How can I fix it?
I'd like your help.
I believe this could be occurring because a single incoming voice call will trigger both of your $estd if statements.
According to Twilio documentation (https://www.twilio.com/docs/voice/client/javascript/connection#status), an incoming call will first have the status pending, and then the status open. If your statuscallbackURL is set for when the status changes, you may be calling your record-keeping code more than once. Depending on how you have your SQL you may be inserting new records each time.
The way to prevent the double record is to save the resource SID for the call in your database and insert on duplicate key or update to prevent creating new records.
Alternatively, if the code snippet you are displaying is from record.php, when you make your outbound call using Twiml, you use a callbackURL to call record.php -- at which time you may be creating a new record in your database (as this call will have it's own unique SID). If you want to attach it to the current record, then you will need to create a different callbackURL for those outbound dials made from this script.
(But it is difficult from the details you have provided to know what code is being called when).
I've followed every single step in the Twilio's documentation called Dynamic Call Center with Laravel.
My problem is that a call gets through the IVR, then after choosing a digit, nothing happens.
My guess is that its not creating a task. the code provided in the documentation just generate a task with json but thats it. I check my tasks in Twilio taskrouter console and nothing shows up.
I've provided all credentials, used ngrok, filled in all url callbacks.
public function enqueueCall(Request $request)
{
define('workflowSid', env('TWILIO_WORKFLOW_SID'));
$selectedSkillInstruction = new \StdClass();
$selectedSkillInstruction->selected_skill = $this->_getSelectedSkill($request);
$response = new Twiml();
$enqueue = $response->enqueue(['workflowSid' => workflowSid]);
$enqueue->task(json_encode($selectedSkillInstruction));
return response($response)->header('Content-Type', 'text/xml');
}
I expect a code that actually creates a task, but when I call this api via postman, a task is not created
The above code returns Twilio Markup Language (TwiML) which uses the enqueue verb and a workflowSid attribute. The enqueue verb is used with Programmable Voice. Have you tried associating your application with a Twilio phone number and then calling the Twilio number which should enqueue the call into a task router workflow?
TwiML Voice: Enqueue
https://www.twilio.com/docs/voice/twiml/enqueue#attributes-workflowSid
I have solved my problem. It turned out that everything was in order, the only problem is that I didn't know I need to press # after choosing from the IVR because all the demo I saw from Twilio only press a number and it gets routed.
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 have some working code for call screening with NodeJS, which I modified from the official twilio example.
https://www.twilio.com/docs/howto/callscreening
https://github.com/coolaj86/bizilio/blob/master/routes/twilio/voice/index.js#L246
Snippit:
response += ""
+ '<Response><Gather action="/twilio/voice/connect' + search + '" finishOnKey="any digit" numDigits="1">'
+ '<Say>Press any key to accept this call</Say>'
+ '</Gather>'
// TODO instead of hanging up, redirect to voicemail?
// otherwise it's left to the fallback url to pickup the voicemail and that takes a while
+ '<Hangup/>'
+ '</Response>'
;
If the screening completes successfully, I get a callback to /twilio/voice/connect?foo=bar.
If the screening is unsuccessful I also want a callback to /twilio/voice/miss?foo=bar.
Is the most appropriate way to do this to do a <Redirect> instead of <Hangup/> and then do the <Hangup/> in the redirect? Or should I had a statusCallback somewhere in the original dial and reference the call id?
In thinking about the possibilities to write out the question here, I've probably already discovered a working solution (and I'll go try it), but I'd still like to hear a best practice approach.
As you suggest, you should replace the <Hangup> with a <Redirect>/twilio/voice/miss?foo=bar</Redirect>. After the timeout expires (by default 5 seconds, but configurable via the timeout attribute of the Gather verb), if no input has been received it will go to the next instruction.
From the Twilio Docs for <Gather>:
If no input is received before timeout, falls through to the next verb in the TwiML document.
In the URL that you redirect to you can record that no input was gathered and return any TwiML you like to continue processing the call or return an empty <Response></Response> (or Hangup) to end the call.
StatusCallback is only used at the completion of the call and cannot execute further TwiML instructions.