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

# Subscribe to Real-Time Streams via Molecule WebSockets

> Subscribe to real-time order, fill, position, balance, order book, and trade print streams over signed WebSocket connections using the Molecule API.

Molecule exposes signed WebSocket streams for every major account and market event. Use these streams to receive low-latency updates on your orders, fills, positions, and balances without polling the REST API, and to consume live order book depth and public trade prints for market-making or monitoring strategies. All WebSocket URLs are authenticated with the same Ed25519 credentials used for REST requests — the SDK signs the connection URL automatically.

## Available Streams

| Stream | Path | Description |
| - | - | - |
| orders | `/v1/ws/orders` | Real-time updates for your order statuses |
| fills | `/v1/ws/fills` | Execution fill events as they occur |
| positions | `/v1/ws/positions` | Position changes as orders are filled |
| balances | `/v1/ws/balances` | Account balance changes |
| orderbooks | `/v1/ws/orderbooks` | Order book snapshots and incremental updates |
| tradeprints | `/v1/ws/tradeprints` | Public trade print feed |

## Authentication

WebSocket connections are authenticated using **signed query parameters** rather than headers. The SDK appends three parameters to every WebSocket URL it constructs:

| Parameter | Description |
| - | - |
| `key_id` | Your API key identifier |
| `ts` | Unix timestamp in milliseconds |
| `sig` | Ed25519 signature over the canonical WebSocket string |

The canonical WebSocket message format is:

```text theme={"dark"}
WS\n{path}\n{sorted_query_without_signing_params}\n{timestamp}
```

The signature covers the path and any stream-specific query parameters (such as `subaccount_id` or `instrument_id`) but excludes the signing parameters themselves to avoid circular dependencies. You do not need to construct this manually — the SDK handles it whenever a `key_id` and `private_key` are configured.

<Info>
  The signed timestamp must be within **30 seconds** of the server clock. Connections with a stale timestamp are rejected with an `unauthorized` / `stale_timestamp` error.
</Info>

## Connecting with the SDK

### `client.iter_ws(path, params)`

The primary way to consume a stream is `client.iter_ws(path, params)`. It returns a synchronous iterator that yields parsed JSON messages from the stream. The iterator blocks until the connection closes or an exception is raised.

**Subscribe to order updates:**

```python theme={"dark"}
from molecule import Molecule

client = Molecule(
    base_url="https://api.molecule.fi",
    key_id="your-key-id",
    private_key="your-base64-private-key",
)

for message in client.iter_ws("/v1/ws/orders", {"subaccount_id": "sub_123"}):
    print(message)
```

**Subscribe to order book updates for a specific instrument:**

```python theme={"dark"}
for update in client.iter_ws("/v1/ws/orderbooks", {"instrument_id": 4001}):
    bids = update.get("bids", [])
    asks = update.get("asks", [])
    print(f"Best bid: {bids[0] if bids else 'none'}, Best ask: {asks[0] if asks else 'none'}")
```

### Obtaining a Signed URL

If you prefer to manage the WebSocket connection yourself — for example, using a library with reconnect logic or async support — retrieve a pre-signed URL with `client.ws.url(path, params)` or a convenience method, and pass it to your WebSocket client.

```python theme={"dark"}
url = client.ws.orders({"subaccount_id": "sub_123"})
# Use url with any websocket library
import websockets

async def stream_orders():
    async with websockets.connect(url) as ws:
        async for message in ws:
            print(message)
```

## Convenience URL Methods

The `client.ws` sub-client provides named methods for every available stream. Each method returns a fully signed URL string ready for direct use with any WebSocket library.

<CodeGroup>
  ```python Orders theme={"dark"}
  url = client.ws.orders({"subaccount_id": "sub_123"})
  ```

  ```python Fills theme={"dark"}
  url = client.ws.fills({"subaccount_id": "sub_123"})
  ```

  ```python Positions theme={"dark"}
  url = client.ws.positions({"subaccount_id": "sub_123"})
  ```

  ```python Balances theme={"dark"}
  url = client.ws.balances({"subaccount_id": "sub_123"})
  ```

  ```python Order Books theme={"dark"}
  url = client.ws.orderbooks({"instrument_id": 4001})
  ```

  ```python Trade Prints theme={"dark"}
  url = client.ws.tradeprints({"instrument_id": 4001})
  ```

  ```python Generic Asset Order Book theme={"dark"}
  # Cross-venue order book aggregated by generic_asset_id
  url = client.ws.generic_asset_orderbook(
      generic_asset_id=9001,
      params={"subaccount_id": "sub_123"},
  )
  ```
</CodeGroup>

### Stream Reference

| Method | Path | Key Query Params |
| - | - | - |
| `client.ws.orders(params)` | `/v1/ws/orders` | `subaccount_id` |
| `client.ws.fills(params)` | `/v1/ws/fills` | `subaccount_id` |
| `client.ws.positions(params)` | `/v1/ws/positions` | `subaccount_id` |
| `client.ws.balances(params)` | `/v1/ws/balances` | `subaccount_id` |
| `client.ws.orderbooks(params)` | `/v1/ws/orderbooks` | `instrument_id` |
| `client.ws.tradeprints(params)` | `/v1/ws/tradeprints` | `instrument_id` |
| `client.ws.generic_asset_orderbook(generic_asset_id, params)` | `/v1/ws/orderbooks/generic-asset/{id}` | `generic_asset_id`, `subaccount_id` |

<Note>
  `client.iter_ws()` is a **synchronous, blocking iterator**. It holds the calling thread open for the duration of the connection. To consume multiple streams concurrently, run each in a separate thread or use the signed URL methods (`client.ws.*`) with an async WebSocket library in an `asyncio` event loop.
</Note>


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