# Gather

The `<Gather>` verb collects DTMF digits, speech, or both from the caller, then sends the result to your `action` URL. Use it to build menus, PIN entry, and any prompt that branches on caller input.

## Attributes

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `action` | string (uri) | — | URL to send the gathered result to. When absent, execution continues with the next verb in the document once gathering ends. |
| `method` | string | `POST` | HTTP method used to request `action`. One of `GET` or `POST`. |
| `input` | string | `dtmf` | Type of input to accept. One of `dtmf`, `speech`, or `dtmf speech` (both, in any order). When both are enabled, PressOne listens for digits and speech at the same time, and the first input to complete wins: entered digits produce `Digits`, a finished transcription produces `SpeechResult`. |
| `timeout` | integer | `5` | Seconds to wait for input before gathering ends with no result. For speech input, `speechTimeout` overrides this as the end-of-speech silence window. |
| `numDigits` | integer | — | Maximum number of DTMF digits to collect. Gathering ends immediately once this many digits are entered, without waiting for `finishOnKey` or `timeout`. When omitted, PressOne collects up to 128 digits. |
| `finishOnKey` | string | `#` | DTMF key that ends input collection. A single character: any digit, `*`, or `#`. Set to an empty string to disable ending on any key. |
| `actionOnEmptyResult` | boolean | `false` | Whether to request `action` even when gathering ends with no result (no digits or speech recognized). When `false`, an empty result falls through to the next verb instead of requesting `action`. |
| `language` | string | `en-US` | Language used for speech recognition, as a BCP-47 tag such as `en-US`. Only applies when `input` includes `speech`. |
| `hints` | string | — | Comma-separated list of words or phrases likely to appear in the caller's speech, to improve recognition accuracy. Only applies when `input` includes `speech`. |
| `speechTimeout` | string | — | Silence duration, in seconds, after the caller stops speaking before speech recognition ends, bounded by `timeout`. Set to `auto` to end recognition as soon as the caller stops talking. A numeric value must be a positive integer. When `speechModel` is set, `speechTimeout` must be numeric: `auto` and the default are rejected. |
| `speechModel` | string | — | Speech recognition model to use. Requires `speechTimeout` to be a positive integer (see above). |
| `partialResultCallback` | string (uri) | — | URL to receive interim speech recognition results while the caller is still talking, before the final result is ready. Only applies when `input` includes `speech`. |
| `partialResultCallbackMethod` | string | `POST` | HTTP method used to request `partialResultCallback`. One of `GET` or `POST`. |
| `profanityFilter` | boolean | — | Whether to mask profanity in speech recognition results. Only applies when `input` includes `speech`. |

## Nesting

`<Gather>` may contain `<Say>`, `<Play>`, and `<Pause>` as prompts, played to the caller while PressOne waits for input. A DTMF digit pressed during a prompt interrupts it and skips any remaining prompts; the interrupting digit becomes the first digit of the result.

## Action parameters

`<Gather>` sends different parameters to `action` depending on what it collected:

| Name | Type | Description |
|------|------|-------------|
| `Digits` | string | DTMF digits collected. Sent when `input` includes `dtmf` and the caller entered at least one digit. |
| `SpeechResult` | string | Transcribed speech text. Sent when `input` includes `speech` and recognition produced a result. |
| `Confidence` | float | Confidence score for `SpeechResult`, from 0 to 1. Sent together with `SpeechResult`. |

### Streaming partial results

When `partialResultCallback` is set and `input` includes `speech`, PressOne posts each interim transcript to that URL as recognition progresses, in addition to the final result sent to `action`:

| Name | Type | Description |
|------|------|-------------|
| `AccountSid` | string | Your account SID. |
| `CallSid` | string | The unique identifier of the call. |
| `UnstableSpeechResult` | string | The interim, not-yet-final transcript recognized so far. |
| `Confidence` | float | Confidence score for `UnstableSpeechResult`, from 0 to 1. |

> **Note:** Interim results are not final. PressOne does not wait for a response from `partialResultCallback`, and `UnstableSpeechResult` may still change before the gather completes.

## Examples

A DTMF menu with two options:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Gather action="/handle-menu" numDigits="1" timeout="10">
    <Say>For sales, press 1. For support, press 2.</Say>
  </Gather>
  <Say>We did not receive your selection. Goodbye.</Say>
  <Hangup/>
</Response>
```

The `/handle-menu` action handler, complete and runnable:

<CodeTabs syncKey="lang">

```javascript title="Node.js"
const express = require("express");
const app = express();
app.use(express.urlencoded({ extended: false }));

app.post("/handle-menu", (req, res) => {
  const digits = req.body.Digits;
  let oneml;

  if (digits === "1") {
    oneml = `<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Say>You selected sales. An agent will call you back shortly.</Say>
  <Hangup/>
</Response>`;
  } else if (digits === "2") {
    oneml = `<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Say>You selected support. An agent will call you back shortly.</Say>
  <Hangup/>
</Response>`;
  } else {
    oneml = `<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Say>That is not a valid option. Goodbye.</Say>
  <Hangup/>
</Response>`;
  }

  res.type("text/xml").send(oneml);
});

app.listen(3000);
```

```python title="Python"
from flask import Flask, request, Response

app = Flask(__name__)

@app.route("/handle-menu", methods=["POST"])
def handle_menu():
    digits = request.form.get("Digits")

    if digits == "1":
        oneml = """<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Say>You selected sales. An agent will call you back shortly.</Say>
  <Hangup/>
</Response>"""
    elif digits == "2":
        oneml = """<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Say>You selected support. An agent will call you back shortly.</Say>
  <Hangup/>
</Response>"""
    else:
        oneml = """<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Say>That is not a valid option. Goodbye.</Say>
  <Hangup/>
</Response>"""

    return Response(oneml, mimetype="text/xml")

if __name__ == "__main__":
    app.run(port=3000)
```

</CodeTabs>

A speech gather with recognition hints:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Gather input="speech" action="/handle-destination" language="en-US" hints="Lagos, Abuja, Port Harcourt" speechTimeout="auto">
    <Say>Where would you like to fly to?</Say>
  </Gather>
</Response>
```

The `/handle-destination` handler reads `SpeechResult` and `Confidence` the same way the menu handler above reads `Digits`, from `req.body` (Express) or `request.form` (Flask).

Requesting `action` even when the caller enters nothing (`actionOnEmptyResult`):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Gather action="/handle-pin" actionOnEmptyResult="true" numDigits="4" timeout="5">
    <Say>Enter your four-digit PIN.</Say>
  </Gather>
</Response>
```

With `actionOnEmptyResult="true"`, PressOne requests `/handle-pin` even if the caller never enters a digit, so the server can react to silence (for example, by repeating the prompt) instead of PressOne falling through to the next verb. The `/handle-pin` handler follows the same pattern as the `/handle-menu` handler in the first example; when the caller enters nothing, `Digits` is absent from the request.

## See also

- [Say](/voice/oneml/say)
- [Play](/voice/oneml/play)
- [Record](/voice/oneml/record)
- [OneML overview](/voice/oneml/overview)
