> For the complete documentation index, see [llms.txt](https://docs.ojolabs.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ojolabs.xyz/markets/api/websocket.md).

# Websocket

Real-time orderbook, trade, and market updates via WebSocket.

## Connection

wss\://api.turbinefi.com/api/v1/stream

No authentication is required. The WebSocket endpoint is public.

### Connection lifecycle

* The server sends a **ping** every 54 seconds.
* Clients must respond with a **pong** within 60 seconds or the connection is closed.
* On subscribe, you receive a confirmation message followed by the current orderbook snapshot.

### Example

{% code title="example.js" %}

```javascript
const ws = new WebSocket("wss://api.turbinefi.com/api/v1/stream");

ws.onopen = () => {
  console.log("Connected");
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  console.log(msg.type, msg.data);
};
```

{% endcode %}

## Subscribe

Subscribe to real-time updates for a market. You can optionally filter by outcome.

### Request

```json
{
  "type": "subscribe",
  "marketId": "0x1234...abcd"
}
```

With outcome filter:

```json
{
  "type": "subscribe",
  "marketId": "0x1234...abcd",
  "data": {
    "outcome": 0
  }
}
```

| Field          | Type    | Description                                                    |
| -------------- | ------- | -------------------------------------------------------------- |
| `type`         | string  | `"subscribe"`                                                  |
| `marketId`     | bytes32 | Market to subscribe to                                         |
| `data.outcome` | uint8   | Optional. `0` = YES only, `1` = NO only. Omit for all outcomes |

### Response

You receive a subscription confirmation followed by the initial orderbook snapshot:

```json
{
  "type": "subscribe",
  "marketId": "0x1234...abcd",
  "data": {
    "status": "subscribed"
  }
}
```

```json
{
  "type": "orderbook",
  "marketId": "0x1234...abcd",
  "data": {
    "marketId": "0x1234...abcd",
    "bids": [
      { "price": 450000, "size": 20000000 }
    ],
    "asks": [
      { "price": 550000, "size": 15000000 }
    ],
    "lastUpdate": 1735689000
  }
}
```

## Unsubscribe

Stop receiving updates for a market.

### Request

```json
{
  "type": "unsubscribe",
  "marketId": "0x1234...abcd"
}
```

### Response

```json
{
  "type": "unsubscribe",
  "marketId": "0x1234...abcd",
  "data": {
    "status": "unsubscribed"
  }
}
```

## Event Types

All server messages follow this format:

```json
{
  "type": "<event_type>",
  "marketId": "0x...",
  "data": { ... }
}
```

### orderbook

Full orderbook snapshot sent on subscribe and after each trade or order change.

```json
{
  "type": "orderbook",
  "marketId": "0x1234...abcd",
  "data": {
    "marketId": "0x1234...abcd",
    "bids": [
      { "price": 450000, "size": 20000000 },
      { "price": 400000, "size": 10000000 }
    ],
    "asks": [
      { "price": 550000, "size": 15000000 },
      { "price": 600000, "size": 5000000 }
    ],
    "lastUpdate": 1735689000
  }
}
```

| Field          | Type   | Description                                                   |
| -------------- | ------ | ------------------------------------------------------------- |
| `bids`         | array  | Buy orders, sorted by price descending                        |
| `asks`         | array  | Sell orders, sorted by price ascending                        |
| `bids[].price` | uint64 | Bid price (6 decimals). `450000` = $0.45                      |
| `bids[].size`  | uint64 | Total size at this price (6 decimals). `20000000` = 20 shares |
| `asks[].price` | uint64 | Ask price (6 decimals). `550000` = $0.55                      |
| `asks[].size`  | uint64 | Total size at this price (6 decimals)                         |
| `lastUpdate`   | uint64 | Unix timestamp of last update                                 |

### trade

Sent when a trade is executed.

```json
{
  "type": "trade",
  "marketId": "0x1234...abcd",
  "data": {
    "marketId": "0x1234...abcd",
    "price": 550000,
    "size": 10000000,
    "outcome": 0,
    "timestamp": 1735689000,
    "tradeHash": "0x...",
    "maker": "0xMakerAddress...",
    "taker": "0xTakerAddress...",
    "side": 0
  }
}
```

| Field       | Type    | Description                                     |
| ----------- | ------- | ----------------------------------------------- |
| `price`     | uint64  | Trade price (6 decimals). `550000` = $0.55      |
| `size`      | uint64  | Trade size (6 decimals). `10000000` = 10 shares |
| `outcome`   | uint8   | `0` = YES, `1` = NO                             |
| `timestamp` | uint64  | Unix timestamp                                  |
| `tradeHash` | string  | Unique trade identifier                         |
| `maker`     | address | Limit order placer                              |
| `taker`     | address | Market order placer                             |
| `side`      | uint8   | Taker's side: `0` = BUY, `1` = SELL             |

### trade\_error

Sent when an on-chain trade settlement fails.

```json
{
  "type": "trade_error",
  "marketId": "0x1234...abcd",
  "data": {
    "marketId": "0x1234...abcd",
    "buyer": "0xBuyerAddress...",
    "seller": "0xSellerAddress...",
    "price": 550000,
    "size": 10000000,
    "txHash": "0xFailedTxHash...",
    "error": "execution reverted"
  }
}
```

| Field    | Type    | Description              |
| -------- | ------- | ------------------------ |
| `buyer`  | address | Buyer's wallet address   |
| `seller` | address | Seller's wallet address  |
| `price`  | uint64  | Trade price (6 decimals) |
| `size`   | uint64  | Trade size (6 decimals)  |
| `txHash` | string  | Failed transaction hash  |
| `error`  | string  | Error description        |

### order\_cancelled

Sent when an order is cancelled, either by the user or by the system (e.g., during market rebalancing).

```json
{
  "type": "order_cancelled",
  "marketId": "0x1234...abcd",
  "data": {
    "orderHash": "0xOrderHash...",
    "marketId": "0x1234...abcd",
    "side": "buy",
    "trader": "0xTraderAddress...",
    "reason": "user_cancelled"
  }
}
```

| Field       | Type    | Description                                                            |
| ----------- | ------- | ---------------------------------------------------------------------- |
| `orderHash` | string  | Cancelled order hash                                                   |
| `marketId`  | string  | Market identifier                                                      |
| `side`      | string  | `"buy"` or `"sell"`                                                    |
| `trader`    | address | Order owner                                                            |
| `reason`    | string  | Cancellation reason (e.g., `"user_cancelled"`, `"market_rebalancing"`) |

### quick\_market

Broadcast to all connected clients when a quick market is created or resolved.

```json
{
  "type": "quick_market",
  "data": {
    "type": "new_market",
    "asset": "BTC",
    "marketId": "0x...",
    "quickMarket": {
      "id": 42,
      "asset": "BTC",
      "startPrice": 9750000000000,
      "startTime": 1735689000,
      "endTime": 1735689900
    }
  }
}
```

```json
{
  "type": "quick_market",
  "data": {
    "type": "resolved",
    "asset": "BTC",
    "marketId": "0x...",
    "quickMarket": {
      "id": 42,
      "asset": "BTC",
      "resolved": true,
      "outcome": 0
    }
  }
}
```

| Field              | Type   | Description                    |
| ------------------ | ------ | ------------------------------ |
| `data.type`        | string | `"new_market"` or `"resolved"` |
| `data.asset`       | string | Asset symbol (e.g., `"BTC"`)   |
| `data.marketId`    | string | Market identifier              |
| `data.quickMarket` | object | Quick market details           |

Quick market events are sent to **all** connected clients regardless of subscriptions.

## Full example

{% tabs %}
{% tab title="JavaScript" %}
{% code title="full-example.js" %}

```javascript
const ws = new WebSocket("wss://api.turbinefi.com/api/v1/stream");

ws.onopen = () => {
  // Subscribe to a market (YES outcome only)
  ws.send(JSON.stringify({
    type: "subscribe",
    marketId: "0x1234...abcd",
    data: { outcome: 0 }
  }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  switch (msg.type) {
    case "subscribe":
      console.log("Subscribed:", msg.data.status);
      break;
    case "orderbook":
      console.log("Bids:", msg.data.bids);
      console.log("Asks:", msg.data.asks);
      break;
    case "trade":
      console.log(`Trade: ${msg.data.size} shares at $${msg.data.price / 1000000}`);
      break;
    case "trade_error":
      console.error("Settlement failed:", msg.data.error);
      break;
    case "order_cancelled":
      console.log("Order cancelled:", msg.data.orderHash, msg.data.reason);
      break;
    case "quick_market":
      console.log("Quick market:", msg.data.type, msg.data.asset);
      break;
  }
};

ws.onclose = () => {
  console.log("Disconnected");
};
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code title="full-example.py" %}

```python
import websocket
import json

def on_message(ws, message):
    msg = json.loads(message)
    print(f"{msg['type']}: {msg.get('data')}")

def on_open(ws):
    ws.send(json.dumps({
        "type": "subscribe",
        "marketId": "0x1234...abcd"
    }))

ws = websocket.WebSocketApp(
    "wss://api.turbinefi.com/api/v1/stream",
    on_message=on_message,
    on_open=on_open
)
ws.run_forever()
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ojolabs.xyz/markets/api/websocket.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
