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

# Realtime and WebSocket sessions

> Stream audio and text bidirectionally through the AI Gateway over WebSocket, with realtime models or with sequential Responses API turns.

The **AI Gateway** exposes two WebSocket endpoints: one for realtime speech and audio models, and one that runs Responses API turns over a single connection. Both authenticate with the workspace API key in the upgrade request; a rejected upgrade returns an HTTP error status.

## Realtime sessions

```
wss://my.orq.ai/v3/router/realtime?model=<provider>/<model>
```

Send `Authorization: Bearer $ORQ_API_KEY` in the upgrade request. `model` is required: a missing value returns `400`, an unknown model `404`, and a model without a realtime protocol `400`.

The endpoint routes xAI Grok Voice models: `xai/grok-voice-3.0` and `xai/grok-voice-latest`.

A session counts against the workspace's rate limits and budgets when it connects. An exhausted limit rejects the upgrade; see [Errors](#errors).

### OpenAI Realtime

The gateway proxies the OpenAI Realtime event protocol: JSON events in both directions and binary frames for audio. The Grok Voice constraints, audio formats, and billing are listed under [Realtime models](https://docs.orq.ai/ai-gateway/supported-models.md#realtime-models).

```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import WebSocket from "ws";

const socket = new WebSocket(
  "wss://my.orq.ai/v3/router/realtime?model=xai/grok-voice-3.0",
  "openai-beta.realtime-v1",
  { headers: { Authorization: `Bearer ${process.env.ORQ_API_KEY}` } },
);

socket.on("open", () => {
  socket.send(JSON.stringify({
    type: "session.update",
    session: { voice: "eve", instructions: "Answer in one sentence." },
  }));
});
```

```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import asyncio
import json
import os

import websockets

async def main() -> None:
    async with websockets.connect(
        "wss://my.orq.ai/v3/router/realtime?model=xai/grok-voice-3.0",
        subprotocols=["openai-beta.realtime-v1"],
        additional_headers={"Authorization": f"Bearer {os.environ['ORQ_API_KEY']}"},
    ) as socket:
        await socket.send(json.dumps({
            "type": "session.update",
            "session": {"voice": "eve", "instructions": "Answer in one sentence."},
        }))
        print(await socket.recv())


asyncio.run(main())
```

An upstream refusal arrives as an error event on the open socket rather than as an HTTP status, because the upgrade has already completed.

## Responses over WebSocket

```
wss://my.orq.ai/v3/router/responses
```

Upgrade with the `openai-beta.responses.v1` subprotocol and `Authorization: Bearer $ORQ_API_KEY`. Each client message creates or steers a response; the server streams the same events as an HTTP streaming request.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "type": "response.create",
  "stream_id": "turn-1",
  "response": {
    "model": "openai/gpt-5.6-sol",
    "input": "Explain quantum error correction in two sentences."
  }
}
```

* **One turn at a time.** Send the next `response.create` after the previous turn's terminal event.
* **`stream_id`** labels the turn and correlates the events that belong to it.
* **`response.steer`** takes a `previous_response_id` and `input`, and steers the live turn that produced that response. A failure arrives as a `response.steer.failed` event with a code such as `response_not_found` or `steering_not_supported`.
* **Connection lifetime** is 30 minutes; the server sends a `connection_duration_exceeded` error event and closes the socket. Reconnect and continue with `previous_response_id`, which fails with `previous_response_not_found` when the response has expired.

## Errors

| Status | Meaning |
| - | - |
| `400` | `model` is missing on the realtime endpoint, or the model has no realtime protocol |
| `401` | The upgrade carries no valid API key |
| `404` | The named model does not exist |
| `402` | Credits or a Grok Voice budget cannot cover the session |
| `429` | A rate limit or budget rule rejects the connection |


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