*** id: 7963fdcb-8f40-4065-8a85-b3037e1f4b45 title: Gather sidebar-title: Gather slug: /cxml/reference/voice/gather position: 1 max-toc-depth: 3 ---------------- The `` verb transcribes speech or collects digits during a call. ## Verb attributes The `action` attribute takes in an absolute URL. SignalWire will make a `GET` or `POST` request to this URL when entering of digits is completed. If there is no URL provided, SignalWire will re-request the URL that was previously used, which can cause an unwanted looping behavior. Be sure to provide the proper URL in order to avoid this outcome. See [below](#gather_action) for specified request parameters. Send a webhook to the `action` URL even if there is no input. By default, if no input is detected, the next XML instruction is executed but by setting `actionOnEmptyResult` to `true`, a callback to the `action` URL will be sent to continue call flow. This attribute enables enhanced speech recognition, which will incur an added cost. When it is `false`, `speechModel` has no effect. The set of digits, (0-9, \*, #), that can end a recording. A list of words and phrases, each a max of 100 characters, a caller is likely to say during a call. The type of input received from a caller (i.e. speech or DTMF). Values can be `dtmf`, `speech`, or `dtmf speech`. The language in which you expect your callers to speak. The `method` attribute specifies whether the request to action is a `GET` or a `POST`. Valid values are `GET` or `POST`. The number of digits you expect to be pressed by a caller. The URL to request to during speech recognition. No URL is specified by default. The type of HTTP request to use when requesting a `partialResultCallback`. Tells SignalWire whether or not to filter profane language when transcribing a call. The model of enhanced speech recognition you would like to use. This attribute only has an effect if `enhanced` is `true`. Valid values are `phone_call`, `video`, or `default`. `phone_call` optimizes speech recognition for phone calls at a 8khz sample rate. `video` optimizes speech recognition for video calls at a 16khz sample rate. `default` will automatically choose the current best option between `phone_call` and `video`. The set time, in seconds, that SignalWire will wait before ending speech recognition. If set to `auto`, SignalWire will automatically end speech recognition when there is a pause in speech. The number of seconds of silence or inaction that denote the end of caller input. #### Supported languages You can find a list of our supported languages [here](/docs/platform/voice/tts). #### Request parameters for `action` URL \[#gather\_action] The `action` request contains the [Standard Request Parameters](/docs/compatibility-api/cxml/reference/voice#request-parameters) as well as: The score, between 0.0 and 1.0, that determines the accuracy of a transcription. The buttons pressed by a caller. The transcribed result of the caller's speech. ## Nesting The following verbs can be nested within a ``: * ``: plays an audio file, that SignalWire fetches from the URL you configured, back to the caller. * ``: waits silently for a distinctive number of seconds. * ``: reads supplied text back to the caller. ## Examples ### Handle gathered input on your server This example demonstrates a complete flow: the initial cXML prompts the caller for input, and your server handles the POST request to process `Digits` or `SpeechResult` and respond with appropriate cXML. This cXML is served to SignalWire (e.g., as your webhook response). It prompts the caller for input and specifies your server's `action` URL to handle the result. ```xml Press 1 or say sales for sales. Press 2 or say support for technical support. Press 3 or say billing for billing questions. We did not receive any input. Goodbye! ``` When the caller provides input, SignalWire POSTs to your `action` URL with `Digits` (for DTMF) and/or `SpeechResult` and `Confidence` (for speech). Your server processes the input and returns cXML to continue the call. ```javascript title="Node.js" const express = require("express"); const app = express(); app.use(express.urlencoded({ extended: true })); app.post("/handle-gather", (req, res) => { // Extract gathered input from POST body const digits = req.body.Digits || ""; const speechResult = (req.body.SpeechResult || "").toLowerCase(); const confidence = parseFloat(req.body.Confidence) || 0; // Also available: CallSid, From, To, and other standard parameters const callSid = req.body.CallSid; let responseXml = ''; // Determine selection from DTMF or speech if (digits === "1" || speechResult.includes("sales")) { responseXml += "Connecting you to sales. Please hold."; responseXml += "+15551234567"; } else if (digits === "2" || speechResult.includes("support")) { responseXml += "Connecting you to technical support."; responseXml += "+15559876543"; } else if (digits === "3" || speechResult.includes("billing")) { responseXml += "Connecting you to billing."; responseXml += "+15555555555"; } else { // Invalid or no input - prompt again responseXml += ''; responseXml += "Sorry, I didn't understand. Press 1 for sales, 2 for support, or 3 for billing."; responseXml += ""; responseXml += "We did not receive valid input. Goodbye!"; } responseXml += ""; res.type("text/xml"); res.send(responseXml); }); app.listen(3000, () => console.log("Server running on port 3000")); ``` ### A simple gather ```xml ``` ```javascript title="Node.js" const { RestClient } = require("@signalwire/compatibility-api"); const response = new RestClient.LaML.VoiceResponse(); response.gather(); console.log(response.toString()); ``` ```csharp using Twilio.TwiML; using System; class Example { static void Main() { var response = new VoiceResponse(); response.Gather(); Console.WriteLine(response.ToString());; } } ``` ```python from signalwire.voice_response import VoiceResponse, Gather response = VoiceResponse() response.gather() print(response) ``` ```ruby require 'signalwire/sdk' response = Signalwire::Sdk::VoiceResponse.new do |response| response.gather end puts response.to_s ``` SignalWire will collect any speech or digits pressed during a call. ### Nesting `` within a gather ```xml Please enter your account number, followed by the pound sign. We did not receive any input. Goodbye! ``` ```javascript title="Node.js" const { RestClient } = require("@signalwire/compatibility-api"); const response = new RestClient.LaML.VoiceResponse(); const gather = response.gather({ action: "https://example.com/process_gather.php", method: "GET", }); gather.say("Please enter your account number, followed by the pound sign."); response.say("We did not receive any input. Goodbye!"); console.log(response.toString()); ``` ```csharp using Twilio.TwiML; using Twilio.Http; using Twilio.TwiML.Voice; using System; class Example { static void Main() { var response = new VoiceResponse(); var gather = new Gather(action: new Uri("https://example.com/process_gather.php"), method: HttpMethod.Get); gather.Say("Please enter your account number, followed by the pound sign."); response.Append(gather); response.Say("We did not receive any input. Goodbye!"); Console.WriteLine(response.ToString());; } } ``` ```python from signalwire.voice_response import VoiceResponse, Gather, Say response = VoiceResponse() gather = Gather(action='https://example.com/process_gather.php', method='GET') gather.say('Please enter your account number, followed by the pound sign.') response.append(gather) response.say('We did not receive any input. Goodbye!') print(response) ``` ```ruby require 'signalwire/sdk' response = Signalwire::Sdk::VoiceResponse.new do |response| response.gather(action: 'https://example.com/process_gather.php', method: 'GET') do |gather| gather.say(message: 'Please enter your account number, followed by the pound sign.') end response.say(message: 'We did not receive any input. Goodbye!') end puts response.to_s ``` You can use the `` verb to prompt callers to enter the desired input. In this example, when a caller enters their account number, SignalWire will submit the result to the URL provided in the `action` attribute. If the caller does not enter any digits, SignalWire will prompt the 'Goodbye' statement. ### Nesting `` within a gather ```xml https://your-application.com/audio.mp3 We did not receive any input. Goodbye! ``` ```javascript title="Node.js" const { RestClient } = require("@signalwire/compatibility-api"); const response = new RestClient.LaML.VoiceResponse(); const gather = response.gather({ action: "https://example.com/process_gather.php", method: "GET", }); gather.play("https://your-application.com/audio.mp3"); response.say("We did not receive any input. Goodbye!"); console.log(response.toString()); ``` ```csharp using Twilio.TwiML; using Twilio.Http; using Twilio.TwiML.Voice; using System; class Example { static void Main() { var response = new VoiceResponse(); var gather = new Gather(action: new Uri("https://example.com/process_gather.php"), method: HttpMethod.Get); gather.Play("https://your-application.com/audio.mp3"); response.Append(gather); response.Say("We did not receive any input. Goodbye!"); Console.WriteLine(response.ToString());; } } ``` ```python from signalwire.voice_response import VoiceResponse, Gather, Say response = VoiceResponse() gather = Gather(action='https://example.com/process_gather.php', method='GET') gather.play('https://your-application.com/audio.mp3') response.append(gather) response.say('We did not receive any input. Goodbye!') print(response) ``` ```ruby require 'signalwire/sdk' response = Signalwire::Sdk::VoiceResponse.new do |response| response.gather(action: 'https://example.com/process_gather.php', method: 'GET') do |gather| gather.play(message: 'https://your-application.com/audio.mp3') end response.say(message: 'We did not receive any input. Goodbye!') end puts response.to_s ``` You can use the `` verb to prompt callers to enter the desired input. In this example, when a caller enters their account number, SignalWire will submit the result to the URL provided in the `action` attribute. If the caller does not enter any digits, SignalWire will prompt the 'Goodbye' statement. ### Gather DTMF or speech ```xml Please press 3 or say account for account information. ``` ```javascript title="Node.js" const { RestClient } = require("@signalwire/compatibility-api"); const response = new RestClient.LaML.VoiceResponse(); const gather = response.gather({ input: "speech dtmf", timeout: 5, numDigits: 1 }); gather.say("Please press 3 or say account for account information."); console.log(response.toString()); ``` ```csharp using Twilio.TwiML; using Twilio.TwiML.Voice; using System; class Example { static void Main() { var response = new VoiceResponse(); var gather = new Gather(input: "speech dtmf", timeout: 5, numDigits: 1); gather.Say("Please press 3 or say account for account information."); response.Append(gather); Console.WriteLine(response.ToString());; } } ``` ```python from signalwire.voice_response import VoiceResponse, Gather, Say response = VoiceResponse() gather = Gather(input='speech dtmf', timeout=5, num_digits=1) gather.say('Please press 3 or say account for account information.') response.append(gather) print(response) ``` ```ruby require 'signalwire/sdk' response = Signalwire::Sdk::VoiceResponse.new do |response| response.gather(input: 'speech dtmf', timeout: 5, num_digits: 1) do |gather| gather.say(message: 'Please press 3 or say account for account information.') end end puts response.to_s ``` A caller can access their account information either through speech recognition or DTMF tones. SignalWire will wait 5 seconds before processing the information and sending the data. ## Potential issues #### `` doesn't receive caller input when the caller is using a VoIP phone. **Solution**: Some VoIP phones have trouble sending DTMF tones. Phones typically use compressed bandwidth-conserving audio protocols that can interfere with the transmission of the digit's signal. #### The `Digits` parameter is not sent to the `` URL. **Solution**: Verify that your application is not responding to the `action` URL with an HTTP 3xx redirect. SignalWire will follow this redirect but will not resend the **Digits** parameter.