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

# WebSocket Streaming

> Real-time orderbook updates with the Python SDK

## Overview

The `WebSocketClient` provides real-time streaming of orderbook updates and price data over a persistent WebSocket connection. It supports automatic reconnection and event-driven message handling via decorators.

## Setup

```python theme={null}
from limitless_sdk.websocket import WebSocketClient, WebSocketConfig

config = WebSocketConfig(
    url="wss://ws.limitless.exchange",
    auto_reconnect=True,
    reconnect_delay=5,  # seconds between reconnection attempts
)

ws_client = WebSocketClient(config)
```

| Parameter         | Type    | Default  | Description                                   |
| ----------------- | ------- | -------- | --------------------------------------------- |
| `url`             | `str`   | Required | WebSocket server URL                          |
| `auto_reconnect`  | `bool`  | `True`   | Automatically reconnect on disconnection      |
| `reconnect_delay` | `float` | `1.0`    | Seconds to wait between reconnection attempts |

## Event Handlers

Register handlers for specific events using the `@ws_client.on()` decorator:

```python theme={null}
@ws_client.on("connect")
async def on_connect():
    print("Connected to WebSocket")

@ws_client.on("orderbookUpdate")
async def on_orderbook(data):
    print("Orderbook update:", data)

@ws_client.on("newPriceData")
async def on_price(data):
    print("Price update:", data)
```

### Available Events

| Event             | Payload | Auth          | Description                                                                             |
| ----------------- | ------- | ------------- | --------------------------------------------------------------------------------------- |
| `connect`         | None    | —             | Fired when the WebSocket connection is established                                      |
| `orderbookUpdate` | `dict`  | Public        | Orderbook changes (new bids/asks, removals)                                             |
| `newPriceData`    | `dict`  | Public        | Latest price data for subscribed markets                                                |
| `positions`       | `dict`  | Authenticated | Your position changes (see [Authenticated Subscriptions](#authenticated-subscriptions)) |
| `orderEvent`      | `dict`  | Authenticated | Your CLOB order lifecycle and settlement events                                         |

## Subscribing to Markets

After connecting, subscribe to specific markets to receive updates:

```python theme={null}
@ws_client.on("connect")
async def on_connect():
    await ws_client.subscribe(
        "subscribe_market_prices",
        {"marketSlugs": ["btc-above-100k-march-2025"]},
    )
    print("Subscribed to market prices")
```

The `subscribe()` method takes two arguments:

| Parameter | Type   | Description                                                |
| --------- | ------ | ---------------------------------------------------------- |
| `event`   | `str`  | Subscription event name (e.g. `"subscribe_market_prices"`) |
| `data`    | `dict` | Subscription parameters including `marketSlugs`            |

<Tip>
  You can subscribe to multiple markets at once by passing a list of slugs in `marketSlugs`.
</Tip>

## Authenticated Subscriptions

The `subscribe_positions` and `subscribe_order_events` channels are per-account and require authentication. Pass `hmac_credentials` to the config — the SDK signs the WebSocket handshake automatically (no manual headers needed). This is the same flow as the [TypeScript SDK](/developers/sdk/typescript/websocket); see [Authentication](/developers/authentication) to generate a token.

```python theme={null}
from limitless_sdk import HMACCredentials
from limitless_sdk.websocket import WebSocketClient, WebSocketConfig

config = WebSocketConfig(
    url="wss://ws.limitless.exchange",
    hmac_credentials=HMACCredentials(
        token_id="your_token_id",
        secret="your_token_secret",  # base64-encoded secret from token creation
    ),
    auto_reconnect=True,
)
ws_client = WebSocketClient(config)
```

### Positions

Subscribe to real-time updates when your positions change:

```python theme={null}
@ws_client.on("connect")
async def on_connect():
    await ws_client.subscribe(
        "subscribe_positions",
        {"marketSlugs": ["btc-above-100k-march-2025"]},
    )

@ws_client.on("positions")
async def on_positions(data):
    print("Position update:", data)
```

### Order Events

Subscribe to your CLOB order lifecycle and settlement events. This channel is per-account and takes no payload:

```python theme={null}
@ws_client.on("connect")
async def on_connect():
    await ws_client.subscribe("subscribe_order_events")

@ws_client.on("orderEvent")
async def on_order_event(event):
    # Several event shapes arrive on the same `orderEvent` name — distinguish by source, then type
    if event.get("source") == "OME":
        print("Order state:", event.get("type"), event.get("orderId"), event.get("clientOrderId"))
    else:
        print("Settlement:", event.get("type"), event.get("orderId"), event.get("txHash"))
```

<Note>
  Authenticated `subscribe()` calls raise `ValueError` if no `hmac_credentials` is set. Auth failures surface on the `exception` event. See the [WebSocket Events reference](/developers/websocket-events) for the full `orderEvent` payload shapes (`source` `OME` vs `SETTLEMENT`, and `type` values).
</Note>

## Auto-Reconnect

When `auto_reconnect` is enabled (the default), the client automatically reconnects after a disconnection:

1. The connection drops (network issue, server restart, etc.)
2. The client waits `reconnect_delay` seconds
3. A new connection is established
4. The `connect` event fires again, so your subscription logic re-executes

<Note>
  Place your `subscribe()` calls inside the `connect` handler to ensure subscriptions are restored after every reconnection.
</Note>

## Complete Example

```python theme={null}
import asyncio
from limitless_sdk.websocket import WebSocketClient, WebSocketConfig

async def main():
    config = WebSocketConfig(
        url="wss://ws.limitless.exchange",
        auto_reconnect=True,
        reconnect_delay=5,
    )
    ws_client = WebSocketClient(config)

    @ws_client.on("connect")
    async def on_connect():
        print("Connected")
        await ws_client.subscribe(
            "subscribe_market_prices",
            {"marketSlugs": ["btc-above-100k-march-2025"]},
        )

    @ws_client.on("orderbookUpdate")
    async def on_orderbook(data):
        slug = data.get("marketSlug", "unknown")
        bids = len(data.get("bids", []))
        asks = len(data.get("asks", []))
        print(f"[{slug}] Orderbook: {bids} bids, {asks} asks")

    @ws_client.on("newPriceData")
    async def on_price(data):
        slug = data.get("marketSlug", "unknown")
        price = data.get("price", "N/A")
        print(f"[{slug}] Price: {price}")

    # Connect, then keep the client alive to receive events
    await ws_client.connect()
    await asyncio.Event().wait()  # runs until interrupted (Ctrl+C)

asyncio.run(main())
```

<Warning>
  `await ws_client.connect()` returns once the connection is established — it does **not** block. Keep the event loop alive afterwards (e.g. `await asyncio.Event().wait()`), otherwise the program exits before any events arrive. Register your `@ws_client.on(...)` handlers and `subscribe()` inside the `connect` handler before calling `connect()`.
</Warning>
