> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.vapi.ai/llms.txt.
> For full documentation content, see https://docs.vapi.ai/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.vapi.ai/_mcp/server.

# Live Call Control

Vapi offers two main features that provide enhanced control over live calls:

1. **Call Control**: This feature allows you to inject conversation elements dynamically during an ongoing call.
2. **Call Listen**: This feature enables real-time audio data streaming using WebSocket connections.

To use these features, you first need to obtain the URLs specific to the live call. These URLs can be retrieved by triggering a `/call` endpoint, which returns the `listenUrl` and `controlUrl` within the `monitor` object.

## Obtaining URLs for Call Control and Listen

To initiate a call and retrieve the `listenUrl` and `controlUrl`, send a POST request to the `/call` endpoint.

### Sample Request

```bash
curl 'https://api.vapi.ai/call' 
-H 'authorization: Bearer YOUR_API_KEY' 
-H 'content-type: application/json' 
--data-raw '{
  "assistantId": "5b0a4a08-133c-4146-9315-0984f8c6be80",
  "customer": {
    "number": "+12345678913"
  },
  "phoneNumberId": "42b4b25d-031e-4786-857f-63b346c9580f"
}'

```

### Sample Response

```json
{
  "id": "7420f27a-30fd-4f49-a995-5549ae7cc00d",
  "assistantId": "5b0a4a08-133c-4146-9315-0984f8c6be80",
  "phoneNumberId": "42b4b25d-031e-4786-857f-63b346c9580f",
  "type": "outboundPhoneCall",
  "createdAt": "2024-09-10T11:14:12.339Z",
  "updatedAt": "2024-09-10T11:14:12.339Z",
  "orgId": "eb166faa-7145-46ef-8044-589b47ae3b56",
  "cost": 0,
  "customer": {
    "number": "+12345678913"
  },
  "status": "queued",
  "phoneCallProvider": "twilio",
  "phoneCallProviderId": "CA4c6793d069ef42f4ccad69a0957451ec",
  "phoneCallTransport": "pstn",
  "monitor": {
    "listenUrl": "wss://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/transport",
    "controlUrl": "<https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control>"
  }
}

```

## Call Control Features

Once you have the `controlUrl`, you can use various control features during a live call. Here are all the available control options:

### 1. Say Message

Makes the assistant say a specific message during the call.

```bash
curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' 
-H 'content-type: application/json' 
--data-raw '{
  "type": "say",
  "content": "Welcome to Vapi, this message was injected during the call.",
  "endCallAfterSpoken": false
}'
```

### 2. Add Message to Conversation

Adds a message to the conversation history and optionally triggers a response.

```bash
curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' 
-H 'content-type: application/json' 
--data-raw '{
  "type": "add-message",
  "message": {
    "role": "system",
    "content": "New message added to conversation"
  },
  "triggerResponseEnabled": true
}'
```

### 3. Assistant Control

Control the assistant's behavior during the call.

```bash
curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' 
-H 'content-type: application/json' 
--data-raw '{
  "type": "control",
  "control": "mute-assistant"  // Options: "mute-assistant", "unmute-assistant", "say-first-message"
}'
```

### 4. End Call

Programmatically end the ongoing call.

```bash
curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' 
-H 'content-type: application/json' 
--data-raw '{
  "type": "end-call"
}'
```

### 5. Transfer Call

Transfer the call to a different destination.

```bash
curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' 
-H 'content-type: application/json' 
--data-raw '{
  "type": "transfer",
  "destination": {
    "type": "number",
    "number": "+1234567890"
  },
  "content": "Transferring your call now"
}'
```

You can also transfer to a SIP URI:

```bash
curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' 
-H 'content-type: application/json' 
--data-raw '{
  "type": "transfer",
  "destination": {
    "type": "sip",
    "sipUri": "sip:+transferPhoneNumber@sip.telnyx.com"
  },
  "content": "Testing transfer call."
}'
```

### 6. Handoff Call

Handoff the call to a different assistant.

```bash
curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' 
-H 'content-type: application/json' 
--data-raw '{
  "type": "handoff",
  "destination": {
    "type": "assistant",
    "contextEngineeringPlan": "none",
    "assistant": {
        "name": "new_assistant",
        "voice": {
            "provider": "vapi",
            "version": 2,
            "voiceId": "Elliot"
        },
    }                                    
  },
  "content": "Handing off your call now"
}'
```

## Call Listen Feature

The `listenUrl` allows you to connect to a WebSocket and stream the audio data in real-time. You can either process the audio directly or save the binary data to analyze or replay later.

### Example: Saving Audio Data from a Live Call

Here is a simple implementation for saving the audio buffer from a live call using Node.js:

```jsx
const WebSocket = require('ws');
const fs = require('fs');

let pcmBuffer = Buffer.alloc(0);

const ws = new WebSocket("wss://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/transport");

ws.on('open', () => console.log('WebSocket connection established'));

ws.on('message', (data, isBinary) => {
  if (isBinary) {
    pcmBuffer = Buffer.concat([pcmBuffer, data]);
    console.log(`Received PCM data, buffer size: ${pcmBuffer.length}`);
  } else {
    console.log('Received message:', JSON.parse(data.toString()));
  }
});

ws.on('close', () => {
  if (pcmBuffer.length > 0) {
    fs.writeFileSync('audio.pcm', pcmBuffer);
    console.log('Audio data saved to audio.pcm');
  }
});

ws.on('error', (error) => console.error('WebSocket error:', error));

```