The APIVex Kalshi API provides read-only access to public events, markets, order books, trades, and price candles. A useful first workflow is to discover an event, select one of its market tickers, and retrieve the yes/no order book.
This guide uses APIVex’s third-party service. Requests require an APIVex key, and these endpoints do not place or cancel orders.
Understand events, markets, and series
The identifiers serve different purposes. An event groups a question or set of related contracts. A market identifies an individual contract. A series groups recurring events and is also needed when requesting candles.
| Identifier | Where to get it | Use |
|---|---|---|
event_ticker | Event list or market record | Event details |
Market ticker | An event’s nested markets array | Market details and order book |
series_ticker | Event record | Series details and candle requests |
Do not derive the series ticker by splitting a market ticker. Preserve the identifier returned by the event response. The market detail object does not supply series_ticker.
Discover open events in one request
Get a key from the APIVex dashboard and set APIVEX_API_KEY in your server environment. The base URL is https://api.apivex.com/kalshi.
curl --get 'https://api.apivex.com/kalshi/api/events/list' \
--header "x-apivex-key: $APIVEX_API_KEY" \
--data-urlencode 'status=open' \
--data-urlencode 'with_nested_markets=true' \
--data-urlencode 'limit=2'Read data.events. With nested markets enabled, each event includes its market records, avoiding a separate market-list request just to discover a ticker. Pagination uses data.cursor: pass that opaque value as cursor on the next request, preserving your filters.
The list filter is status=open, but a returned market can describe its status as active. Do not silently drop those markets because the two strings differ.
Fetch a market’s order book with Node.js
Save this as kalshi-book.mjs, set your environment key, and run node kalshi-book.mjs with Node.js 20 or newer. It reads one page of events and then requests up to five price levels per side for a returned market. The selected market can change as the event list changes.
const key = process.env.APIVEX_API_KEY;
if (!key) throw new Error('Set APIVEX_API_KEY first');
const base = 'https://api.apivex.com/kalshi';
// Demonstration pacing; use the request rate allowed by your plan.
const pause = () => new Promise(resolve => setTimeout(resolve, 2500));
async function get(path, params) {
const url = new URL(base + path);
url.search = new URLSearchParams(params).toString();
const response = await fetch(url, {
headers: {'x-apivex-key': key},
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error('HTTP ' + response.status);
const body = await response.json();
if (body.status !== true) throw new Error(body.message || 'API request failed');
return body.data;
}
const page = await get('/api/events/list', {status: 'open', with_nested_markets: true, limit: 2});
const event = page.events.find(e => e.markets?.length);
const market = event?.markets[0];
if (!market) throw new Error('No market in this event page');
console.log({event: event.event_ticker, series: event.series_ticker, ticker: market.ticker});
await pause();
const book = await get('/api/markets/orderbook', {ticker: market.ticker, depth: 5});
console.log(JSON.stringify(book, null, 2));The book response includes yes_bids, no_bids, best_yes_bid, best_no_bid, implied_yes_ask, and implied_no_ask. Each bid level has a price and size.
These are two sides of a binary contract. The API exposes implied asks alongside bids; do not label no_bids as a list of yes asks without applying the correct relationship. Keep market identifiers with every stored snapshot so observations from different contracts cannot be mixed.
Add price history without guessing identifiers
The candlestick route requires both ticker and series_ticker, plus start_ts and end_ts in Unix seconds. period_interval is measured in minutes and accepts 1, 60, or 1440.
The documented maximum is 5,000 candles per request. Split longer windows into bounded ranges and deduplicate any shared boundary timestamps. JavaScript’s Date.now() is in milliseconds; divide by 1,000 and round down when constructing these request timestamps.
For a dashboard, store when you fetched each snapshot and the underlying market status. An old order book should not be displayed as a newly retrieved quote after a failed refresh.
Avoid two common integration traps
An empty book is ambiguous. It can mean there are no resting orders, or that the ticker is unknown. Confirm the ticker through market details before reporting that a market has no liquidity.
Multivariate/CROSS tickers have different coverage. The market-list endpoint excludes them by default, and the documented market-detail route returns 404 for those tickers. Changing mve_filter to only does not make the same downstream detail workflow work for them.
Use the Kalshi API documentation to inspect the full response and try a market you actually want to monitor. For Polymarket’s different identifier model, see the Polymarket outcome and order-book guide.



