The Kalshi API field map
Kalshi's v2 API moved prices and sizes to *_dollars and *_fp suffixed fields. A bot still reading yes_price or position gets None — and silently misprices everything. Below is what the responses actually contain.
GET /markets/{ticker}
Prices are dollar strings. `result` is only present once settled. Bid/ask sizes are `_fp`.
yes_bid_dollarsyes_ask_dollarsyes_bid_size_fpyes_ask_size_fpno_bid_dollarsno_ask_dollarslast_price_dollarsprevious_price_dollarsprevious_yes_bid_dollarsprevious_yes_ask_dollarsvolume_fpvolume_24h_fpopen_interest_fpnotional_value_dollarsresultstatusGET /portfolio/balance
`balance` is cents (int); `balance_dollars` is the string you actually want. `portfolio_value` is the mark of open positions, in cents.
balancebalance_dollarsbalance_breakdown[]portfolio_valueupdated_tsGET /portfolio/positions
The big one — `position` no longer exists. Size is `position_fp`; money is `_dollars`. Reading the old names returns nothing and silently misprices everything.
tickerposition_fpmarket_exposure_dollarsrealized_pnl_dollarsfees_paid_dollarstotal_traded_dollarslast_updated_tsexchange_indexGET /portfolio/fills
`count_fp` for size; both sides of the price are given (`yes_price_dollars`, `no_price_dollars`). `is_taker` tells you whether you paid the taker fee.
tickermarket_tickerorder_idfill_idtrade_idactionsideoutcome_sidebook_sideis_takercount_fpyes_price_dollarsno_price_dollarsfee_costcreated_timeGET /portfolio/orders
`remaining_count_fp` / `initial_count_fp` / `fill_count_fp` for size; maker vs taker fees are broken out separately.
order_idclient_order_idtickeractionsideoutcome_sidetypestatusyes_price_dollarsno_price_dollarsinitial_count_fpremaining_count_fpfill_count_fpmaker_fees_dollarstaker_fees_dollarscreated_timeexpiration_timeGET /markets/{ticker}/orderbook
The only trustworthy price source. Best yes_ask = 1 − best no_bid; best no_ask = 1 − best yes_bid. Each entry is [price, size].
orderbook_fp.yes_dollarsorderbook_fp.no_dollarsTick sizes are not uniform
Every market carries price_level_structure and price_ranges, and the tick changes with the price. Two schemes, taken from live responses:
linear_cent0.00–1.00 in 1¢ steps. The common case (diesel ladders, most sports and mention markets).
tapered_deci_cent0.1¢ from 0.00–0.10 · 1¢ from 0.10–0.90 · 0.1¢ from 0.90–1.00. Fine ticks at the extremes, coarse in the middle.
Why it matters for a fade: near the certainty end you can bid 0.961, not just 0.96 — which is often the difference between resting at the touch and being a cent away from it. Read the schedule per market rather than assuming a cent.
Two rules that follow
- Price off the live orderbook, never the snapshot. The market object's
*_dollarsbid/ask can lag the book by tens of cents on thin or fast markets, so an "edge" computed from them can be pure fiction. - Parse defensively. A helper that returns
0.0on failure keeps one stale row from crashing a scan — but never let that helper feed a price into a decision.
Related: the free Kalshi fee calculator — and the edge calculator for whether the trade clears the floor at all.
Produced by dumping live Kalshi v2 responses on 2026-10-23. Not exhaustive — endpoints gain fields over time, so treat this as a map, not a schema.
Hitting one of these walls?
The free Operator's Playbook covers the setup traps. The full guide covers surviving API drift, controlling AI spend, reading the dashboard, and the paper-first protocol.