> 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.

# WebSocket Transport

> Stream audio directly via WebSockets for real-time, bidirectional communication

Vapi's WebSocket transport enables real-time, bidirectional audio communication directly between your application and Vapi's AI assistants. Unlike traditional phone or web calls, this transport method lets you stream raw audio data instantly with minimal latency.

## Key Benefits

* **Low Latency**: Direct streaming ensures minimal delays.
* **Bidirectional Streaming**: Real-time audio flow in both directions.
* **Easy Integration**: Compatible with any environment supporting WebSockets.
* **Flexible Audio Formats**: Customize audio parameters such as sample rate.
* **Automatic Sample Rate Conversion**: Seamlessly handles various audio rates.

## Creating a WebSocket Call

To initiate a call using WebSocket transport:

### PCM Format (16-bit, default)

```bash
curl 'https://api.vapi.ai/call' \
  -H 'authorization: Bearer YOUR_API_KEY' \
  -H 'content-type: application/json' \
  --data-raw '{
    "assistantId": "YOUR_ASSISTANT_ID",
    "transport": {
      "provider": "vapi.websocket",
      "audioFormat": {
        "format": "pcm_s16le",
        "container": "raw",
        "sampleRate": 16000
      }
    }
  }'
```

### Mu-Law Format

```bash
curl 'https://api.vapi.ai/call' \
  -H 'authorization: Bearer YOUR_API_KEY' \
  -H 'content-type: application/json' \
  --data-raw '{
    "assistantId": "YOUR_ASSISTANT_ID",
    "transport": {
      "provider": "vapi.websocket",
      "audioFormat": {
        "format": "mulaw",
        "container": "raw",
        "sampleRate": 8000
      }
    }
  }'
```

### Sample API Response

```json
{
  "id": "7420f27a-30fd-4f49-a995-5549ae7cc00d",
  "assistantId": "5b0a4a08-133c-4146-9315-0984f8c6be80",
  "type": "vapi.websocketCall",
  "createdAt": "2024-09-10T11:14:12.339Z",
  "updatedAt": "2024-09-10T11:14:12.339Z",
  "orgId": "eb166faa-7145-46ef-8044-589b47ae3b56",
  "cost": 0,
  "status": "queued",
  "transport": {
    "provider": "vapi.websocket",
    "websocketCallUrl": "wss://api.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/transport"
  }
}
```

## Audio Format Configuration

When creating a WebSocket call, the audio format can be customized:

| Parameter    | Description            | Default                            |
| ------------ | ---------------------- | ---------------------------------- |
| `format`     | Audio encoding format  | `pcm_s16le` (16-bit PCM)           |
| `container`  | Audio container format | `raw` (Raw audio)                  |
| `sampleRate` | Sample rate in Hz      | `16000` for PCM, `8000` for Mu-Law |

### Supported Audio Formats

Vapi supports the following audio formats:

* **`pcm_s16le`**: 16-bit PCM, signed little-endian (default)
* **`mulaw`**: Mu-Law encoded audio (ITU-T G.711 standard)

Both formats use the `raw` container format for direct audio streaming.

### Format Selection Guidelines

* **PCM (`pcm_s16le`)**: Higher quality audio, larger bandwidth usage. Ideal for high-quality applications.
* **Mu-Law (`mulaw`)**: Lower bandwidth, telephony-standard encoding. Ideal for telephony integrations and bandwidth-constrained environments.

Vapi automatically converts sample rates as needed. You can stream audio at 8kHz, 44.1kHz, etc., and Vapi will handle conversions seamlessly. The system also handles format conversions internally when needed.

## Connecting to the WebSocket

Use the WebSocket URL from the response to establish a connection:

```javascript
const socket = new WebSocket("wss://api.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/transport");

socket.onopen = () => console.log("WebSocket connection opened.");
socket.onclose = () => console.log("WebSocket connection closed.");
socket.onerror = (error) => console.error("WebSocket error:", error);
```

## Sending and Receiving Data

The WebSocket supports two types of messages:

* **Binary audio data** (format depends on your configuration: PCM or Mu-Law)
* **Text-based JSON control messages**

### Audio Data Format

The binary audio data format depends on your `audioFormat` configuration:

* **PCM (`pcm_s16le`)**: 16-bit signed little-endian samples
* **Mu-Law (`mulaw`)**: 8-bit Mu-Law encoded samples (ITU-T G.711)

### Sending Audio Data

```javascript
function sendAudioChunk(audioBuffer) {
  if (socket.readyState === WebSocket.OPEN) {
    socket.send(audioBuffer);
  }
}

navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
  const audioContext = new AudioContext();
  const source = audioContext.createMediaStreamSource(stream);
  const processor = audioContext.createScriptProcessor(1024, 1, 1);

  processor.onaudioprocess = (event) => {
    const pcmData = event.inputBuffer.getChannelData(0);
    const int16Data = new Int16Array(pcmData.length);

    for (let i = 0; i < pcmData.length; i++) {
      int16Data[i] = Math.max(-32768, Math.min(32767, pcmData[i] * 32768));
    }

    sendAudioChunk(int16Data.buffer);
  };

  source.connect(processor);
  processor.connect(audioContext.destination);
});
```

### Receiving Data

```javascript
socket.onmessage = (event) => {
  if (event.data instanceof Blob) {
    event.data.arrayBuffer().then(buffer => {
      const audioData = new Int16Array(buffer);
      playAudio(audioData);
    });
  } else {
    try {
      const message = JSON.parse(event.data);
      handleControlMessage(message);
    } catch (error) {
      console.error("Failed to parse message:", error);
    }
  }
};
```

### Sending Control Messages

```javascript
function sendControlMessage(messageObj) {
  if (socket.readyState === WebSocket.OPEN) {
    socket.send(JSON.stringify(messageObj));
  }
}

// Example: hangup call
function hangupCall() {
  sendControlMessage({ type: "hangup" });
}
```

## Ending the Call

The recommended way to end a call is using [Live Call Control](/calls/call-features#end-call) which provides more control and proper cleanup.

Alternatively, you can end the WebSocket call directly:

```javascript
sendControlMessage({ type: "end-call" });
socket.close();
```

## Comparison: WebSocket Transport vs. Call Listen Feature

Vapi provides two WebSocket options:

| WebSocket Transport               | Call Listen Feature                |
| --------------------------------- | ---------------------------------- |
| Primary communication method      | Secondary, monitoring-only channel |
| Bidirectional audio streaming     | Unidirectional (listen-only)       |
| Replaces phone/web as transport   | Supplements existing calls         |
| Uses `provider: "vapi.websocket"` | Accessed via `monitor.listenUrl`   |

Refer to [Live Call Control](/calls/call-features) for more on the Call Listen feature.

When using WebSocket transport, phone-based parameters (`phoneNumber` or `phoneNumberId`) are not permitted. These methods are mutually exclusive.