> For the complete documentation index, see [llms.txt](https://docs.sfox.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sfox.com/websocket-api/market-data/order-book.md).

# Order Book

Real-time order book snapshots and incremental updates for a currency pair.

The WebSocket API provides incremental Orderbook Delta feeds.

### Orderbook Delta feed

The Orderbook Delta feed sends an initial snapshot of the configured published depth first. It then sends sequential updates containing only changed levels. Apply these updates to maintain a local order book.

#### Subscribe

Subscribe to `orderbook.delta.<pair>`, where `<pair>` is a lowercase currency pair.

#### Message format

| Field           | Type    | Description                                                                                                                       |
| --------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `pair`          | string  | Currency pair, such as `btcusd`.                                                                                                  |
| `product_type`  | string  | Product type for the order book. Values are `spot` or `perp`.                                                                     |
| `type`          | string  | `snapshot` or `update`.                                                                                                           |
| `bids`          | array   | Bid levels. See [Order book structure](#order-book-structure).                                                                    |
| `asks`          | array   | Ask levels. See [Order book structure](#order-book-structure).                                                                    |
| `lu`            | integer | UNIX timestamp in milliseconds when the book was last updated.                                                                    |
| `lp`            | integer | UNIX timestamp in milliseconds when the book was last published.                                                                  |
| `u`             | integer | Incrementing update ID for validating message order.                                                                              |
| `market_making` | object  | Separate top-of-book maker quotes, grouped by side. In update messages, `bids` or `asks` is `null` when that side has no changes. |

#### Order book structure

Each level has the form `[price, quantity, liquidity_source]`. Prices and quantities are strings.

Maintain normal bids and asks by side, price, and liquidity source. The `market_making` book is separate. Maintain it by side and liquidity source.

Market-making prices include maker fees. They may differ from normal order book levels.

#### Snapshot message

A snapshot contains the configured published depth for the normal order book and the current market-making state. The normal order book contains the configured top N levels per side, not the entire order book. Replace both local books and store `u`.

See the **Snapshot message** example below.

#### Update message

An update contains only changed levels. Omitted levels remain unchanged. A quantity of `"0"` removes the matching level from the local published book. Because the feed represents only the configured top levels per side, `"0"` may also mean that the level moved outside the published depth window.

See the **Update message** example below.

#### Maintain a synchronized book

1. Each WebSocket message wraps the payload:

   `{"recipient":"orderbook.delta.btcusd","timestamp":<ns>,"payload":{...}}`

   Orderbook Delta messages do not contain the general WebSocket `sequence` field. Use `payload.u` for message ordering and gap detection.

   1. Discard updates until you receive a snapshot.
   2. On any snapshot, replace the normal and market-making books and store its `u`, regardless of its value.
   3. For each update:
      * If `u` is less than or equal to the stored update ID, ignore the update.
      * If `u` equals the stored update ID plus 1, apply the update and store the new `u`.
      * If `u` is greater than the stored update ID plus 1, updates were missed. Unsubscribe, subscribe again, and discard updates until a new snapshot arrives.
   4. Upsert levels with non-zero quantities and remove levels whose quantity is `"0"`.
   5. Compare prices numerically rather than as formatted strings.

   The local book represents only the configured top levels per side. A quantity of `"0"` can indicate that a level was removed or that it moved outside the published depth.

If a client cannot consume Delta messages fast enough, messages may be dropped rather than queued indefinitely. This will appear as a gap in `u`. When a gap is detected, resubscribe and rebuild the book from the next snapshot.

For market-making updates, `market_making.bids` or `market_making.asks` is `null` when that side has no changes.

#### Examples

{% tabs %}
{% tab title="NodeJS" %}

```javascript
const WebSocket = require('ws')

const ws = new WebSocket('wss://ws.sfox.com/ws')

ws.on('open', function() {
  ws.send(JSON.stringify({
    type: 'authenticate',
    apiKey: '<API_KEY>'
  }))

  ws.send(JSON.stringify({
    type: 'subscribe',
    feeds: ['orderbook.delta.btcusd']
  }))
})

ws.on('message', function(message) {
  console.log(JSON.parse(message))
})
```

{% endtab %}

{% tab title="Python" %}

```python
import asyncio
import json
import websockets

async def main(uri):
    async with websockets.connect(uri) as ws:
        await ws.send(json.dumps({
            "type": "authenticate",
            "apiKey": "<API_KEY>"
        }))

        await ws.send(json.dumps({
            "type": "subscribe",
            "feeds": ["orderbook.delta.btcusd"]
        }))

        async for message in ws:
            print(json.loads(message))

asyncio.run(main("wss://ws.sfox.com/ws"))
```

{% endtab %}

{% tab title="Snapshot message" %}

```json
{
  "recipient": "orderbook.delta.btcusd",
  "timestamp": 1737568924001000000,
  "payload": {
    "pair": "btcusd",
    "product_type": "spot",
    "type": "snapshot",
    "bids": [["92567.89", "2.34", "market1"]],
    "asks": [["92568.45", "1.12", "otc17"]],
    "lu": 1737568923478,
    "lp": 1737568924001,
    "u": 10000,
    "market_making": {
      "bids": [["92567.5", "2.34", "market2"]],
      "asks": [["92568.8", "1.12", "otc61"]]
    }
  }
}
```

{% endtab %}

{% tab title="Update message" %}

```json
{
  "recipient": "orderbook.delta.btcusd",
  "timestamp": 1737568931500000000,
  "payload": {
    "pair": "btcusd",
    "product_type": "spot",
    "type": "update",
    "bids": [["92567.89", "1.98", "market1"], ["92566.12", "0", "otc61"]],
    "asks": [["92600", "2", "otc17"]],
    "lu": 1737568931123,
    "lp": 1737568931500,
    "u": 10001,
    "market_making": {
      "bids": [["92567.5", "1.98", "market2"]],
      "asks": null
    }
  }
}
```

{% endtab %}
{% endtabs %}

Prices and quantities are encoded as strings, but formatting is not fixed-width and trailing zeros may be omitted. Compare prices and quantities numerically rather than by string representation.


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.sfox.com/websocket-api/market-data/order-book.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
