Base URL
All paths are relative tohttps://data.kairos.trade.
Authentication
Every endpoint on this page is marked with the auth mode it accepts and its rate limit, for examplex-kairos-auth: api-key · 200 req/min.
x-kairos-auth: api-key means you send three headers together:
All three are required.
X-Client-Id sent without both X-Api-Key and X-Api-Secret is a 401, as are invalid credentials. API keys are IP-whitelisted: a key used from a non-whitelisted IP is a 403. API-key callers bypass the invite_only gate that applies to session-authenticated callers.
One endpoint — equity/forex/commodity snapshot — uses x-kairos-auth: session instead and rejects API-key headers. See that section.
Examples below read credentials from KAIROS_CLIENT_ID, KAIROS_API_KEY, and KAIROS_API_SECRET in your shell; the one session-authenticated example reads KAIROS_SESSION_JWT.
Price scales
Price scale is the most common source of bugs on this page: some endpoints return a 0–1 decimal probability, one returns cents, and one discover endpoint mixes the two — its filters are cents while its response is a decimal. This table collects what each endpoint section states; the per-endpoint notes stay where they are.Active markets snapshot
x-kairos-auth: api-key · 200 req/min
Request
Response
Apart from
provider and source, the body is the metadata cache’s own page payload passed through unchanged.
Market details lookup
market_id / condition_id / token_id rows for a batch of (market_id, provider_id) pairs — market_id in the request matches any of the three identifiers. Unmatched markets are simply absent from the response; there’s no found: false sentinel here (contrast with batch metadata).
x-kairos-auth: api-key · 100 req/min (global default — no per-endpoint limit)
Request
Response
token_ids and outcomes are 1:1 lists of every on-chain CTF token this market has — CTF is the on-chain conditional-token contract each outcome share is minted under. Index 0 is YES / Up / first outcome, index 1 is NO / Down / second outcome, and so on for multi-outcome markets. The singular token_id is retained for back-compat and holds the first token only.
Gotcha:token_idsandoutcomesare both empty when the market has no on-chain tokens yet (indexer lag). Check for a non-emptytoken_idsbefore submitting an order.
Gotcha:markets[].market_idin the response is the canonical market id, which is not necessarily the identifier you asked with — a Polymarket lookup bycondition_idcomes back keyed on the numeric Gamma id. Re-key using the returnedcondition_id/token_id/token_idsrather than assuming the request id round-trips.
Batch prices
(market_id, provider_id) pairs, with responses briefly cached. Every reference must include a non-empty market identifier and known integer provider ID. Venues without batch-price support are skipped — their markets are simply absent, not an error.
x-kairos-auth: api-key · 200 req/min
Request
Response
Flat object keyed by the requestedmarket_id, no wrapper:
Tick size
Retired. Tick grids are served by the Market Data API at
GET /v1/markets/tick-size, which also has a batch variant and needs no API key. The request parameters (provider, contract_id, asset_id) and the response body are the same, so moving an integration is a base-URL change.Market metadata
resolution_rules, an extra provider-API call backfills rules/description without discarding the rest of the document.
For polymarket/predictfun, a best-effort liquidity-rewards enrichment also mutates extra in place.
x-kairos-auth: api-key · 100 req/min (global default — no per-endpoint limit)
Gotcha: Only the primary indexed-record path populates
condition_id, event_id, and contract.settlement_ts. The faster Polymarket path and every provider-API fallback leave those null — a null here does not mean the market lacks one.Request
Response
404 only when no source — cache nor any provider API — has the market at all.
Batch market metadata
titles_only: true, three best-effort enrichment passes run after lookup (each swallows its own errors): API fallback for still-unfound markets, category inference from ticker/title patterns, and platform tag-icon enrichment. The single-market endpoint’s Polymarket rewards enrichment is intentionally not run here — this feeds list views where the rewards badge doesn’t render.
x-kairos-auth: api-key · 100 req/min (global default — no per-endpoint limit)
Request
Response
Keyed by requested ticker; every requested ticker appears,found: false for unresolved ones.
Market outcomes
market_id belongs to, sourced from the discover cache. If the event can’t be resolved and provider=polymarket, falls back to a live provider lookup; other providers get no such fallback and return the empty shape.
x-kairos-auth: api-key · 100 req/min (global default — no per-endpoint limit)
Gotcha: Outcome prices here are a 0–1 decimal probability, not the platform’s usual 0–100 cents scale. The cache stores cents and the handler divides by 100 before serving.
Request
Response
is_grouped is always true.
Crypto markets
window_offset shifts by whole windows of interval (0=current, -1=previous, +1=next). Past windows are cached immutably; current/future windows use a short cache.
x-kairos-auth: api-key · 200 req/min
Gotcha:
price is a raw 0–1 decimal probability read from each venue’s order book.Request
Response
Crypto oracle history
[end_ms - minutes*60000, end_ms], for chart pre-population. Each request names one source so settlement feeds are never mixed. Binance gaps may be backfilled from Binance REST; venue-specific sources remain empty when their stored feed has a gap.
x-kairos-auth: api-key · 200 req/min
Source identities
Every source publishes underprovider: "oracle" on the market-data WebSocket, so the wire symbol is the identity. Logical assets are btc-usd, eth-usd, sol-usd, xrp-usd, doge-usd, hype-usd, bnb-usd.
Request
Response
Keyed by symbol, ascending by timestamp:Gotcha: Only Binance has external backfill. A gap in a venue series (-polymarket-*,-kalshi-cfb,-hyperliquid-mark) stays a gap — Binance klines are a different series and are never written under another source’s contract id — so a symbol with nothing in the local store comes back as an empty array rather than being filled.
Gotcha: Mixing wire symbols from two sources in one request (or omittingsourcewhen the symbols do not identify exactly one) is a400, not a merged response.
Crypto price-to-beat
{window: {symbol: {...}}}. Window starts align to clean ET boundaries. Symbols with no resolvable price are omitted rather than filled from a different source.
x-kairos-auth: api-key · 200 req/min
Request
Response
Symbols with no resolvable price for a window are omitted from that window’s object, not returned as null.
Equity/forex/commodity snapshot
cached: false (never a merge of cached + fresh in one response). Returns the last regular-session print even when markets are closed.
x-kairos-auth: session · 200 req/min
Gotcha: auth differs from every other endpoint on this page. This route accepts a first-party session JWT or the internal admin secret, and does not accept the
X-Client-Id/X-Api-Key/X-Api-Secret headers the rest of /markets/* accepts. An API key clears the router’s invite gate and is then rejected by the route’s own auth dependency with 401.Request
Response
A symbol whose upstream fetch fails is dropped from
prices — the request still returns 200, so check for the key rather than assuming every requested symbol is present.
Discover markets
search/min_price/max_price/min_volume_1h/market_ids/tag_ids) are served from cache; requests with any of those filters always run fresh and are never cached. Tag/subcategory filters that resolve to zero markets short-circuit to an empty payload; an empty tag-filtered result also gets one fallback query so populated subtopics never render empty.
x-kairos-auth: api-key · 60 req/min
Request
Response
Discover ticker feed
x-kairos-auth: api-key · 60 req/min
Request
Response
markets[] (id, title, provider, price — 0–1 decimal, volume1h, token_id), count, timestamp.
Discover breaking markets
x-kairos-auth: api-key · 60 req/min
Request
Response
markets[] (id, ticker, title, provider, price — 0–1 decimal, volume1h, priceChange24hSigned, token_id, condition_id, image, icon, category), count, timestamp.
Discover expiring markets
x-kairos-auth: api-key · 60 req/min
Request
Response
markets[] (id, ticker, title, provider, price — 0–1 decimal, volume1h, volume24h, volume, expiration, token_id, condition_id, category, image, icon, isGrouped), count, timestamp.
Discover subcategories
discover:subcats:<category>) — the endpoint does no tag resolution of its own. The frontend display aliases (elections, geopolitics, economy, climate & science) are remapped to their canonical category before the index lookup.
x-kairos-auth: api-key · 60 req/min
Request
Response
category echoes back the requested (lowercased) value, not the canonical one it was aliased to. count is approximate and may run slightly higher than the post-grouping total shown on the cards page.
Gotcha: An unknown category is a
503, not a 404 — the endpoint can’t distinguish “no such topic” from “the cron hasn’t built that index yet”.Discover search index
x-kairos-auth: api-key · 60 req/min
Request
No parameters.Response
markets[] (grouped rows carry outcomes[]; single rows carry token_id), total, timestamp.
Trending markets
x-kairos-auth: api-key · 60 req/min
Request
Response
price is a 0–1 decimal. timestamp is the server time the response was built, not a cache-build time.
Trending markets (WebSocket subscription list)
x-kairos-auth: api-key · 60 req/min. Not present in the OpenAPI spec — no live-tester link for this one.
Gotcha:
price here is cents (0–100), the raw cached value — this is the one endpoint on this page that does not divide by 100. /api/markets/trending returns the same field as a 0–1 decimal.Request
Response
Kalshi live sports (discover)
games is supplied, matches each AWAY:HOME[:league] triple’s team codes against each event’s ticker suffix, grouping and sorting matches by total volume descending. Documented here alongside the rest of this page’s crypto/discovery endpoints.
x-kairos-auth: api-key · 60 req/min
Request
Response
200 with {"events": [], "matched": []}, not an error.
Errors
Every error on this page is{ "detail": "<message>" }, except 429, which is { "error": "Rate limit exceeded: <limit>" } and carries Retry-After / X-RateLimit-* headers. Unhandled failures are 500 {"detail": "An internal error occurred. Please try again later."}.
This service has no separate machine-readable code field, so the Code column below holds the example detail message you’ll see.
Rate limits above are the group defaults; admin-managed tiers can raise or lower any group at runtime without a deploy, so treat the documented numbers as the baseline and the
X-RateLimit-* response headers as authoritative. Endpoints marked “global default” have no per-endpoint limit and are not group-tunable. A 429 does not consume quota.
Note the endpoints on this page that return an empty 200 instead of an error: /markets/outcomes (unresolvable event), /markets/metadata/batch (found: false), /markets/batch-prices (venues without batch-price support omitted), /api/sports/kalshi-live (cold cache), and both trending endpoints (empty ranked set).
