# WebSocket

One WebSocket carries a Live session: your audio in, and the model’s speech, transcripts and turn events out.

> **Coming from the OpenAI Realtime API?** The Live API follows the Live convention, which is not Realtime-shaped: there is no `input_audio_buffer`, speech does not arrive inside a `response`, and the two transcripts are their own event streams. A Realtime client will not run a Live session unchanged. For transcription in the Realtime format, use the [Realtime API](https://dotwave.ai/docs/realtime/).

## Connect

- `WSS wss://api.dotwave.ai/v1/live/sessions`: No query parameters are needed.

- **From your server**: `Authorization: Bearer <API key>`
- **From a browser**: `?token=<client secret>`, with a secret from [`POST /v1/live/client_secrets`](https://dotwave.ai/docs/live/client-secrets/)

## Start the session

The first event you send must be `session.start`. The socket refuses anything else with the error “The first Live event must be session.start.” The server answers `session.started`, with the session’s id, model and audio configuration.

```json
{"type": "session.start",
 "session": {"model": "nemotron-voicechat",
             "audio": {"input": {"format": {"type": "audio/pcm", "rate": 24000}},
                       "output": {"format": {"type": "audio/pcm", "rate": 24000},
                                  "encoding": "base64",
                                  "voice": "aria"}}}}
```

A refused `session.start` sends an `error` event and closes the socket with 4400; nothing is created or billed.

## Audio

- **Format**: 24 kHz mono PCM16, both ways. Send it in chunks of 3,840 bytes.
- **In**: `session.input_audio.append` with base64 audio, or the same chunks as binary messages.
- **Out**: `session.output_audio.delta`, base64 by default. Set `audio.output.encoding` to `binary` to receive bare PCM16 as binary messages instead.
- **Pacing**: Send audio at the speed of speech. The server buffers at most 1.28 s ahead; audio sent faster ends the session with close code 1013.
- **Muting**: After `session.input_audio.mute`, keep streaming: the model hears silence until `session.input_audio.unmute`.

## Turns and transcripts

The model takes and gives the turn on its own, so there is no buffer to commit and no response to request. `session.turn.event` reports each change. The user’s speech arrives as `session.input_transcript.delta` and the model’s as `session.output_transcript.delta`. See [server events](https://dotwave.ai/docs/live/server-events/).

## Close codes

Send `session.close` to end the session. The server answers `session.closed`, with the reason, the final session and its usage, then closes the socket. A session also ends when it reaches its limit.

| Close code | Meaning | What to do |
| --- | --- | --- |
| 1000 | Closed normally: by you, or when the session reached its limit. | Nothing, or open a new session. |
| 1011 | A server error. | Open a new session. |
| 1012 | The server is restarting. | Open a new session. |
| 1013 | Audio arrived faster than real time. | Open a new session, and pace the audio. |
| 4400 | A protocol error, such as a first event other than `session.start`, or a refused `session.start`. | Fix the client. |
| 4401 | The credential is invalid, expired or already used. | Use your API key, or a new client secret. |
| 4413 | The service is not ready. | Retry shortly. |
| 4429 | No capacity when the session started. An `error` event with `capacity_exhausted` comes first. | Retry after a short wait. |

> After an interruption, open a new session and let the user know. Do not resend audio from the previous session.
