Skip to main content
Market lookups, batch pricing and metadata, discovery feeds, and crypto-specific endpoints. Reach for this page when you need to resolve a market identifier, read a current price, or build a browse or search surface. Full parameter reference and a live tester: API Reference.

Base URL

All paths are relative to https://data.kairos.trade.

Authentication

Every endpoint on this page is marked with the auth mode it accepts and its rate limit, for example x-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

Cursor-paginated page of the canonical active-market snapshot for one provider — a live cache, not a historical catalogue. For ranked, filtered, or text-search results use Discover instead. 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.
Gotcha: 503 means the snapshot couldn’t be read (cache not ready, or unreachable) — never an empty page. Do not treat it as “no active markets”.

Market details lookup

Looks up 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_ids and outcomes are both empty when the market has no on-chain tokens yet (indexer lag). Check for a non-empty token_ids before submitting an order.
Gotcha: markets[].market_id in the response is the canonical market id, which is not necessarily the identifier you asked with — a Polymarket lookup by condition_id comes back keyed on the numeric Gamma id. Re-key using the returned condition_id/token_id/token_ids rather than assuming the request id round-trips.

Batch prices

Current price/volume/liquidity for up to 300 (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 requested market_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

Full metadata for one market — resolution rules, contract spec, images. Resolution order: (1) an indexed record, with a faster path for Polymarket; (2) on a miss, a live provider-API fetch (covers markets too new to be indexed, e.g. short-lived 15-minute crypto markets); (3) if the resolved document has empty 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

Batch variant of market metadata, capped at 100 contracts. Contracts whose provider is hidden in admin are dropped first. Unless 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.
Gotcha: Contracts on a hidden provider also come back as {"ticker": "...", "found": false} — a settled answer, not a lookup failure, so don’t retry them.

Market outcomes

Every outcome in the event that 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

On the populated path is_grouped is always true.
Gotcha: An unresolvable event is a 200 with the empty shape {"event_title": null, "outcomes": [], "is_grouped": false, "event_groups": {…}, "event_titles": {…}} — never a 404.

Crypto markets

The crypto up/down markets (BTC/ETH/SOL/XRP on Kalshi + Polymarket, plus DOGE/HYPE/BNB and predict.fun on some intervals) for one time window. 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

Per-symbol resolution-price history over [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 under provider: "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 omitting source when the symbols do not identify exactly one) is a 400, not a merged response.

Crypto price-to-beat

Oracle price from the requested window resolution source at the start of each window (“the price to beat”), nested {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

Last-known prices for a fixed allow-list of stock, ETF, forex, and commodity symbols, mapped to standard ticker symbols. A shared cache holds all previously-fetched symbols; served straight from it only if every requested symbol is present. Otherwise missing symbols are fetched and merged into the cache, and the response returns only the freshly-fetched subset with 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

Paginated, filtered, event-grouped market list backed by a periodically-refreshed discover cache. Cacheable requests (no 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

Gotcha: the response price is a 0–1 decimal, but the min_price/max_price filters you send are in cents (0–100). The two ends of this endpoint do not use the same scale.

Discover ticker feed

Compact ticker-bar feed of top active markets by 1h volume. Grouped (multi-outcome) markets and parlays are excluded. 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

Interleaves the biggest 24h price movers, top 1h-volume, and top 24h-volume markets (deduped) for the Pulse rail. Only markets priced strictly between 10 and 90 cents, open/active, with ≥10 in 1h volume, no parlays, and a resolvable trade-history identifier are eligible; movers additionally need ≥2% 24h price change. 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

Markets expiring soonest with actionable prices (strictly between 0.5 and 99.5 cents). Backed by a short-lived (15s) Redis response cache. 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

Available subcategories (subtopics) for a topic category, each with a market count. Served straight from a cron-built Redis index (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

Every valid market, grouped by event, in a compact shape for client-side instant search. Results are cached after the first build to keep subsequent requests fast. 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 ranked by 1-hour volume. Not cached at the router level. 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 market IDs formatted for WebSocket subscription — a lighter payload than trending markets, for seeding a subscription list rather than rendering a list view. Ranked by 24-hour volume, unlike trending markets, which ranks by 1h volume. 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)

Kalshi sports events matched against live Polymarket games. Reads a cached set of Kalshi sports events and, if 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

An unpopulated cache is a 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).