# Voice Command Reference

> Required fields, options, and example payloads for all 19 voice WebSocket commands.

Send these commands using the [voice call command frame](/guides/voice-calls#command-frame) or [SDK voice helpers](/methods/voice-websockets#command-frames).

Expand a command to see its required and optional fields and a sample payload.

## Call control

Answer, end, transfer, and annotate the active call.

### call.answer

Answer an inbound call or confirm an outbound call is ready for interaction.

**Optional fields:**

- `as`

```json
{
  "as": "Support"
}
```

### call.end

End an active call or reject a pre-answer call.

**Optional fields:**

- `cause` — `user_busy`, `call_rejected`

```json
{
  "cause": "call_rejected"
}
```

### call.transfer

Dial and bridge a new number, or bridge to another Pinnacle call.

**Dial a new number**

**Required fields:**

- `to`

**Optional fields:**

- `from`
- `as`
- `custom_headers`

```json
{
  "to": "+14155551234",
  "from": "+14155559876",
  "as": "Support",
  "custom_headers": {
    "X-Customer-ID": "cus_123"
  }
}
```

**Bridge an existing call**

**Required fields:**

- `call_id` — Must be a Pinnacle call ID, not a provider call-control ID.

**Optional fields:**

- `as`

```json
{
  "call_id": "call_123",
  "as": "Support"
}
```

### call.update_state

Attach metadata that appears on future call events.

**Required fields:**

- `metadata`

```json
{
  "metadata": {
    "ticket_id": "tkt_123"
  }
}
```

## Audio

Play audio, stop playback, and tune the live audio stream.

### audio.play

Play TTS or a public audio URL into the call.

**Text-to-speech**

**Required fields:**

- `text`

**Optional fields:**

- `voice` — `female`, `alice`
- `language` — `en-US`

```json
{
  "text": "Thanks for calling.",
  "voice": "female",
  "language": "en-US"
}
```

**URL playback**

Replace the placeholder URL below with your publicly accessible audio file.

**Required fields:**

- `url` — Must be a public http or https URL without embedded credentials or private-network hosts.

**Optional fields:**

- `loop`
- `overlay`

```json
{
  "url": "https://example.com/hold.wav",
  "loop": 1,
  "overlay": true
}
```

### audio.stop

Stop active URL playback or TTS.

This command takes no parameters.

### audio.clear

Stop audio your app has streamed over the WebSocket and drop what's still queued. Use it for barge-in: audio you send is buffered, so stopping sending doesn't stop the caller hearing it.

This command takes no parameters.

### audio.reduce_noise

Enable or disable noise reduction for inbound, outbound, or both tracks.

**Required fields:**

- `enabled`

**Optional fields:**

- `engine` — `default`, `krisp`, `aicoustics`
- `direction` — `inbound`, `outbound`, `both`

```json
{
  "enabled": true,
  "engine": "krisp",
  "direction": "both"
}
```

## Input

Collect keypad digits, spoken answers, and send DTMF tones.

### input.get

Gather digits, speech, or structured AI extraction after an optional prompt.

**Optional fields:**

- `prompt`
- `minDigits`
- `maxDigits`
- `validDigits` — `12345`
- `terminatingDigit` — `#`
- `timeoutMs`
- `interDigitTimeoutMs`
- `ai`

```json
{
  "prompt": {
    "text": "Enter your PIN.",
    "voice": "female",
    "language": "en-US"
  },
  "minDigits": 4,
  "maxDigits": 4,
  "validDigits": "0123456789",
  "terminatingDigit": "#",
  "timeoutMs": 10000,
  "interDigitTimeoutMs": 3000,
  "ai": {
    "extract": {
      "type": "object",
      "properties": {
        "pin": {
          "type": "string"
        }
      },
      "required": [
        "pin"
      ]
    },
    "instructions": "Extract the caller's PIN."
  }
}
```

### input.cancel

Cancel the active input gathering request.

This command takes no parameters.

### dtmf.send

Send keypad tones to the far end of the call.

**Required fields:**

- `digits` — `0-9`, `*`, `#`, `A-D`

**Optional fields:**

- `duration_ms`

```json
{
  "digits": "1234#",
  "duration_ms": 250
}
```

## Recording

Control Pinnacle-managed recording during the call.

### recording.start

Start recording future audio frames.

This command takes no parameters.

### recording.stop

Stop future capture and flush the current recording segment.

This command takes no parameters.

## Conferences

Add people to a conference with this call in it, and change or remove them. See the Conference Calls guide.

### conference.add_participant

Dial someone (or pull in another of your calls). Without conference_id, uses this call's conference, creating one with this call in it. from defaults to your number on this call.

**Dial someone**

**Required fields:**

- `to`

**Optional fields:**

- `from`
- `label`
- `muted`
- `on_hold`
- `whisper_to`
- `announce`
- `ring_timeout_secs`
- `end_conference_on_leave`
- `record`
- `metadata`
- `conference_id`

```json
{
  "to": "+14155551234",
  "label": "supervisor",
  "muted": true,
  "announce": {
    "text": "You're joining a billing call. You're muted."
  }
}
```

**Pull in an existing call**

**Required fields:**

- `call_id`

**Optional fields:**

- `label`
- `muted`
- `on_hold`
- `whisper_to`
- `end_conference_on_leave`
- `conference_id`

```json
{
  "call_id": "call_7cQe4F8xT1yB2mN9pK3L",
  "label": "caller"
}
```

### conference.update_participant

Mute, hold, whisper, or relabel a participant. participant is a call ID, a label, or self (this call).

**Required fields:**

- `participant`

**Optional fields:**

- `muted`
- `on_hold`
- `whisper_to`
- `label`

```json
{
  "participant": "supervisor",
  "muted": false,
  "whisper_to": [
    "specialist"
  ]
}
```

### conference.remove_participant

Hang up a participant's call; everyone else stays.

**Required fields:**

- `participant`

```json
{
  "participant": "specialist"
}
```

### conference.leave

This call leaves the conference (hangs up).

This command takes no parameters.

### conference.get

Get this call's conference and its participants in the ack.

This command takes no parameters.

### conference.end

End this call's conference and hang up everyone.

This command takes no parameters.
