# Orderbook

> Live bid/ask depth for one outcome.

The snapshot shows liquidity at prices for the requested outcome. In binary
markets with cross-orderbook matching enabled, it includes both that outcome's
resting orders and complementary liquidity from the other outcome.

For a YES snapshot:

| Resting order    | Where it appears |
| ---------------- | ---------------- |
| BUY YES at 0.40  | YES bid at 0.40  |
| SELL NO at 0.60  | YES bid at 0.40  |
| SELL YES at 0.60 | YES ask at 0.60  |
| BUY NO at 0.40   | YES ask at 0.60  |

Quantities at the same effective price are added together. The NO snapshot
shows the same liquidity from the opposite perspective; do not sum both
snapshots as separate liquidity. Your own resting orders are included, but
[self-trade prevention](/docs/self-trade-prevention) stops you from filling
against them. See [Cross-orderbook matching](/docs/cross-orderbook-matching)
for examples and price/time priority across both outcomes.

## Read the orderbook [#read-the-orderbook]

`GET /trade/v1/orderbook/{token_id}`

**Public — no token required.** Market data is free to read by anyone;
you only need a token for private trading endpoints. Omit the
`Authorization` header. Supplying one makes the request authenticate: an
invalid token returns `401`, and a valid token consumes your Read budget.

### Path parameters [#path-parameters]

| Name       | Description                                                           |
| ---------- | --------------------------------------------------------------------- |
| `token_id` | The outcome you want depth for. Discover via [Markets](/docs/markets) |

### Response [#response]

```json
{
  "bids": [
    { "price": 0.58, "size": 100.0 },
    { "price": 0.57, "size": 250.0 }
  ],
  "asks": [
    { "price": 0.60, "size": 75.0 },
    { "price": 0.61, "size": 300.0 }
  ],
  "timestamp": "2026-05-12T10:23:45.678Z",
  "hash": "1234",
  "tick_size": "0.01"
}
```

| Field       | Notes                                                                                                                                                                  |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bids`      | Best bid first, descending by price                                                                                                                                    |
| `asks`      | Best ask first, ascending by price                                                                                                                                     |
| `price`     | Dollars per share as a float. **Not micro units** — the orderbook is the one endpoint that breaks the convention, because most consumers feed it directly into a chart |
| `size`      | Shares as a float                                                                                                                                                      |
| `timestamp` | When the snapshot was taken                                                                                                                                            |
| `hash`      | The engine sequence for the ladder. Equal values mean bids and asks have not changed; `timestamp` is still refreshed per response                                      |
| `tick_size` | The minimum price increment for this market (`"0.01"` means prices snap to the nearest cent)                                                                           |

Empty sides come back as empty arrays, not omitted. If nobody is
bidding, you get `"bids": []`.

### Errors [#errors]

| Status                            | Reason                                                                            |
| --------------------------------- | --------------------------------------------------------------------------------- |
| `404 token_not_found`             | Stop requesting this `token_id`; discover the current outcome IDs again           |
| `502 dependency_invalid_response` | Do not reuse the response; retain `request_id` and retry only after investigating |
| `503 dependency_unavailable`      | Back off with jitter and retry                                                    |

### Examples [#examples]

```bash
curl "$AGARA_BASE_URL/trade/v1/orderbook/21742633143463906290569050155826241533067272736897614950488156847949938836455"
```

```python
import os, requests

resp = requests.get(f"{os.environ['AGARA_BASE_URL']}/trade/v1/orderbook/{token_id}")
resp.raise_for_status()
book = resp.json()

best_bid = book["bids"][0]["price"] if book["bids"] else None
best_ask = book["asks"][0]["price"] if book["asks"] else None
mid = (
    (best_bid + best_ask) / 2
    if best_bid is not None and best_ask is not None
    else None
)

print(f"best bid {best_bid} / ask {best_ask} / mid {mid}")
```

## Polling cadence [#polling-cadence]

Polling the snapshot on a loop is the simplest approach — 1–2 seconds is
the right ballpark for most strategies. For lower-latency updates, subscribe
to the live `orderbook` channel on the public market WebSocket instead (see
[Streaming](/docs/streaming)). Current v1 sends a replacement `snapshot` after
every book change. Clients must still route on `data.kind` and apply a `delta`
if one is received. API traders should keep this REST endpoint in their
startup and recovery flow: subscribe and buffer first, wait for the initial
orderbook `snapshot`, then use the REST `hash` as the sequence baseline before
processing later frames.

Use the `hash` to skip work when nothing's changed:

```python
last_hash = None
while True:
    book = fetch_orderbook(token_id)
    if book["hash"] != last_hash:
        last_hash = book["hash"]
        on_book_change(book)
    time.sleep(1.5)
```

## Price grid [#price-grid]

Orders only match on a fixed price grid set per market. If you place
a limit price that isn't a multiple of `tick_size`, the request is
rejected. For most markets, `tick_size` is `"0.01"` — prices snap to
the nearest cent (`0.60`, `0.61`, …, never `0.605`).

When you place an order, the price comes in as `price_micro` (an
integer in millionths of a collateral unit). To translate the `tick_size` string
into a step in micro units:

```python
tick_micro = int(float(book["tick_size"]) * 1_000_000)  # "0.01" → 10000
```

So `price_micro` must be a multiple of `tick_micro`.

## Top of book vs. full depth [#top-of-book-vs-full-depth]

The response returns the full depth on both sides — there's no
`depth=N` query parameter today. If you only need top-of-book, take
`bids[0]` and `asks[0]`. If you need to control payload size, let us
know.

See [Get orderbook depth](/docs/api-reference/orderbook/agara_orderbook) for the
full response schema.
