Skip to content

Kalshi Search API

Discover, cluster, and correlate markets across the live Kalshi prediction-market universe. These endpoints turn the open market set into a queryable database with three lenses — keyword search, embedding similarity, and time-series math — joinable in a single request.

Pair this surface with the Baskets API for server-side portfolio construction, with the Prediction Markets Agent for narrative analysis on individual events, and with the Events API for per-event snapshots and time series.

Like the Chat Completions and Responses endpoints, these are direct REST endpoints called relative to the Octagon API base URL:

text
https://api.octagonai.co/v1

Conventions

ConventionDetails
Path styleKebab-case (e.g. /behavioral-clusters, /markets-with-edge, /cluster-peers).
Field stylesnake_case in query strings, request bodies, and response payloads.
TimestampsRFC 3339 UTC (2026-08-19T00:00:00Z).
Prices0–1 fraction units (Kalshi cents are normalized server-side).
ProbabilitiesOctagon model/market probabilities (model_probability, market_probability) are percentages on a 0–100 scale; edge_pp is their difference in percentage points; confidence_score is 0–10. Note: the Baskets API sizing endpoints take probabilities as 0–1 fractions — divide by 100 when feeding values across.
Paginationbase64(JSON) cursor tokens. Pass next_cursor from a previous page back as cursor=....

Data refresh

Market, event, candle, cluster, and model-run data refresh nightly.

Search & Browse

GET /predictions/kalshi/markets

Structured + full-text search over the open Kalshi universe.

Query parameters

ParameterTypeRequiredDescription
qstringNoFull-text query over title, subtitle, and ticker. Results are ranked by relevance when supplied. Minimum 3 characters.
categorystringNoMatches event category or subcategory (exact).
series_tickerstringNoFilter by Kalshi series (exact match).
series_prefixstringNoLIKE '<prefix>%' filter on series_ticker — tree-style browsing (e.g. KXBTC matches KXBTCD, KXBTCY, KXBTCMAX100, …).
event_tickerstringNoFilter to markets in a single event.
close_beforedatetimeNoOnly markets closing on or before this RFC 3339 timestamp.
min_volume_24hfloatNoFloor on volume_24h.
sort_bystringNovolume_24h, close_time, or last_price. Defaults to rank when q is supplied, otherwise volume_24h.
boost_categorystringNoBoosts relevance rank for markets in this category (case-insensitive), so a macro-flavored query like Brent crude prefers Financials over an MLB prop bet. Ignored when q is empty or sort_by is set.
limitintegerNoPage size. Default 50; min 1; max 200.
cursorstringNoPagination cursor returned from a previous response.

Response fields

Each market row in the data array includes:

FieldTypeDescription
market_tickerstringTicker for this market.
event_tickerstringParent event ticker.
series_tickerstringParent series ticker.
titlestringMarket title.
subtitlestring | nullMarket subtitle.
statusstringMarket status (e.g. "open").
close_timedatetimeWhen the market closes.
last_pricefloatLast traded price (0–1).
yes_bid / yes_askfloatYES-side bid/ask (0–1).
no_bid / no_askfloatNO-side bid/ask (0–1).
volumenumberTotal volume.
volume_24hnumber24-hour volume.
liquiditynumberLiquidity metric.
open_interestnumberOpen interest.
categorystringEvent category.
event_namestringParent event name.

The response envelope also includes next_cursor and has_more for pagination.

GET /predictions/kalshi/markets/similar

Semantic similarity search. Catches matches keyword search misses (e.g. "Will Bitcoin pierce six figures""BTC above $100k") and is freely combinable with structured filters.

Query parameters — exactly one of anchor_ticker or q is required; supplying neither or both returns 400.

ParameterTypeRequiredDescription
anchor_tickerstringCond.Use the stored embedding of this market as the anchor. Zero added latency. Mutually exclusive with q.
qstringCond.Anchor by free-text query. Adds a short embedding step. Mutually exclusive with anchor_ticker.
top_kintegerNoNumber of nearest neighbors. Default 25; min 1; max 100.
categorystringNoRestrict to a category.
min_volume_24hfloatNoFloor on volume_24h.
close_beforedatetimeNoOnly markets closing before this RFC 3339 timestamp.

Response fields

FieldTypeDescription
anchor_tickerstring | nullThe anchor ticker, when anchored by ticker.
anchor_querystring | nullThe free-text query, when anchored by q.
dataarrayNearest neighbors: market_ticker, event_ticker, title, category, and distance. Lower distance = closer cosine similarity.

GET /predictions/kalshi/series

Per-series rollup over the active universe — one row per series with active counts, volume, and dominant category.

Query parameters

ParameterTypeRequiredDescription
series_prefixstringNoLIKE '<prefix>%' filter on series_ticker (e.g. KXBTC matches KXBTCD, KXBTCY, KXBTCMAX100, …).
categorystringNoFilter against the dominant category for each series.
min_volume_24hfloatNoFloor on total_volume_24h.
sort_bystringNototal_volume_24h (default), market_count, or active_count.
limitintegerNoDefault 50; min 1; max 200.
cursorstringNoPagination cursor.

Response fields

Each series row in the data array includes:

FieldTypeDescription
series_tickerstringSeries ticker.
series_titlestringSeries title.
market_countintegerTotal markets in the series.
active_countintegerActive markets in the series.
total_volume_24hfloatCombined 24-hour volume across the series.
dominant_categorystringMost common category across the series.
categoriesarrayAll categories present in the series.
last_seen_atdatetimeWhen the series was last observed in the sync.

Performance

Expect 1–3 s on the first call; later calls are served from the nightly rollup.

GET /predictions/kalshi/series/{series_ticker}/events

List events inside a single series.

Query parameters

ParameterTypeRequiredDescription
qstringNoOptional free-text filter within the series (title / subtitle).
limitintegerNoDefault 50; min 1; max 200.
cursorstringNoPagination cursor.

Response fields

The envelope echoes series_ticker; each event row in the data array includes:

FieldTypeDescription
event_tickerstringEvent ticker.
titlestringEvent title.
categorystringEvent category.
close_timedatetimeWhen the event closes.
market_countintegerTotal markets within the event.
active_market_countintegerActive markets within the event.
total_volume_24hfloatCombined 24-hour volume.

GET /predictions/kalshi/events/{event_ticker}/markets

Walk an event's child markets — e.g. every strike in an IPO date-ladder, every state in an election, every band in a recession-by-date event.

Query parameters

ParameterTypeRequiredDescription
min_volume_24hfloatNoFloor on volume_24h.
limitintegerNoDefault 100; min 1; max 500.
cursorstringNoPagination cursor.

Response fields

The envelope echoes event_ticker; each market row in the data array uses the same market fields as GET /predictions/kalshi/markets.

Clusters

GET /predictions/kalshi/clusters

Browse the current run of thematic (embedding-based) clusters.

Query parameters

ParameterTypeRequiredDescription
limitintegerNoDefault 200; min 1; max 500.
sample_titlesintegerNoNumber of sample titles per cluster. Default 4; min 0; max 20.
label_containsstringNoCase-insensitive substring filter on the cluster label.
cursorstringNoPagination cursor.

Response fields

Each cluster in the data array includes:

FieldTypeDescription
cluster_idintegerCluster identifier under the current run.
labelstringLLM-generated cluster label.
descriptionstringLLM-generated cluster description.
sizeintegerNumber of markets in the cluster.
sample_titlesarrayRepresentative market titles.
created_atdatetimeWhen the cluster run was created.

GET /predictions/kalshi/clusters/{cluster_id}/markets

Markets in one thematic cluster, ranked ascending by distance to the cluster centroid. Same response shape and cursor pagination as GET /predictions/kalshi/markets.

GET /predictions/kalshi/behavioral-clusters

Same shape as /predictions/kalshi/clusters but over the behavioral cluster run, which groups markets by their 30-day daily return patterns. Each row additionally exposes mean_daily_return and daily_volatility. Covers markets with ≥14 days of daily candles.

Query parameterslimit, sample_titles, and cursor, as on GET /predictions/kalshi/clusters. label_contains is not supported here.

GET /predictions/kalshi/behavioral-clusters/{cluster_id}/markets

Members of one behavioral cluster, same response shape as the thematic version.

GET /predictions/kalshi/markets/{market_ticker}/clusters

Return the thematic and behavioral cluster IDs a single market belongs to under the current runs. Useful for driving "no more than N legs from the same cluster" basket constraints client-side when not using POST /predictions/kalshi/baskets/build.

Response fields

FieldTypeDescription
market_tickerstringThe requested market.
thematicobject | nullThematic assignment: cluster_id, label, description, size.
behavioralobject | nullBehavioral assignment: cluster_id, label, size, mean_daily_return, daily_volatility.

Either field can be null if the market isn't in a current-run assignment for that clustering kind.

GET /predictions/kalshi/markets/{market_ticker}/cluster-peers

Peer markets in the anchor's cluster, in one call.

Query parameters

ParameterTypeRequiredDescription
kindstringNothematic (default) or behavioral. Selects the clustering to use.
limitintegerNoNumber of peers, excluding the anchor. Default 50; min 1; max 200.

Response fields

FieldTypeDescription
market_tickerstringThe anchor market.
kindstringThe clustering used (thematic or behavioral).
clusterobjectThe anchor's cluster: cluster_id, label, description, size.
dataarrayPeer markets: market_ticker, title, and distance to the anchor.

Correlations & Model Edge

POST /predictions/kalshi/markets/correlations

Pairwise Pearson correlation matrix over close-price series for N markets. Side-aware: pass per-ticker sides to mix YES and NO legs (the sign is flipped for each NO leg, since corr(YES_A, NO_B) = -corr(YES_A, YES_B)).

Request body

FieldTypeRequiredDescription
market_tickersarray of stringsYes2–100 distinct market tickers.
sidesarray of stringsNoPer-ticker side — "yes" or "no", same length as market_tickers. Defaults to all yes. Filtered to the present tickers in the response.
window_daysintegerNoLookback window. Default 30; min 1; max 730.
intervalstringNo"1h" or "1d". Auto-picked when omitted: 1d when window_days ≥ 90, else 1h. 1h reads hourly candles, 1d reads daily.
include_cell_detailbooleanNoWhen true, include a cells_detail array with overlap counts and a reason code per pair. Default false.

Response fields

FieldTypeDescription
tickersarrayThe tickers included in the matrix, in matrix order.
sidesarrayThe effective per-ticker sides.
matrixarray of arraysPairwise Pearson correlations, already side-flipped server-side. Cells with fewer than 3 paired observations or constant series are null.
ranked_pairsarrayThe upper-triangle of the matrix sorted ascending by correlation — the most-uncorrelated pairs come first. Each entry: ticker_a, ticker_b, correlation.
cells_detailarray | nullPresent only with include_cell_detail: true. Each entry: ticker_a, ticker_b, correlation, overlap_count, and reason"ok", "insufficient_overlap", or "zero_variance".
window_daysintegerThe lookback window used.
intervalstringThe candle interval used.
missingarrayMarkets without candle data in the window — dropped from the matrix.

POST /predictions/kalshi/markets/edge

Per-ticker Octagon model-edge lookup. Accepts a mix of market and event tickers — markets are resolved to their parent event server-side. Returns stored model output from the most recent scoring run.

Typical use: pull model priors for a known list of tickers, then feed model_probability into POST /predictions/kalshi/baskets/size for Kelly sizing.

Request body

FieldTypeRequiredDescription
tickersarray of stringsYes1–100 tickers. Mix of market_ticker and event_ticker values is allowed.
run_idstring (UUID)NoSpecific scoring run. Defaults to the most recent run.

Response fields

The envelope includes the resolved run_id and its captured_at; each row in the data array includes:

FieldTypeDescription
input_tickerstringThe ticker as supplied in the request.
market_tickerstring | nullResolved market ticker. null when the input was an event ticker (no per-market resolution applies).
event_tickerstringResolved parent event ticker.
titlestringEvent title.
series_categorystringEvent category.
model_probabilityfloat | nullOctagon model probability (0–100 percentage scale).
market_probabilityfloat | nullMarket-implied probability (0–100 percentage scale).
edge_ppfloat | nullModel edge in percentage points (model_probability - market_probability).
expected_returnfloat | nullExpected return if the model is correct.
confidence_scorefloatOctagon's confidence in the model output (0–10 scale).
total_volumefloatTotal trading volume.
total_open_interestfloatTotal open interest.
statusstring"scored" when the parent event was scored in this run, otherwise "unscored".
captured_atdatetimeSnapshot capture time.

GET /predictions/kalshi/markets-with-edge

Edge-vs-consensus ranking against the latest completed scoring run, the same data exposed by the Events API. One-call recipe for "10 most-traded politics markets ranked by edge vs consensus".

Query parameters

ParameterTypeRequiredDescription
run_idstring (UUID)NoDefaults to the most recent scoring run.
categorystringNoFilter on series_category (case-insensitive).
edge_pp_minnumberNoLower bound on edge_pp (model probability minus market probability, in percentage points).
edge_pp_maxnumberNoUpper bound on edge_pp.
expected_return_minnumberNoFloor on expected_return.
total_volume_minnumberNoFloor on total_volume.
model_probability_minnumberNoFloor on model_probability, on the same 0–100 scale (e.g. 60 for 60%).
sort_bystringNoOne of edge_pp (default), expected_return, total_volume, model_probability. Descending.
limitintegerNoDefault 50; min 1; max 200.
cursorstringNoPagination cursor.

Response fields

The envelope includes the resolved run_id, its captured_at, and the effective sort_by; each row in the data array includes:

FieldTypeDescription
event_tickerstringEvent ticker.
titlestringEvent title.
series_categorystringEvent category.
model_probabilityfloatOctagon model probability (0–100 percentage scale).
market_probabilityfloatMarket-implied probability (0–100 percentage scale).
edge_ppfloatModel edge in percentage points (model_probability - market_probability).
expected_returnfloatExpected return if the model is correct.
confidence_scorefloatOctagon's confidence in the model output (0–10 scale).
total_volumefloatTotal trading volume.
total_open_interestfloatTotal open interest.

The envelope also includes next_cursor and has_more for pagination. If filters reject every row but the run exists, captured_at still reflects the run's snapshot age.

Use Cases

  • Keyword search — markets matching "BTC 100k" via GET /predictions/kalshi/markets?q=....
  • Semantic search — markets similar to a known ticker (anchor_ticker) or a free-text description (q) via GET /predictions/kalshi/markets/similar.
  • Browse the universe tree — series rollups (GET /predictions/kalshi/series), events within a series (GET /predictions/kalshi/series/{series_ticker}/events), and every strike/state/band within an event (GET /predictions/kalshi/events/{event_ticker}/markets).
  • Browse themes — the clustered map of the universe (GET /predictions/kalshi/clusters), drill into a theme (GET /predictions/kalshi/clusters/{cluster_id}/markets), or jump straight to a market's theme-mates (GET /predictions/kalshi/markets/{market_ticker}/cluster-peers).
  • Find uncorrelated betsPOST /predictions/kalshi/markets/correlations and read off ranked_pairs (most-uncorrelated pairs first), mixing YES and NO legs via sides.
  • Rank by model edgeGET /predictions/kalshi/markets-with-edge for edge-vs-consensus rankings, or POST /predictions/kalshi/markets/edge to pull model priors for a known ticker list.
  • True top-N by volumeGET /predictions/kalshi/markets?sort_by=volume_24h across the entire universe, no client reranking.

Errors

StatusCause
400Bad query parameters — unknown name, invalid kind / sort_by, anchor_ticker + q both supplied, and similar.
401Missing or invalid Authorization header.
422Request body validation failure — a missing or wrongly-typed field, or a value outside its documented range.
502Upstream failure — typically an embedding or candle-data error.
503Kalshi search is unavailable, or q is shorter than 3 characters.

All errors return a JSON body with a detail field describing the cause.

  • Baskets API — server-side basket building, Kelly sizing, backtests, and validation over this universe.
  • Prediction Markets Agent — the agent that produces narrative reports on individual events.
  • Events API — latest snapshot of every analyzed event plus per-event history. Exposes the same scoring runs as /predictions/kalshi/markets-with-edge.