The following code is used to build up TwiML to ask the caller which department they are looking for.
If the user is already talking when the gather.Say is being read to the caller, then whatever they are saying over the message is being included, as well as their actual answer to the question in the Action url.
The documentation states:
The following example shows a that specifies speech input
from the user. When this TwiML executes, the caller will hear the
prompt. Twilio will then collect speech input for up to 60
seconds.
However the speech input collection is happening whilst the say is executing.
How do i make sure that whatever is being said whilst the Say is executing is not included as part of the actual response to the question?
...
var call = GetCallData();
var gather = new Gather(
timeout: 4,
input: new List<Gather.InputEnum> { Gather.InputEnum.Speech },
method: HttpMethod.Post,
language: call.TwilioLanguage,
bargeIn: false
)
{
Action = new Uri("MyUrl/Answer/Department")
};
gather.Say("Please say the name of the department you wish to be connected to",
language: call.TwilioLanguage,
voice: call.TwilioVoice);
response.Append(gather);
response.Redirect(new Uri("MyUrl/Hangup"), HttpMethod.Post);
return TwiML(response);
If you do not nest the Say in the Gather, the caller must listen to the Say before the Gather collects input.
More details are here.
TwiML Gather
"By nesting Say or Play in your Gather, you can read some text or play music for your caller while waiting for their input. See "Nest other verbs" below for examples and more information."
Related
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.
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'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'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.
We have currently developed a phone system for our call centre using Twilio (mainly c#, angular2 and typescript). Our company is currently in the UK but we have now started expanding out to the USA and because of laws in the US it looks like we'd need the ability to choose when we turn on the call recording. In the US people have to consent to recording the call before you can start recording them. I am trying to - when we make an outbound call via twilio to first play a message and get the user to input a key on their dialer to consent to recording the call before continuing with the call. I have attempted to use the gather and say verbs after we have dialled out but this doesn't seem to work. Code below:
`
public override void ApplyAction(TwilioResponse response)
{
var attributes = this.GetAttributes<DialAttributes>("attribute-");
attributes.callerId = this.PhoneNumber;
response.Dial(new Number(this.ReceiverPhoneNumber), attributes);
response.Gather(
new
{
timeout = 10,
finishOnKey = '*'
});
response.Say("We record all calls - please press the star key to consent to call recording");
}`
Twilio developer evangelist here.
The problem is that you are performing the <Dial> before the <Gather>
and <Say>. If you want the user to approve the call first you need to nest the <Say> in the <Gather> and provide an action URL for the <Gather>. When the user presses a button as part of the <Gather> Twilio will make an HTTP request to the action URL with the results in the Digits parameter. Then you should return the <Dial> as the response to that request, if the user signifies agreement. This way you ask them first and then connect the call.
Let me know if that helps.