> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cartesia.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# WebSocket API

> Stream audio and events between your application and an agent.

Use one bidirectional WebSocket to send user audio, receive agent audio, and handle conversation or client-tool events.

## Quick start

```javascript theme={null}
const agentId = "agent_Fo7pKNBUwLZxrTd6jvhpaE";
const accessToken = "<token from POST /access-token>";

const ws = new WebSocket(
  `wss://api.cartesia.ai/v1/agents/websocket/${agentId}` +
    `?cartesia_version=2026-08-14&access_token=${accessToken}`
);

let ready = false;

ws.onopen = () => {
  ws.send(JSON.stringify({
    type: "session_create",
    audio: {
      input_format: "pcm_44100",
      output_delivery: "speaking_pace",
    },
  }));
};

ws.onmessage = (message) => {
  const event = JSON.parse(message.data);

  if (event.type === "session_ready") ready = true;
  if (event.type === "audio_output") playAudio(atob(event.audio));
  if (event.type === "audio_output_clear") stopPlayback();
};

function sendAudio(base64Audio) {
  if (!ready) return;
  ws.send(JSON.stringify({ type: "audio_input", audio: base64Audio }));
}

// Connect these to your audio player.
function playAudio(pcmBytes) {}
function stopPlayback() {}
```

Create an access token with the [`/access-token` endpoint](/api-reference/auth/access-token#body-grants-agent). See [Authenticate client applications](/get-started/authenticate-your-client-applications) for token handling.

## Connect

```text theme={null}
wss://api.cartesia.ai/v1/agents/websocket/{agent_id}?cartesia_version=2026-08-14
```

Server applications can authenticate with the `X-API-Key` header. Browser and mobile applications should send an `access_token` query parameter. Never expose an API key in a client application.

The connection captures the agent's current version when it opens. A configuration change does not affect a call already in progress. The `session_ready` event reports the resolved `agent_version_id` and the call's `call_id`.

## Start the session

Send `session_create` as the first event, within 10 seconds of connecting:

```json theme={null}
{
  "type": "session_create",
  "audio": {
    "input_format": "pcm_44100",
    "output_delivery": "speaking_pace"
  }
}
```

Supported input formats are `mulaw_8000`, `pcm_16000`, `pcm_24000`, and `pcm_44100`. Agent audio uses the same format.

`output_delivery` defaults to `speaking_pace`. Use `as_available` when your application manages its own playback buffer. `as_available` cannot be used when the agent has background audio configured.

Wait for `session_ready` before sending audio:

```json theme={null}
{
  "type": "session_ready",
  "call_id": "ac_gqkgRWUz2u64qFUjA1mZyr",
  "agent_id": "agent_Fo7pKNBUwLZxrTd6jvhpaE",
  "agent_version_id": "av_7Hq2mXbK9cLdNfPzR3tWvE",
  "audio": {
    "input_format": "pcm_44100",
    "output_delivery": "speaking_pace"
  }
}
```

## Stream audio

Send user audio as base64-encoded `audio_input` events. Chunks of 20 to 100 milliseconds usually provide good latency.

```json theme={null}
{
  "type": "audio_input",
  "audio": "base64_encoded_audio_data"
}
```

The server returns `audio_output` events in the configured format:

```json theme={null}
{
  "type": "audio_output",
  "audio": "base64_encoded_audio_data"
}
```

When the user starts speaking, the server sends `audio_output_clear`. Discard buffered agent audio and stop playback immediately. The event can arrive while no agent audio is playing, in which case there is nothing to clear.

## Conversation events

Use `turn_started`, `turn_output_text_delta`, and `turn_ended` to show speaking state or build a transcript. Assistant text arrives incrementally in `turn_output_text_delta`; `turn_ended.text` contains the final text for either role.

These events are informational. Audio handling should not depend on them.

## Client tools

When the agent invokes a [client tool](/agents/client-tools), the server sends `client_tool_call`:

```json theme={null}
{
  "type": "client_tool_call",
  "tool_call_id": "call_2b7e4f9a1c0d",
  "tool_name": "lookup_cart",
  "parameters": { "cart_id": "cart_456" },
  "expects_response": true
}
```

If `expects_response` is `true`, answer with the same `tool_call_id`:

```json theme={null}
{
  "type": "client_tool_result",
  "tool_call_id": "call_2b7e4f9a1c0d",
  "result": "2 items in cart",
  "is_error": false
}
```

Late, duplicate, and mismatched results are ignored. Results may be up to 4 KiB.

## Errors and connection limits

The server sends an `error` event when it rejects an event. A recoverable error has `fatal: false`; a fatal error is followed by a connection close.

* A JSON message may be up to 32 KiB. Larger messages close with code `1009`.
* The server closes after 120 seconds without a valid client event. Streaming audio continuously, including silence, keeps the connection active. WebSocket ping frames do not reset this application-level timer.
* Close with code `1000` for a normal client shutdown. The server uses `1008` for protocol errors and `1011` for internal failures.

See the [WebSocket API reference](/api-reference/agents/agent-websocket) for every event and field.
