Documentation

API reference

Everything for the DepthFeed v3 API — authentication, every endpoint, the response contract, the data model, and the venues behind it. Base URL https://api.depthfeed.com/v3.

Contents

Introduction

DepthFeed is historical order-book depth for prediction markets — the full bid/ask ladder on both sides, captured tick by tick, for Polymarket, Kalshi, and Limitless. Not the last trade price, not the top of book — every resting level with its size, at every change. It is the data you need to backtest a fill against the liquidity that was actually there.

It is delivered over a metered REST API — market discovery, metadata, and latest + historical order-book snapshots, keyset-paginated with per-plan rate limits. Pull exactly the depth your strategy needs and replay it in your own stack.

Coverage spans 3 venues, 7 assets (btc · eth · sol · xrp · doge · bnb · hype) and the recurring up/down crypto markets each venue runs (5m, 15m, 1h, 4h, 24h, depending on venue).

New to evaluating data sources? The buyer’s guide covers the five criteria that decide whether prediction-market data is actually backtestable, and how DepthFeed clears each.

Independent project. Not affiliated with Polymarket, Kalshi, Binance, Chainlink, or Limitless. Coverage is continuous: our own capture runs live, and licensed historical depth extends the archive back to March 2026— every plan’s full window is backed by stored data, not a forward-filling promise. Third-party data attribution is listed in the terms.

Quickstart

1. Create a free account and mint an API key from the dashboard. Keys look like df_… and are shown once.

2. Make your first authenticated call:

shell
curl https://api.depthfeed.com/v3/whoami \
  -H "Authorization: Bearer df_your_key_here"

3. The response is a JSON envelope — your plan, limits, and history window:

json
{
  "data": {
    "user_id": "acct_…", "plan": "pro",
    "rps": 25, "rpm": 1000, "history_days": 30, "coins": "all"
  },
  "meta": { "request_id": "req_…", "timestamp": "2026-06-07T02:27:09.532Z" }
}

4. Pull the latest BTC up/down markets, then the order-book depth for one of them — see Markets and Snapshots.

Authentication

Every endpoint except /v3/health and /v3/overview requires an API key. Pass it either way — both schemes are accepted:

shell
# Authorization header (recommended)
curl https://api.depthfeed.com/v3/btc/markets -H "Authorization: Bearer df_your_key"

# or the X-API-Key header
curl https://api.depthfeed.com/v3/btc/markets -H "X-API-Key: df_your_key"
/v3/streamalso requires a key, but authenticates once at connection time — a WebSocket can’t carry a per-request header, so it accepts X-API-Key, Authorization: Bearer, or a ?api_key= query param. See Live stream.

Keys are minted per account from the dashboard and carry a plan that sets your rate limit, history window, and asset/venue access. Keys are stored SHA-256-hashed at rest — the raw value is shown exactly once at creation. Revoking a key in the dashboard takes effect immediately. Quotas are per user, not per key — extra keys do not multiply your limit.

FailureStatuscode
No key supplied401AUTH_MISSING
Unknown / revoked / malformed key401AUTH_INVALID
Key store temporarily unreachable503AUTH_UNAVAILABLE

Base URL & versioning

All endpoints live under a single versioned base path:

text
https://api.depthfeed.com/v3

TLS is required (Let's Encrypt, HTTP/2). The current API version is v3, built to PolyBackTest parity (same envelope, cursor pagination, and error-code enum) over our superset data (3 venues, 7 assets). Legacy v1/v2 namespaces are not served.

Response format

Every successful response is the same envelope:

json
{
  "data": … ,                 // object (single) or array (list)
  "pagination": { … },        // present only on list endpoints
  "meta": { "request_id": "req_…", "timestamp": "2026-06-07T02:27:09.532Z" }
}

Errors share the shape, with the HTTP status set per code:

json
{
  "error": { "code": "INVALID_COIN", "message": "…", "details": { … } },
  "meta": { "request_id": "req_…", "timestamp": "…" }
}

Every response — success or error — carries meta.request_id, also returned as the X-Request-Id header. Quote it in support requests.

Errors

Branch on error.code — it is stable. The HTTP status is implied by the code.

codeHTTPMeaning
AUTH_MISSING401No API key on the request.
AUTH_INVALID401Key is unknown, revoked, or malformed.
COIN_NOT_IN_PLAN402Your plan does not include that coin (e.g. eth on Free).
ENDPOINT_NOT_IN_PLAN402Kalshi / Limitless require a paid plan.
HISTORY_LIMIT_EXCEEDED403start_time / timestamp is older than your plan window.
INVALID_COIN400Coin not one of the seven supported.
INVALID_CURSOR400Cursor is malformed.
INVALID_TIMESTAMP400Not ms-epoch or ISO-8601.
INVALID_INTERVAL400interval not a duration like 30s, 1m, 5m, 1h, 1d (1s–1d).
INVALID_SLUG400Empty/invalid {slug} path segment (e.g. a missing URL variable).
INVALID_TICKER400Empty/invalid {ticker} path segment.
BATCH_TOO_LARGE400More than 10 sub-requests in a batch.
BATCH_INVALID_PATH400Sub-request is not a GET /v3/ path (per-sub status).
MARKET_NOT_FOUND404No market with that id / slug / ticker.
SNAPSHOT_NOT_FOUND404No snapshot for the query.
ENDPOINT_NOT_FOUND404Path matches no v3 route.
RATE_LIMIT_BURST429Per-second burst exceeded.
RATE_LIMIT_SUSTAINED429Per-minute sustained limit exceeded.
INTERNAL_ERROR500Unexpected server error — retry, then contact us with the request id.
AUTH_UNAVAILABLE503Key verification is temporarily unavailable — retry shortly.

403 HISTORY_LIMIT_EXCEEDED carries details.max_history_days and details.oldest_allowed. 429 also sets Retry-After and the X-RateLimit-* headers.

Rate limits

Limits are a per-user token bucket with two windows: a per-second burst and a per-minute sustained cap. Exceeding either returns 429 with the matching code and a Retry-After of 1 second.

HeaderMeaning
X-RateLimit-LimitYour per-second burst limit (rps).
X-RateLimit-RemainingBurst tokens left this second.
Retry-AfterSeconds to wait (set on 429).
X-Request-IdEcho of meta.request_id.

See Plans & access for the rps/rpm per tier.

Pagination & filters

List endpoints use opaque keyset cursors — O(1) at any depth. Pass ?cursor= from the previous page's pagination.next_cursor; stop when has_more is false.

json
"pagination": {
  "next_cursor": "6274…",   // opaque; feed back as ?cursor=
  "has_more": true,
  "limit": 50,
  "count": 50,
  "total_count": 1284        // only when ?include_count=true
}

Common query parameters

ParamTypeNotes
limitintMarkets max 100, snapshots/trades max 1000. Defaults: 50 / 100.
cursorstringOpaque keyset cursor from the prior page.
include_countboolAdds total_count (costs a COUNT — opt-in).
start_timetsms-epoch or ISO-8601. Older than your window → 403.
end_timetsms-epoch or ISO-8601.
intervaldurSnapshots only. Downsample to one book per bucket (latest in each): 30s, 1m, 5m, 1h … up to 1d. Omit for full resolution.

Timestamps accept either milliseconds-since-epoch (e.g. 1780774485780) or ISO-8601 (e.g. 2026-06-07T02:27:09Z). Every value reaching the database is validated and injection-safe. The plan history window is enforced on every list/snapshot endpoint: an explicit start_time beyond the window returns 403; an omitted one is clamped to the window floor.

Downsampling with interval

By default the snapshot endpoints return every recorded book change — full event-driven resolution. When you only need a periodic sample (say one book per minute for a chart or a coarse backtest), add ?interval= and the server collapses each time bucket to a single snapshot: the most recent book in that bucket. It is far less data over the wire than fetching every tick and thinning client-side.

shell
# one snapshot per minute instead of every change
curl "https://api.depthfeed.com/v3/btc/markets/{id}/snapshots?interval=1m&include_orderbook=true" \
  -H "Authorization: Bearer df_your_key"

Accepts a duration: a bare number of seconds, or a value with a unit — 30s, 1m, 5m, 15m, 1h, 4h, 1d — from 1s to 1d. Buckets are aligned to the epoch, so 1m snaps to wall-clock minute boundaries. Cursor pagination and include_count apply to the downsampled rows (total_count becomes the number of buckets). Omit it, pass raw, or pass 0 for full resolution. An unrecognised value returns 400 INVALID_INTERVAL. Works on every snapshot endpoint — Polymarket, Kalshi, Limitless, and Binance.

Plans & access

Four flat plans. The plan field returned by /v3/whoami is the raw value in the right column.

PlanplanPricerpsrpmHistoryCoinsVenuesStream
Explorerfree$017 daysBTC onlyPolymarket + Binance1 sub · 1 conn
Quant pro$29/mo251,00030 daysAll 7All — incl. Kalshi + Limitless5 subs · 1 conn
Desk Litescale$79/mo503,00090 daysAll 7All — incl. Kalshi + Limitless25 subs · 2 conns
Deskenterprisefrom $200/mo1006,000Full archiveAll 7All + dedicated infra100 subs · 5 conns · wildcards

Gating is enforced server-side:

  • Coins — a non-BTC coin on Free → 402 COIN_NOT_IN_PLAN.
  • Venues — Kalshi and Limitless on Free → 402 ENDPOINT_NOT_IN_PLAN.
  • Historystart_time beyond your window → 403 HISTORY_LIMIT_EXCEEDED.
  • Streaming — limits apply at subscribe time on /v3/stream; Quant streams Polymarket book + price channels, Desk Lite and up stream every venue.

Health & identity

GET/v3/healthno auth

Liveness probe, no auth. Returns { status: "ok", service, time }.

GET/v3/whoami

Your plan, rate limits, history window, and coin access — the fastest way to confirm a key works.

Markets

Polymarket up/down markets per coin, joined to settlement reference (open/close price, winner, volume). {coin} is one of btc · eth · sol · xrp · doge · bnb · hype.

GET/v3/{coin}/markets

Filters: type (5m/15m/1h/4h/24h), resolved (true/false), plus the common time + pagination params.

GET/v3/{coin}/markets/{market_id}
GET/v3/{coin}/markets/by-slug/{slug}

A single market by id or slug. Example response (per-coin price keys are dynamic, like the reference):

json
{ "data": {
  "market_id": "2456720", "event_id": "566750",
  "slug": "btc-updown-5m-1780860300", "market_type": "5m",
  "start_time": "…", "end_time": "2026-06-07T19:30:00Z",
  "condition_id": "0xb7ce…",
  "clob_token_up": "15598…", "clob_token_down": "51823…",
  "btc_price_start": null, "btc_price_end": null,
  "winner": null, "final_volume": null, "final_liquidity": null, "resolved_at": null
}, "meta": { … } }
The settlement fields — *_price_*, winner, resolved_at, final_volume, and final_liquidity — are null until the market settles and the reference backfills (~12–24 h after settlement).

Order-book snapshots

The order-book depth time-series for a market, with the underlying coin price stamped on each snapshot.

GET/v3/{coin}/markets/{market_id}/snapshots

Add ?include_orderbook=true to get the full ladder (omitted by default for a lighter payload). Time-windowed + cursor-paginated. Add ?interval=1m (or 5m, 1h, …) to downsample to one book per bucket instead of every change — see Pagination & filters. The list response is an array with a pagination block:

json
{ "data": [{
  "id": "1780774485780", "time": "2026-06-06 19:34:45.780",
  "market_id": "2456720", "btc_price": 60606.68,
  "price_up": 0.505, "price_down": 0.495,
  "orderbook_up":   { "bids": [[0.50, 304.25], …], "asks": [[0.51, 30.0], …] },
  "orderbook_down": { "bids": [ … ],               "asks": [[0.50, 304.25], …] }
}], "pagination": { … }, "meta": { … } }
GET/v3/{coin}/markets/{market_id}/snapshots/at/{timestamp}

The single snapshot closest to a timestamp (within ±2 s). {timestamp} is ms-epoch or ISO-8601. Unlike the list endpoint, data is a single object (the same row shape) with no pagination block; no match within ±2 s returns 404 SNAPSHOT_NOT_FOUND.

json
{ "data": {
  "id": "1780774485780", "time": "2026-06-06 19:34:45.780",
  "market_id": "2456720", "btc_price": 60606.68,
  "price_up": 0.505, "price_down": 0.495,
  "orderbook_up":   { "bids": [[0.50, 304.25], …], "asks": [[0.51, 30.0], …] },
  "orderbook_down": { "bids": [ … ],               "asks": [[0.50, 304.25], …] }
}, "meta": { … } }

Levels are [price, size]. price_up is the best-bid/ask midpoint; price_down = 1 − price_up. The orderbook_down side is derived as the binary complement of the up book (down = 1 − up, sizes preserved). The coin price is the nearest preceding tick via an ASOF join — exact for 1h/4h/24h, a labeled Binance proxy for 5m/15m.

Binance — spot & futures

The underlying-asset book and trade tape from Binance. {venue} is spot or futures. The book is 20 levels per side.

GET/v3/{coin}/{venue}/latest
GET/v3/{coin}/{venue}/snapshots

Latest book / paginated book history. Each snapshot: price (mid), bids, asks, timestamp.

GET/v3/{coin}/{venue}/trades
GET/v3/{coin}/{venue}/trades/latest

1-second OHLCV candles with an aggressive buy/sell split — exact, 1:1 with the reference:

json
{ "data": [{
  "id": "1780747762000", "timestamp": "2026-06-06 12:09:22.000",
  "price_open": 61097.1, "price_high": 61097.1,
  "price_low": 61097.09, "price_close": 61097.1,
  "total_volume": 0.01667,
  "aggressive_buy_volume": 0.0156, "aggressive_sell_volume": 0.00107,
  "num_trades": 3
}], "pagination": { … }, "meta": { … } }
Futures trades are currently geo-restricted from our capture region — the endpoint is live and returns a valid empty page; the futures book is unaffected. Spot trades and all books are full.

Kalshi

Kalshi's crypto contracts — full yes/no depth the reference doesn't carry. Paid plans only. 21 series for all 7 assets: 15-minute KX{ASSET}15M, threshold KX{ASSET}, and directional KX{ASSET}D. The threshold and directional series each run hourly, daily, and weekly markets concurrently — market_typecarries each market's actual window.

GET/v3/kalshi/marketspaid plan

Filters: ?coin= (base asset) and ?type= (window). Each market carries market_type (15m/1h/24h/1w), derived from the market's open→close span.

GET/v3/kalshi/{ticker}/orderbook/latestpaid plan

Newest full yes/no book for a ticker. yes/no are [price, size] arrays (prices in 0–1 dollars).

json
{ "data": {
  "ticker": "KXHYPED-26JUN0717-T73.9999", "series": "KXHYPED",
  "base_asset": "hype", "market_type": "24h",
  "id": "1780…", "timestamp": "…",
  "yes": [[0.62, 1400], …], "no": [[0.38, 900], …]
}, "meta": { … } }
GET/v3/kalshi/{ticker}/snapshotspaid plan

The historical yes/no depth series for one ticker — same row shape, ordered by receive time, time-windowed + cursor-paginated (include_count opt-in, max 1000). The forward-captured Kalshi book history (~1.5 s poll cadence) — full parity with Polymarket and Limitless /snapshots, so Kalshi depth is backtestable too.

Comparing all three venues at once? Start from the cross-venue screener instead of stitching per-venue calls.

Limitless

Limitless Exchange — a CLOB on Base running recurring up/down crypto markets at 5m and 15m. Depth is captured live over its order-book websocket (so even the fast 5m books are recorded). Paid plans only. {slug} looks like btc-up-or-down-15-min-1780798512077.

GET/v3/limitless/marketspaid plan

Currently-open slots. Filters: ?coin= and ?type= (5m/15m).

GET/v3/limitless/{slug}/orderbook/latestpaid plan

Newest L2 depth for a slug (bids descending, asks ascending):

json
{ "data": {
  "slug": "btc-up-or-down-15-min-1780798512077", "condition_id": "0x…",
  "base_asset": "btc", "market_type": "15m",
  "id": "1780798…", "timestamp": "2026-06-07 02:27:09.532", "midpoint": 0.5,
  "bids": [[0.45, 200.0], …], "asks": [[0.46, 120.0], …]
}, "meta": { … } }
GET/v3/limitless/{slug}/snapshotspaid plan

The historical depth series for one slug — same row shape, ordered by receive time, time-windowed + cursor-paginated. This is the forward-captured order-book history.

Cross-venue screener

Start here for anything cross-venue. The screener answers the core question — how is the same “up or down” market priced on Polymarket, Kalshi, and Limitless right now? — in a single request, so you never stitch the three per-venue endpoints (with their three different identifiers) together yourself. Plan-aware: on Free you see BTC + Polymarket; the Kalshi and Limitless cells fill in on a paid plan.

GET/v3/screener

The grid: one cell per asset with each venue's latest “up” probability, best bid/ask, and settlement reference. A placeholder/empty book reports null rather than a meaningless 0.50.

json
{ "data": {
  "assets":  ["btc","eth","sol","xrp","doge","bnb","hype"],
  "windows": ["5m","15m","1h","4h","24h"],
  "cells": [{ "asset": "btc",
    "polymarket": { "up": 0.735, "down": 0.265, "best_bid": 0.73, "best_ask": 0.74, "price_to_beat": 62764.0 },
    "kalshi":     { "up": 0.71,  "down": 0.29,  … },
    "limitless":  { "up": 0.75,  "down": 0.25,  "slug": "btc-up-or-down-…", … } }],
  "paid": true
}, "meta": { … } }
GET/v3/screener/{asset}/{window}

Drill into one (asset, window): the full L2 book on every venue side by side (books.polymarket / books.kalshi / books.limitless), plus the underlying spot series and the settlement price_to_beat — the single call a cross-venue backtest or arb screen actually needs.

GET/v3/overviewno auth

Per-asset, cross-venue time-series overview (price segments per window) — what powers the dashboard overview chart. Public, no key required; select with ?asset=.

Batch

POST/v3/batch

Run up to 10 GET /v3/ requests in one round-trip. Each sub-request is dispatched independently and gets its own status.

shell
curl -X POST https://api.depthfeed.com/v3/batch \
  -H "Authorization: Bearer df_your_key" -H "Content-Type: application/json" \
  -d '{ "requests": [
    { "id": "a", "method": "GET", "path": "/v3/btc/markets?limit=1" },
    { "id": "b", "method": "GET", "path": "/v3/limitless/markets?type=5m&limit=1" }
  ] }'

Returns { data: [ { id, status, body }, … ] } with an outer 200. Over 10 sub-requests → 400 BATCH_TOO_LARGE; a non-GET or non-/v3/ path gets a per-sub 400 BATCH_INVALID_PATH.

Live stream (WebSocket)

GET/v3/stream

A WebSocket that pushes live order books and prices as they change. Frame payloads are the same JSON objects the REST snapshot endpoints return, so code written against REST transfers directly. Authenticate at connect time with the X-API-Key header, Authorization: Bearer, or — for browsers, which cannot set WebSocket headers — ?api_key=df_….

shell
# wscat -c "wss://api.depthfeed.com/v3/stream?api_key=df_your_key"
> {"op":"subscribe","channels":["book:polymarket:btc:2510645","price:btc"]}
< {"op":"subscribed","channels":[…],"active":2}
< {"channel":"price:btc","data":{"coin":"btc","price":63560.1,…},"ts":1781300671083}
< {"channel":"book:polymarket:btc:2510645","data":{…same shape as REST snapshot…},"ts":…}

Channels

ChannelPayloadNotes
book:polymarket:<coin>:<market_id>REST snapshot object (with orderbooks)Tick-level via our CLOB websocket tap
book:kalshi:<coin>:<ticker>Same shape as /v3/kalshi/…/snapshots rowsFollows Kalshi's ~1.5s capture cadence
book:limitless:<coin>:<slug>Same shape as /v3/limitless/…/snapshots rowsPush-based (socket.io tap)
book:binance:<coin>:<spot|futures>Same shape as /v3/…/latest100ms depth feed
price:<coin>{ coin, price, source, venue, id, time }Binance underlying, ~4 ticks/s max

Ops: subscribe · unsubscribe (each takes {"channels":[…]}, applied atomically) and pingpong. A trailing * market segment (e.g. book:kalshi:btc:*) subscribes a whole venue/coin — Desk plan only. Op-level problems (bad channel, over your subscription cap) come back as {"op":"error","code":…} frames and never drop the connection.

Per-plan limits

PlanConnectionsSubscriptionsChannels
Explorer11BTC — Polymarket books + price
Quant15Polymarket books + prices, all coins
Desk Lite225Every venue
Desk5100Every venue + wildcards

Close codes & reconnecting

CodeMeaning
4001Authentication failed (missing / unknown / revoked key)
4003Plan connection limit reached
4029Op flooding — slow down
1013Key verification temporarily unavailable — retry shortly

The server heartbeats with protocol pings every 25s. Deploys and failovers drop connections by design — treat disconnect → reconnect with exponential backoff (250ms doubling to ~5s) and re-send your subscriptions as the normal lifecycle, not an error path.

Freshness, measured

Median capture→client delivery measured from an external client through our edge: Polymarket ≈10ms (p95 ≈30ms), Binance and Limitless sub-100ms, underlying price ≈110ms. Kalshi follows its REST capture cadence, ≈1s median. Numbers come from deploy/stream_freshness.py runs against production — we publish what we measure, nothing rounder.

Streamed messages are metered into your usage like REST responses. Subscriptions are limited per plan, and quotas are per user across all connections.

Venues & coverage

Precision comes from sourcing the same upstreams the markets use, so values match by construction.

VenueCaptureWindowsNotes
PolymarketCLOB websocket — every book + price-change event5m · 15m · 1h · 4h · 24hFull depth, event-driven. Settlement open/close from Polymarket's own metadata.
KalshiPublic REST, full-depth poll (~1.5 s)15m · 1h · 24h · 1wYes/no book, up to 100 levels/side, 7 assets; hourly ladders polled fastest.
Limitlesssocket.io websocket (orderbookUpdate)5m · 15mCLOB on Base; live push captures the fast 5m books REST can't snapshot.
Binancespot + futures @depth20@100ms + @aggTradeUnderlying book + 1s OHLCV, the precision anchor for the up/down markets.

All 7 assets (btc · eth · sol · xrp · doge · bnb · hype) across every venue that lists them.

Data model & schema

Timestamps are epoch-millis. exch_ts_ms = exchange time, recv_ts_ms = our receive time (the difference is capture latency). These are the fields every order-book snapshot returns over the API.

polymarket_book — full order-book snapshots

asset_id, condition_id, slug, base_asset, market_type, exch_ts_ms, recv_ts_ms, hash, bid_prices[], bid_sizes[], ask_prices[], ask_sizes[]

polymarket_changes — deltas for replay between snapshots

asset_id, condition_id, exch_ts_ms, recv_ts_ms, side, price, size

polymarket_markets — one row per token

asset_id, market_id, event_id, condition_id, slug, outcome, base_asset, market_type, clob_token_up, clob_token_down, resolution_source, start_time, end_time, first_seen_ms

polymarket_reference — settlement

slug, base_asset, market_type, start_ms, end_ms, price_to_beat, final_price, winner, final_volume, final_liquidity, resolved_at, captured_ms

binance_book — 20-level book (spot & futures)

venue, symbol, exch_ts_ms, recv_ts_ms, bid_prices[], bid_sizes[], ask_prices[], ask_sizes[]

binance_trades_1s — 1s OHLCV

venue, symbol, second_ms, open, high, low, close, volume, buy_volume, sell_volume, trades, recv_ts_ms

prices — unified underlying-price series

asset, source (binance|chainlink), venue, exch_ts_ms, price

kalshi_book / kalshi_markets

kalshi_book: ticker, series, base_asset, market_type, recv_ts_ms, yes_prices[], yes_sizes[], no_prices[], no_sizes[]

kalshi_markets: ticker, event_ticker, series, base_asset, market_type, title, status, strike, open_time, close_time, first_seen_ms

limitless_book / limitless_markets

limitless_book: slug, condition_id, base_asset, market_type, recv_ts_ms, midpoint, bid_prices[], bid_sizes[], ask_prices[], ask_sizes[]

limitless_markets: slug, condition_id, base_asset, market_type, title, status, expiration_ms, first_seen_ms

History & coverage

Every plan window is served from the live store plus the cold archive, so the full window is always available — not a forward-filling promise. Licensed historical depth extends the Polymarket and Kalshi archive back to January 2026; our own capture runs continuously on top of it.

Need a specific market or range backfilled? Desk plans get priority backfill requests — reach out on the contact page.

Code examples

Walk a market's full depth history (Python)

python
import requests

BASE = "https://api.depthfeed.com/v3"
H = {"Authorization": "Bearer df_your_key"}

# 1. find a market
m = requests.get(f"{BASE}/btc/markets?type=15m&limit=1", headers=H).json()["data"][0]
mid = m["market_id"]

# 2. page through its order-book snapshots
cursor, rows = None, []
while True:
    q = f"{BASE}/btc/markets/{mid}/snapshots?include_orderbook=true&limit=1000"
    if cursor: q += f"&cursor={cursor}"
    page = requests.get(q, headers=H).json()
    rows += page["data"]
    if not page["pagination"]["has_more"]: break
    cursor = page["pagination"]["next_cursor"]

print(len(rows), "snapshots")

Latest cross-venue depth for BTC up/down (JavaScript)

javascript
const h = { Authorization: "Bearer df_your_key" };

// One call → the full BTC 15m book on all three venues at once.
// (No stitching: the screener is the cross-venue entry point.)
const res = await fetch("https://api.depthfeed.com/v3/screener/btc/15m", { headers: h }).then(r => r.json());
const { books } = res.data;        // books.polymarket / books.kalshi / books.limitless

AI agents & LLMs

DepthFeed is built to be driven by agents: plain JSON over HTTPS, one Bearer key, stable error codes, and no SDK required. A machine-readable product summary lives at /llms.txt.

As a function-calling / MCP-style tool

Wrap any endpoint as a tool — the API is self-describing enough that one generic definition covers most workflows:

json
{
  "name": "depthfeed_get",
  "description": "Query DepthFeed prediction-market order-book data. Paths: /v3/{coin}/markets, /v3/{coin}/markets/{id}/snapshots, /v3/kalshi/markets, /v3/kalshi/{ticker}/snapshots, /v3/limitless/{slug}/snapshots, /v3/{coin}/{spot|futures}/latest. Coins: btc eth sol xrp doge bnb hype.",
  "parameters": {
    "type": "object",
    "properties": { "path": { "type": "string", "description": "GET path under /v3, with query params" } },
    "required": ["path"]
  }
}

The tool body is a single authenticated GET:

shell
curl "https://api.depthfeed.com{path}" -H "Authorization: Bearer df_your_key"

Live data in agents

The WebSocket stream uses three JSON ops (subscribe / unsubscribe / ping) and authenticates with ?api_key=where headers can't be set — trivial to drive from any runtime. Frames carry the same JSON objects as REST, so an agent's parsing code is identical for history and live.

Tip for assistants: /v3/whoamiechoes the key's plan, rate limits, and history window — call it first and self-configure instead of guessing limits.

Status & changelog

What's live, newest first:

  • Live streaming. /v3/stream WebSocket — order-book and price channels on every venue, ~10ms median Polymarket delivery, plan-gated subscriptions.
  • Limitless venue. Markets, latest orderbook, and historical depth snapshots — with 5m + 15m captured live over the order-book websocket.
  • Kalshi expanded. 21 series for all 7 assets (15-minute, threshold, and directional — the latter two running hourly/daily/weekly concurrently); market_type exposed and filterable.
  • Full v3 API. Polymarket markets + snapshots, Binance spot/futures, batch, cursor pagination, per-plan history enforcement, metered usage.
  • Public HTTPS. https://api.depthfeed.com over TLS.

Order-book depth fills forward from capture start and cannot be back-filled — history matures toward your plan window over calendar time. Questions or a backfill request? Get in touch.