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 — recorded full bid/ask ladders on both sides for Polymarket, Kalshi, and Limitless. Not just the last trade price or top of book: each stored observation includes resting levels and sizes. 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 separate general-admission and historical-workload controls. 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).

The Desk plan also bundles realtime sports— live Polymarket & Kalshi books, sportsbook odds, scores and injuries across the major leagues. Jump to the Sports endpoints.

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. Our own capture runs live, and licensed historical depth makes the longest-running Polymarket series available from January 2026. Exact per-series archive floors are listed under History & coverage. Every plan window is backed by stored data. 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", "sports": false
  },
  "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.
MARKET_TICKER_REQUIRED400A Kalshi series was passed where an exact discovered market ticker is required.
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.
HISTORY_CONCURRENCY_LIMIT429Another snapshot or batch history request is still running for this account.
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.

The advertised rps/rpm values are general REST admission limits, not archive-delivery rates. Historical snapshots, batches containing history reads, and other heavyweight routes use separate account-level concurrency and delivery controls. These controls apply independently of the general token bucket and do not change the plan's history window.

Explorer, Quant, and Research currently accept one historical request in flight per account. Desk accepts 2 parallel historical snapshot requests per account through its dedicated Desk query pool. An overlap returns 429 HISTORY_CONCURRENCY_LIMIT with Retry-After: 2; retry only after an active request completes. General rps/rpm values must not be used to infer historical parallelism.

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.

Historical query pattern

Keep no more than your confirmed history concurrency active. Use bounded start_time andend_time, cursor pagination, and limit=1000; omit include_count and request the full ladder only when needed. Add interval when a downsampled series is sufficient. DepthFeed is a metered query-access product: bulk files, offline archive delivery, database replication, and systematic archive mirroring are not included.

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 the raw stored series
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.

PlanplanPriceGeneral rpsGeneral rpmHistorical parallelismUnified historyWallet IntelligenceCryptoSports RESTLive sports books
Explorerfree$0117 days1 saved · 3 auditsBTC sampleAll sports venuesREST only
Quant pro$49/mo251,000130 days5 saved · 10 auditsAll assets + venuesAll sports venues1
Researchscale$149/mo503,000190 days10 saved · 25 auditsAll assets + venuesAll sports venues2
Deskenterprise$399/mo1006,0002 parallelFull archive20 saved · 50 auditsAll; dedicated Desk historical query poolAll sports venues3

There are no Polymarket or Kalshi add-ons. Both sports venues use the same key, schema, rate limit, and history window; upgrading buys more history, throughput, and live-book concurrency.

The General rps/rpm columns describe request admission, not simultaneous archive scans. Historical query parallelism and delivery controls are separate. Desk historical reads use a dedicated Desk-only query pool isolated from regular-plan query traffic, without removing account-level controls. The pool is shared across Desk accounts and is not customer-owned or account-exclusive infrastructure.

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.
  • Sports — the /v3/sports/* REST surface is included on every plan; the same plan history window applies to both venues.
  • Historystart_time beyond your window → 403 HISTORY_LIMIT_EXCEEDED.
  • Streaming — limits apply at subscribe time on /v3/stream; Quant and up stream every venue, Explorer streams Polymarket + Binance (BTC) — Kalshi and Limitless channels require a paid plan.

Health & identity

GET/v3/healthno auth

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

GET/v3/whoami

Your plan, rate limits, unified history window, coin access, and sports 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 the raw stored series — 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": { … } }
Binance doesn't deliver futures aggTrade over the websocket to our region (depth streams fine), so the futures 1s trade tape is polled from the REST aggTrades endpoint and aggregated to the same 1s OHLCV as spot. Spot and futures trades, and all books, are live.

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), ?type= (window), and exact ?series= (for example KXBTC15M). For historical downloads, pass start_time and end_time here first and use the returned venue-native tickers. Do not generate Kalshi ticker ids from UTC timestamps; the venue's ticker clock convention changed historically.

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 exact discovered market ticker — same row shape, ordered by receive time, time-windowed + cursor-paginated (include_count opt-in, max 1000). The forward-captured Kalshi book history from a paced REST polling loop. Effective cadence varies with the active market set and API limits; it uses the same historical endpoint pattern as Polymarket and Limitless /snapshots, so Kalshi depth is backtestable too. Passing a series such as KXBTC15M, or an invented historical ticker, returns an explicit discovery error instead of a misleading empty page.

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.

Binance prediction markets

Binance Wallet's Predict.fun-backed crypto prediction markets, normalized into a dedicated DepthFeed namespace. The initial catalogue covers BTC, ETH, and BNB up/down markets. Paid plans only.

GET/v3/binance-prediction/marketspaid plan

Filter with ?coin=btc, ?type=5m, or ?status=resolved. Results include the market/topic IDs, condition and token metadata, resolution, winning outcome, volume, liquidity, participant count, chain, and exchange contract.

GET/v3/binance-prediction/{market_id}/orderbook/latestpaid plan
GET/v3/binance-prediction/{market_id}/snapshotspaid plan

Latest and historical full L2 depth. Snapshot history is forward-captured from 17 July 2026; an earlier resting book cannot be reconstructed from settlement data.

GET/v3/binance-prediction/{market_id}/timeseries?metric=chancepaid plan
GET/v3/binance-prediction/{market_id}/timeseries?metric=pricepaid plan
GET/v3/binance-prediction/{market_id}/timeseries?metric=last_tradepaid plan
GET/v3/binance-prediction/{market_id}/tradespaid plan

Probability, displayed price, and last-trade samples are kept separately and begin on 17 July 2026. The trades route is reserved while historical fills are reconstructed from BNB Smart Chain logs and currently returns an empty historical dataset.

Deterministic 5-minute and 15-minute catalogue, resolution, volume, and liquidity history is backfilled from 5 May 2026. The equivalent /v3/predictfun/* paths remain compatible aliases. Customers use a DepthFeed key; no Binance key or wallet pairing is required.

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.

Sports

Realtime sports prediction-market data — live order-book depth on Polymarket and Kalshi, alongside sportsbook odds, live scores, and an injury feed across the major leagues (NBA, NFL, MLB, NHL, soccer, tennis, UFC, F1 and more). Both venues are included together on every tier; plans change the shared history window, throughput, and live-book concurrency. Same{ data, meta, pagination } envelope, auth, and cursor pagination as the rest of the API.

Discovering a market. Walk the funnel: /v3/sports/leagues/v3/sports/markets?league=… → take a market's tokens[](each is one outcome's asset_id) → /v3/sports/books/{asset_id}/latest for the live book. Or start from /v3/sports/overview, which answers “what's trading now, on every venue” in one call.

GET/v3/sports/overview

Start here. The live cross-sport board — every tracked league with its in-progress and upcoming games, current prices, and best bid/ask per venue, in a single request.

GET/v3/sports/leagues

The leagues we track, each with its game and market counts — the top of the discovery funnel.

GET/v3/sports/markets

Sports markets across Polymarket and Kalshi. Filter with ?league= (e.g. nba, mlb, soccer); cursor-paginated like every list endpoint (?limit=, ?cursor=). Each market carries its condition_id, market_slug, outcomes, and tokens — the per-outcome asset_ids you hand to the book endpoint.

json
{ "data": [{
  "condition_id": "0xfb53…", "market_slug": "mls-nyc-laf-…-total-2pt5",
  "league": "soccer", "kind": "totals", "title": "New York City FC vs. Los Angeles FC",
  "outcomes": ["Over", "Under"],
  "tokens": ["45485059…", "38846626…"],   // one asset_id per outcome
  "game_start": "2026-11-05T00:30:00Z", "resolved": false
}], "pagination": { "next_cursor": "…", "has_more": true, "limit": 50 }, "meta": { … } }
GET/v3/sports/books/{asset_id}/latest

Newest recorded full order book for one outcome — the asset_idis a token from the market'stokens[]. Same [price, size] bid/ask ladder shape as the crypto book endpoints. For latency-sensitive live use, Quant and higher tiers can subscribe to the sports WebSocket channels below.

GET/v3/sports/books/{asset_id}/history

Historical full-ladder snapshots for the outcome. Page with ?limit= and ?cursor=; bound time with ?start_time= / ?end_time= (the shorter ?from= / ?to= aliases are also accepted). Add ?interval=1m to return the latest snapshot in each epoch-aligned bucket; supported units are s, m, h, and d, from one second through one day. Omit it, or useraw / tick, for every captured change. Sports depth is forward-captured: the Polymarket archive starts 14 April 2026 and the Kalshi archive starts 12 June 2026.

Games and resolved market context

GET/v3/sports/{league}/games

Live games and scores for a league (e.g. nba, nfl, soccer/eng.1), each with its linked Polymarket & Kalshi markets.

GET/v3/sports/games/{game_slug}

The joined game document: schedule and final score, linked prediction markets and settlements, sportsbook lines, and injury context. Use the companion routes below when you need an individual high-volume layer.

GET/v3/sports/games/{game_slug}/markets
GET/v3/sports/games/{game_slug}/lines
GET/v3/sports/games/{game_slug}/box
GET/v3/sports/games/{game_slug}/plays
GET/v3/sports/games/{game_slug}/winprob

Game markets, line movement, box scores, play-by-play, and per-play win probability.

GET/v3/sports/markets/{condition_id}

One normalized market with venue identifiers, outcomes, token IDs, game join, and settlement state.

Players, props, and injuries

GET/v3/sports/{league}/players

Search the league athlete directory and retrieve stable athlete IDs used by player-prop joins.

GET/v3/sports/players/{athlete_id}
GET/v3/sports/players/{athlete_id}/injuries
GET/v3/sports/players/{athlete_id}/box
GET/v3/sports/players/{athlete_id}/markets

Player profile, injury change-log, box-score game log, and entity-resolved prediction-market props.

GET/v3/sports/{league}/injuries

The live injury feed per league — the pre-game status changes that move the market.

Sportsbook odds

GET/v3/sports/odds/lines

Live moneyline, spread, total, and prop lines across books, normalized for comparison with the market price.

GET/v3/sports/odds/books

The active sportsbook catalog and source freshness.

GET/v3/sports/{league}/odds-history

Historical sportsbook lines, including NFL history to 1999 and European soccer to the 2000/01 season. Bound NFL requests with season, team, from, or to. Soccer requests require a football-data season code (for example 2324) and/or team.

GET/v3/sports/odds/stream

Server-Sent Events for changing sportsbook lines. Send Accept: text/event-stream; events pass through as they arrive and the connection remains open. Sports order books use the main DepthFeed WebSocket below.

Injury webhooks

POST/v3/sports/webhookspaid plan

Register an HTTPS receiver with league and injury-status filters. The signing secret is shown once. Deliveries include X-DepthFeed-Event and X-DepthFeed-Signature; verify the HMAC-SHA256 signature over the exact raw request body before parsing JSON.

shell
curl -X POST "https://api.depthfeed.com/v3/sports/webhooks" \
  -H "Authorization: Bearer df_your_key" -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/depthfeed","leagues":["nba","nfl"],"statuses":["out","questionable"]}'
GET/v3/sports/webhookspaid plan
POST/v3/sports/webhooks/{sub_id}/testpaid plan
DELETE/v3/sports/webhooks/{sub_id}paid plan

List subscriptions and delivery health, send a signed test event, or revoke a subscription.

shell
# discover a market, then pull its live book
curl "https://api.depthfeed.com/v3/sports/markets?league=mlb&limit=1" -H "Authorization: Bearer df_your_key"
# take tokens[0] from the response, then:
curl "https://api.depthfeed.com/v3/sports/books/<asset_id>/latest" -H "Authorization: Bearer df_your_key"

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 rowsUpdates from the paced Kalshi polling loop
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
book:sports:polymarket:<token_id>Full sports ladderQuant+: first-party, event-driven CLOB stream
book:sports:kalshi:<ticker>Full sports ladderQuant+: best-effort adaptive public REST; change-only frames
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.

Sports channels use concrete identifiers and do not support wildcards. Quant, Research, and Desk allow one, two, and three concurrent sports books respectively. Every sports frame includes the complete ladder, venue, asset_id, exchange/receive timestamps, full_ladder: true, and adeliveryfield that distinguishes event-driven Polymarket from Kalshi's adaptive REST snapshots. Kalshi's credential-free public endpoint is globally paced and backs off automatically when the upstream quota is busy. It starts with a 125ms shared polling floor; multiple active books and upstream throttling increase the actual interval.

shell
> {"op":"subscribe","channels":[
    "book:sports:polymarket:<token_id>",
    "book:sports:kalshi:<market_ticker>"
  ]}
< {"op":"subscribed","channels":[…],"active":2}

Per-plan limits

PlanConnectionsSubscriptionsChannels
Explorer11BTC — Polymarket + Binance books + price
Quant15Every venue, all coins; 1 sports book
Research225Every venue; 2 sports books
Desk5100Every venue + wildcards; 3 concurrent sports books

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. A scoped, automatically expiring 7-day Desk evaluation is available on request for production-latency validation.

Wallet Intelligence

Wallet Intelligence is a read-only research workspace for public Polymarket wallets. Save a watchlist, discover traders from Polymarket's public leaderboard, and review public positions, recent activity, realized samples, and portfolio-level metrics in one place. It never connects a wallet, signs a transaction, or places a real order.

Next-book execution audit

For each eligible public trade, DepthFeed finds the first Polymarket book it recorded after the activity timestamp, walks the displayed ladder for the same number of shares, and reports the replay price, fillable fraction, observed delay, and signed price difference versus the public trade. The lookup window is 90 seconds. A missing match is shown as missing; it is never estimated.

Grades are mechanical: Depth remainedmeans at least 95% of the public size was displayed within 1¢ of the trader's price; Price moved means at least 95% remained but at a difference above 1¢; Size unavailable means less than 95% of the public size was displayed.

Forward paper copy

Start a paper mirror from any inspected wallet. Only public trades observed after the mirror is created are eligible: DepthFeed deduplicates each fill, applies the configured copy ratio and per-trade cap, then fills it at the next available live quote in the normal Paper Trading ledger. Cash, positions, P&L, the equity curve, circuit breaker, and settlement history appear under Paper Trading.

An optional HTTPS callback receives each successful copied fill. Its signing secret is shown once. Verify HMAC-SHA256(timestamp.body) against x-depthfeed-signature; the timestamp is sent in x-depthfeed-timestamp. Local, private-network, credential-bearing, non-HTTPS, and redirect destinations are rejected.

PlanSaved walletsAudited trades per refreshPublic activity rows
Explorer1330
Quant510100
Research1025250
Desk2050500

Interpretation limits

  • A public address may be only one wallet in a trader's portfolio and does not prove identity or ownership.
  • Public activity timestamps are not private order timestamps. The audit measures what DepthFeed observed after publication, not the trader's original latency.
  • Only trades in DepthFeed's recorded Polymarket coverage can be matched. Unsupported or uncaptured markets are shown without an audit.
  • The replay consumes displayed size mathematically; it cannot model hidden liquidity, queue priority, cancellation races, fees, or the market impact of a real follower order.
  • Leaderboard rank, P&L, positions, and activity come from Polymarket's public data services and may be delayed, revised, incomplete, or temporarily unavailable.
  • Wallet Intelligence and its paper mirror are research tooling—not live copy trading, investment advice, a recommendation, or a guarantee of execution.
Only watchlist addresses and user-authored labels are stored by DepthFeed. Public wallet data is fetched on demand and briefly cached; execution audits are computed against our recorded order books at request time.

Wallet research guides

Start with the Polymarket wallet tracker guide, then compare wallet analytics, leaderboard research, and copy-trading execution analysis.

Backtest Lab

The Backtest Lab (in your dashboard) backtests entry/exit strategies on resolved native Polymarket, directional Kalshi, and Limitless crypto markets — settlement-anchored, so every simulated trade has a known outcome. It runs on the same order-book history the API serves, within your plan's history window.

Venues and sampling

Polymarket supports 5m, 15m, 1h, 4h and 24h windows. Limitless supports captured 5m and 15m up/down contracts. Kalshi supports the captured directional 15m, 1h and 24h series; range buckets are excluded because YES does not mean UP. Kalshi defaults to one representative directional contract per event so a ladder of correlated strikes is not counted as independent evidence. Advanced users can inspect all strikes with an explicit correlation warning.

Strategies

Five built-in presets (late-favorite, spot-leads, dip-reversion, level-cross, cheap-lotto) plus a custom JavaScript editor: your script plans entries over each market's price path and runs sandboxed in a web worker — no network, hard time budget, stored locally in your browser and exportable as JSON.

Fill models

ModelEntry price
MidThe snapshot mid — fastest, most optimistic.
Mid + slippageMid shifted by a fixed slippage you set.
Book-depth VWAPWalks the real ask ladder level by level. Missing or one-sided depth is unfillable; it never falls back to a modeled midpoint.

Fees are included in sizing and net P&L. Polymarket and Limitless use an editable flat per-share assumption; Kalshi uses its non-linear expected-earnings formula with an editable rate and cent rounding per order.

Portable exports

Export the complete trade log as CSV, the strategy and execution assumptions as portable JSON, or a reproducible run bundle containing the exact tested sample, statistics, risk report, equity curve and trades. Exports never embed raw historical paths or order-book archives.

Position sizing

How much each trade stakes — a flat amount, or a fraction of a compounding bankroll:

SchemeStake per trade
FixedA flat dollar amount — simple, but the only scheme that can trade a bankroll to zero.
FractionalA constant fraction of your live bankroll (fixed-fractional). It compounds and can't reach zero from sizing alone.
KellyGrowth-optimal f* = (q − p)/(1 − p) for a $1 binary at price p, scaled by a fractional-Kelly multiplier (half-Kelly = the standard hedge) and capped per trade. The win probability q comes from a fixed edge, a fixed win probability, or the strategy's own trailing hit rate. No edge (f* ≤ 0) ⇒ the entry is skipped.

Risk of ruin

Every run reports a risk panel derived from its own trades: the optimal fraction your edge can support (Ralph Vince optimal-f), a recommended max (half of it), a Monte-Carlo risk of ruin (the chance the bankroll ever falls to ≤30% of its start), and an over-bettingwarning when you're staking past the growth-optimal point — where more risk buys less long-run growth. Deploying to paper auto-caps the live per-trade size at this safe fraction.

Results: trade log, win rate, ROI, Sharpe, max drawdown, the equity curve, and the risk-of-ruin panel. Paid plans can save up to 50 frozen runs (they re-render identically later, no data re-reads), and the built-in AI assistant helps write and debug strategies and interpret sizing and risk within a plan-metered allowance.

When a backtested rule looks good, deploy it to Paper Trading to forward-test it on live markets with virtual cash.

Paper trading

Paper Trading runs strategies forward on livemarkets with virtual cash. Fills, marks and settlement are all priced from DepthFeed's live order books — buys at the ask, sells at the bid, positions settle to $0/$1 automatically when the market resolves. Each strategy gets its own equity curve, positions view, and full trade log.

Three ways to trade

ModeHow it works
WebhookYour own system (bot, cron, notebook) POSTs buy/sell signals to a per-strategy token URL. Your logic stays yours — we do execution, accounting and charts.
Lab ruleDeploy a Polymarket or Kalshi Backtest Lab preset (time-window entry, level cross, dip reversion) with venue-native sides, take-profit/stop-loss, a max-open cap, and position sizing (fixed / fractional / Kelly); it's evaluated server-side against live quotes (~90s cadence).
Wallet copyMirror new public fills from an inspected Polymarket wallet with a copy ratio and per-trade cap. Results use the same paper ledger and may optionally emit signed HTTPS fill webhooks.

Signal webhook

POST/paper/hook/{token}no auth

The token (shown once at create/rotate) is the auth. Fills always price from the live book at signal time — a payload can never set its own price. Markets are identified by venue + market: a Kalshi ticker, or a Polymarket CLOB token id. You can trade any market on the venue, not just the ones DepthFeed records — if we don't have it locally, the fill is priced from a live read of the venue's own order book.

shell
curl -X POST 'https://api.depthfeed.com/paper/hook/pt_your_token' \
  -H 'content-type: application/json' \
  -d '{
    "action": "buy",              # buy | sell | close
    "venue": "polymarket",        # polymarket | kalshi
    "market": "1234567890...",    # CLOB token id / Kalshi ticker
    "side": "yes",                # kalshi: yes|no (polymarket tokens are one-sided)
    "usd": 100,                   # size by dollars… or "shares": 150
    "client_id": "sig-0042"       # optional idempotency key (safe retries)
  }'
json
{ "data": { "filled": true, "action": "buy", "price": 0.62,
            "shares": 161.29, "cost_cents": 10000, "cash_cents": 990000,
            "position_id": "…" } }
ErrorMeaning
NO_FRESH_QUOTENo live book for that market — a bad id, or the market has closed / gone one-sided at 0/1 (settlement closes positions automatically).
INSUFFICIENT_CASHThe order exceeds the strategy's paper cash.
NO_POSITIONsell/close with no open lot on that market/side.
RATE_LIMITEDOver 120 signals/min for the strategy.
PAUSEDThe strategy is paused in the dashboard.

Circuit breaker

Each strategy has a trailing max-drawdown stop (default 60%, editable; set to 0 to disable). If live equity ever falls that far below its high-water mark, the strategy is automatically flattened at current marks and halted — a hard stop against a strategy trading itself toward zero. Resume it any time; resuming resets the high-water mark to your current equity.

Limits

Concurrent strategies per plan: Explorer 1 · Quant 5 · Research 15 · Desk 40. Up to 100 open positions per strategy; starting balance $100–$1,000,000 (default $10,000). Marks refresh on a ~90-second cadence — this is a forward-testing tracker, not an execution venue.

Paper results use real displayed liquidity for pricing but don't consume it — live fills of size may see more slippage than the paper fill at top-of-book. Markets we don't record locally are priced from a live venue read and won't re-settle from our resolution data — they close at their last mark after a few days if the venue doesn't resolve them through a path we track.

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, paced full-depth polling15m · 1h · 24h · 1wYes/no book, up to 100 levels/side, 7 assets; effective cadence varies with market load and API limits.
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. Desk has no rolling history cap: it can query every recorded snapshot from the applicable series floor through the live feed. The floors differ because contracts and licensed capture did not begin on the same day for every asset/window combination.

Polymarket full-depth archive floors (UTC)

Assets5m15m1h4h24h
BTC2026-02-122026-01-012026-01-012026-01-012026-01-01
ETH, SOL, XRP2026-02-182026-01-012026-01-012026-01-012026-01-01
BNB2026-03-132026-03-132026-03-062026-03-132026-03-07
DOGE2026-03-132026-03-132026-03-112026-03-132026-03-11
HYPE2026-03-132026-03-132026-03-062026-03-132026-03-07

These are the earliest days with recorded full ladders, not a claim that every asset/window existed before its floor. A snapshot returns the complete recorded ladder; it can legitimately contain no levels when the market itself had no resting orders at that instant.

Order-book depth is captured live and cannot be recreated after the fact. Archive access is delivered through the documented metered query surfaces; DepthFeed does not provide customer-requested reconstruction or bulk archive delivery.

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.

Start backtesting Polymarket & Kalshi on real depth.

Free to start, no card. Upgrade when your strategy is ready for the full book.

Start free