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

# tpslBook

{% hint style="info" %}
💧 New endpoint - this endpoint is not a part of original Hyperliquid API and is added by us for builder convenience.
{% endhint %}

### Overview

The `tpslBook` endpoint returns a snapshot of all untriggered TP/SL orders (take profit, stop loss) across all markets. These are orders that exist on Hyperliquid but have **not yet been triggered** — they are not visible in the L4 orderbook.

**Key details:**

* \~110K trigger orders across \~330 markets (typical)
* Updated in real-time (per-block)
* Includes user address, trigger price, size, and order type for each order
* Use with [tpslUpdates](/readme/websocket/tpslupdates.md) WebSocket stream for real-time sync

## Request

**Endpoint:** `POST /info`

**All markets:**

```json
{
    "type": "tpslBook"
}
```

**Specific coins:**

```json
{
    "type": "tpslBook",
    "coins": ["BTC", "ETH"]
}
```

**Parameters:**

| Parameter | Type      | Required | Description                                      |
| --------- | --------- | -------- | ------------------------------------------------ |
| `coins`   | string\[] | No       | Specific markets to fetch. Omit for all markets. |

### Response

**Content-Type:** `application/octet-stream`

The response is a binary multi-zstd payload (\~4.2 MB for all markets, vs \~31 MB if served as JSON). Each market is compressed independently and concatenated with the same outer framing as [l4Book](/readme/rest-api/market-data/l4book.md). The SDK's `TpslClient` decodes this transparently — see [Streaming sync](#streaming-sync) below.

**Response headers:**

| Header             | Value                      |
| ------------------ | -------------------------- |
| `Content-Type`     | `application/octet-stream` |
| `x-payload-format` | `multi-zstd`               |
| `x-compression`    | `inner-zstd`               |

**Logical content (after decode):**

```json
{
    "height": 1012534610,
    "timestamp_ms": 1779884746878,
    "markets": [
        {
            "coin": "BTC",
            "orders": [
                {
                    "oid": 443601009265,
                    "coin": "BTC",
                    "user": "0x106cf0642235394d51cba33693ac49ce05262298",
                    "side": "B",
                    "triggerPx": "71000",
                    "limitPx": "63900",
                    "sz": "0.00789",
                    "triggerCondition": "Price below 71000",
                    "orderType": "Take Profit Market",
                    "isPositionTpsl": false,
                    "reduceOnly": true,
                    "timestamp": 1779821645206
                }
            ]
        }
    ]
}
```

### Response fields

| Field              | Type   | Description                              |
| ------------------ | ------ | ---------------------------------------- |
| `height`           | int    | Block height at the time of the snapshot |
| `timestamp_ms`     | int    | Block timestamp (ms since epoch)         |
| `markets`          | array  | Array of markets with trigger orders     |
| `markets[].coin`   | string | Market symbol                            |
| `markets[].orders` | array  | Trigger orders in this market            |

Order fields are the same as the [tpslUpdates](/readme/websocket/tpslupdates.md) `add` diff — see that page for full field descriptions.

<details>

<summary>Wire format (for non-SDK decoders)</summary>

All integers are little-endian. The SDK's [tpsl\_formats.py](https://github.com/hydromancerxyz/hydromancer-sdk/blob/main/src/hydromancer_sdk/_internal/tpsl_formats.py) is a \~100-line reference decoder.

**Outer framing:**

```
[count:u32_le][height:u64_le][timestamp_ms:u64_le]
  [blob_len:u32_le][blob_bytes] × count
```

| Field          | Bytes      | Description                                 |
| -------------- | ---------- | ------------------------------------------- |
| `count`        | 4          | Number of market blobs that follow          |
| `height`       | 8          | Block height of the snapshot                |
| `timestamp_ms` | 8          | Block timestamp (ms since epoch)            |
| `blob_len`     | 4          | Length in bytes of the next compressed blob |
| `blob_bytes`   | `blob_len` | zstd-compressed market payload (see below)  |

Markets are sorted by coin name. Coins with no trigger orders are omitted.

**Per-market blob:**

Each blob is `zstd(msgpack([coin, [order_tuples...]]))`. The msgpack uses positional arrays (not maps) for compactness — `rmp_serde::to_vec` on the Rust side. Each order is a 12-element array in struct-declaration order:

```
[oid, coin, user, side, trigger_px, limit_px, sz,
 trigger_condition, order_type, is_position_tpsl,
 reduce_only, timestamp]
```

| Index | Field               | Type   | Notes                                        |
| ----- | ------------------- | ------ | -------------------------------------------- |
| 0     | `oid`               | uint64 | Order ID                                     |
| 1     | `coin`              | string | Market symbol (matches outer `coin`)         |
| 2     | `user`              | string | User address (0x...)                         |
| 3     | `side`              | string | `"A"` (sell) or `"B"` (buy)                  |
| 4     | `trigger_px`        | string | Trigger price, decimal string                |
| 5     | `limit_px`          | string | Limit price, decimal string                  |
| 6     | `sz`                | string | Size, decimal string                         |
| 7     | `trigger_condition` | string | Human-readable condition                     |
| 8     | `order_type`        | string | E.g. `"Take Profit Market"`, `"Stop Market"` |
| 9     | `is_position_tpsl`  | bool   | `true` if attached to a position             |
| 10    | `reduce_only`       | bool   | `true` if reduce-only                        |
| 11    | `timestamp`         | uint64 | Order creation timestamp (ms)                |

</details>

### Streaming sync

To maintain a real-time view of trigger orders:

1. Subscribe to [tpslUpdates](/readme/websocket/tpslupdates.md) WebSocket stream
2. Fetch `tpslBook` snapshot — note the `height`
3. Apply buffered WS updates where `height > snapshot_height`
4. Continue applying live updates

See the [TP/SL heatmap streaming guide](/readme/builder-guides/tpsl-heatmap-streaming.md) for details.

### Rate limits

* 10 requests per 5 minutes

### Common errors

* **403**: Permission denied - check API key
* **429**: Rate limit exceeded
* **503**: Service unavailable - heatmap service is bootstrapping


---

# 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, and the optional `goal` query parameter:

```
GET https://docs.hydromancer.xyz/readme/rest-api/market-data/tpslbook.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
