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

# Realtime avatar API

> Run Realistic Avatars from any language over one WebSocket: no SDK needed.

The SDK's `LiveAvatar` is a thin client for this API. Use the API directly when your server isn't Node.js (Python, Go, Java, Ruby, .NET, Rust…), or when you want full control. Everything the SDK can do, the API can do: start a session, stream your agent's voice, interrupt, get speech events, and show the avatar in browsers or in your LiveKit room.

> **[Messages](https://docs.talking-avatar.dev/api-reference/realtime/messages.md)**
>
> Every message you send and receive, with its fields.

> **[Python example](https://docs.talking-avatar.dev/api-reference/realtime/python.md)**
>
> A complete client, with FastAPI and LiveKit.

> **[Browser playback](https://docs.talking-avatar.dev/api-reference/realtime/browser-playback.md)**
>
> Show the avatar in your page over WebRTC.

> **[Node.js SDK](https://docs.talking-avatar.dev/realistic-avatars/quickstart.md)**
>
> On Node.js, the SDK does all of this for you.

## Endpoint

```text theme={null}
wss://api.talking-avatar.dev
```

One WebSocket connection is one avatar session. Authenticate with your [API key](https://docs.talking-avatar.dev/dashboard/api-keys.md) in the first message. Keep the key, and the connection, on your server.

## A session, step by step

```mermaid theme={null}
sequenceDiagram
  participant S as Your server
  participant A as wss://api.talking-avatar.dev
  participant B as Browser (or your LiveKit room)
  S->>A: connect
  S->>A: {"type":"start","apiKey":"tav_…","avatar":"ava4","output":"direct"}
  A-->>S: {"type":"ready","width":832,"height":468,"audio":true}
  Note over S,A: Billing starts
  S->>A: view (relayed for each browser)
  A-->>S: view_offer
  S->>A: view_answer
  A-->>S: view_ready
  A-->>B: video + voice over WebRTC
  loop As your agent speaks
    S->>A: binary audio (PCM16)
    A-->>S: speech_started / speech_ended
  end
  S->>A: {"type":"clear"} (the user interrupts)
  A-->>S: {"type":"cleared","playedMs":1840}
  S->>A: close (1000)
  Note over S,A: Billing stops
```

1. **Connect** and send a [`start`](https://docs.talking-avatar.dev/api-reference/realtime/messages#start) message within 10 seconds. It names your API key, the avatar, your audio's sample rate, and where the avatar goes: **direct** to browsers over WebRTC, or into **your LiveKit room**.
2. **Wait for [`ready`](https://docs.talking-avatar.dev/api-reference/realtime/messages#ready).** The avatar is live, and billing starts.
3. **Show it.** Direct output: relay a `view` handshake for each browser ([Browser playback](https://docs.talking-avatar.dev/api-reference/realtime/browser-playback.md)). LiveKit: the avatar joins your room by itself.
4. **Stream your agent's voice** as [binary audio messages](https://docs.talking-avatar.dev/api-reference/realtime/messages.md#audio) of raw PCM16 mono. The avatar speaks it, with the voice and lips in sync.
5. **Interrupt** with [`clear`](https://docs.talking-avatar.dev/api-reference/realtime/messages#clear) when the user talks over the avatar.
6. **Close the WebSocket** when the conversation ends. Billing stops.

## The smallest session

Any WebSocket client works. In Python:

```python theme={null}
import asyncio, json, os, struct
import websockets  # pip install websockets

async def main():
    async with websockets.connect("wss://api.talking-avatar.dev", max_size=2**20) as ws:
        await ws.send(json.dumps({
            "type": "start",
            "apiKey": os.environ["TALKING_AVATAR_API_KEY"],
            "avatar": "ava4",
            "output": "direct",
            "sampleRate": 24000,
        }))
        print(json.loads(await ws.recv()))  # {"type": "ready", "width": 832, "height": 468, ...}

        pcm = open("hello.pcm", "rb").read()  # PCM16 mono, 24 kHz
        await ws.send(struct.pack("<dI", 0, 24000) + pcm)  # header: play time 0 (queue it), sample rate
        # … show it in a browser, see Browser playback …
    # Leaving the block closes the connection: billing stops

asyncio.run(main())
```

## Billing

\$0.02 per minute, billed per second from `ready` until the connection closes, from your prepaid balance. It's the same session, with the same price and limits, as one started with the SDK, and it appears on the [Usage](https://docs.talking-avatar.dev/dashboard/usage.md) page under your API key's name.

## Limits

| | |
| - | - |
| Session length | Up to 3 hours. The connection then closes with `4003`. |
| Sessions at once | As many as you need |
| Message size | Up to 1 MB. Send long audio in pieces (256 KB is a good size). |
| First message | The `start` message, within 10 seconds of connecting |
| Viewers per session (direct) | Any number |
| Video | 832 × 468, 25 fps, H.264. Direct output adds the voice as Opus. |

## Close codes

The connection's close code says why a session ended. Before closing for an error, the server usually sends an [`error`](https://docs.talking-avatar.dev/api-reference/realtime/messages#error) message with the details.

| Code | Meaning | What to do |
| - | - | - |
| `1000` | You closed the session. Also used after an `error` before `ready`, for example an unknown avatar or an unsupported sample rate. | Read the `error` message |
| `1009` | A message was larger than 1 MB | Send audio in smaller pieces |
| `1011` | The avatar's stream was lost and couldn't recover | Start a new session |
| `4001` | Missing or invalid API key, or the first message wasn't a `start` message | Check the key and the `start` message |
| `4002` | Out of credits (below a minute's worth at the start, or used up during the session), or the monthly spending limit is reached. Running sessions are checked every 30 seconds. | Add credits, turn on auto top-up, or raise the limit on [Billing](https://docs.talking-avatar.dev/dashboard/billing.md) |
| `4003` | The session reached its 3-hour limit | Start a new session |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.