My question: Can Twilio Announcements be used when there is only a single participant in the conference?
My Test Application: Is a simple node app that keeps a caller waiting while work is done in the background, with periodic updates on progress to the caller, before finally moving the call to a real person.
The problem: I saw Announcements and that this would excellent for my needs.
My node test app successfully dumps each incoming call into its own unique conference. I later attempt to announce an update on the background processing while the caller is waiting.
client.conferences(conferenceSid)
.update({announceUrl:'https://cccbae85.ngrok.io/twilio/announce'})
.then(result => console.log('success'))
.catch(error => console.log('conference error = ' + error));
The following results:
conference error = Error: The requested resource /2010-04-01/Accounts/ACX*/Conferences/CFb15222ac23964077e8161c819cd9dcca.json was not found
When I change this to use a conference AND participant:
client.conferences(conferenceSid)
.participants (particpantCallSid)
.update({announceUrl:'https://cccbae85.ngrok.io/twilio/announce'})
.then(result => console.log('success'))
.catch(error => console.log('conference error = ' + error));
The result is 'success', meaning the conferenceSid was accepted, but I never see any call to the announceUrl (no errors in Twilio, no attempts through ngok).
So back to my question, can Announcements be used in conferences that have a single participant, or do I need to go back to having a "bot" jump into the conference, say something, and jump back out.
OR - did I royally mess up my understanding of Announce....
Thanks!!
Related
What i'm trying to accomplish:
On an incoming call, I display a small box in the frontend that contains caller info along with a button to pickup the call, and a button to send to voicemail. When the agent clicks the button for voicemail, I want to simply forward the incoming call to voicemail.
The issue:
As long as the call is unanswered and still ringing, I cannot redirect it by updating the call the usual way, it has to be answered to allow updating. If I make the button either ignore or reject the call, I have no specific callback status to track, ignore has no status at all, reject just returns "completed" which is no help to me at all.
What I have tried:
// Called by Ajax on button click, variable $callSid contains the call SID
$client->calls($callSid)->update([
"method" => "POST",
"url" => "https://URL_TO_TWIML"
]);
// TWIML returned by URL_TO_TWIML
$response = new VoiceResponse();
$response->say('Agent is unable to take your call, please leave a message');
$response->record(['timeout' => 10]);
$response->hangup();
return $response;
I have tried to find a usable status on callback for ignore / reject as mentioned previously without success. I've searched far and wide for an answer to this without success.
Maybe i'm looking at it the wrong way, i'm still fairly new to Twilio. Any help would be appreciated.
I am currently receiving a call with the use of dequeue command.
_onReservationCreated: (reservation) =>
reservation.dequeue(
null
null
'record-from-answer'
5
'https://myurl/webhooks/twilio/completed'
'completed'
"client:#{reservation.workerName}"
(error, r) =>
if error
console.log(error)
else
console.log(r)
)
I want to send the user to voicemail after the timeout.
on my rails code, I have the webhook which is successfully called.
def completed
message = 'We are currently not able to answer your call, please leave a message'
twiml = Twilio::TwiML::VoiceResponse.new do |response|
response.say(message: message)
response.record
response.hangup
end
render xml: twiml.to_xml
end
The above is not working, the webhook is been triggered but nothing happens.
Twilio developer evangelist here.
You have the webhook URL set up as the dequeueStatusCallbackUrl. Status Callback Webhooks like this are asynchronous, so you can't affect the call by returning TwiML.
The parameters of the callback should include the taskCallSid, so you can use that to call the TaskRouter REST API to update the task, move it to a different workflow or get the CallSid and redirect the call to an endpoint that does then set up the voicemail.
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.
I'm trying to have the ability to update a call to dial it into a conference, and then I want to keep track of which phone numbers are in the conference. I'll already have the phone number before updating the call, so my plan was to add it as parameter to the statusCallback, then when someone joins, I'll know which phone number has joined (or left). Here is the Twiml I'm using to update the call into the conference.
let conferenceTwiml = function(conferenceName, phoneNumber) {
let voiceResponse = new VoiceResponse();
let options = {
startConferenceOnEnter: true,
endConferenceOnExit: false,
waitUrl: <myWaitUrl>,
statusCallbackEvent: "join leave",
statusCallback: <myStatusCallBackUrl> + '?phoneNumber=' + phoneNumber,
statusCallbackMethod:"POST",
};
voiceResponse.dial().conference(options, conferenceName);
return voiceResponse.toString();
}
The body sent to the statusCallback looks like this:
{
Coaching: 'false',
FriendlyName: 'Room 123',
SequenceNumber: '4',
ConferenceSid: 'CF1c7a162ba5d0587f390a0d7e7c6eb9a5',
EndConferenceOnExit: 'false',
CallSid: 'CA5244195567afec7327bb24d65a2d2b15',
StatusCallbackEvent: 'participant-join',
Timestamp: 'Wed, 17 Jul 2019 18:18:27 +0000',
StartConferenceOnEnter: 'true',
Hold: 'false',
AccountSid: <myAccountSid>,
Muted: 'false'
}
So you can see there's not really any identifying information, without the additional query parameter.
The problem I've run into is that, according to the docs:
The statusCallback URL is set by the first Participant to join the conference, subsequent statusCallbacks will be ignored.
So in essence I can't dynamically set the phoneNumber parameter for each person I'm dialing into the conference, since it will always reflect the phoneNumber of the first person who joined.
My question is, how can I get some kind of identifying information about who is joining or leaving the conference? Where are my twilio evangelists at? Thanks!
Heyooo Developer Evangelist here. 👋
There are two ways to approach this.
1. Persist the call information via CallSid yourself
When you receive the initial phone call and you put people into the conference, what you could do it to persist the call information (including the phone number) on your end and use the CallSid later to reference it when you receive the statusCallback hook. This way you would have all the information at hand using the available CallSid when the statusCallback hook comes in.
2. Fetch the call information when you receive the statusCallback
While the statusCallback hook doesn't include the call details what you can always do is to fetch the call information again by using the CallSid. This way you can take the information from StatusCallbackEvent and merge it with additional information after you received the call details.
Both approaches have pros and cons but are similar in the way that you have to get the call information from "somewhere".
The first approach needs you to find a way to persist call information. This brings additional overhead in your application.
The second approach saves you the need to persist call details but introduces an additional API request.
As always – it depends on your case. I hope that helps. :)
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.