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 stops you from filling against them. See Cross-orderbook matching for examples and price/time priority across both outcomes.
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
| Name | Description |
|---|---|
token_id | The outcome you want depth for. Discover via Markets |
Response
{
"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
| 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
curl "$AGARA_BASE_URL/trade/v1/orderbook/21742633143463906290569050155826241533067272736897614950488156847949938836455"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 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). 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:
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
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:
tick_micro = int(float(book["tick_size"]) * 1_000_000) # "0.01" → 10000So price_micro must be a multiple of tick_micro.
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 for the full response schema.