← Back
Free reference

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_dollarsresultstatus

GET /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_ts

GET /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_index

GET /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_time

GET /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_time

GET /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_dollars

Tick 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_cent

0.00–1.00 in 1¢ steps. The common case (diesel ladders, most sports and mention markets).

tapered_deci_cent

0.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

  1. Price off the live orderbook, never the snapshot. The market object's *_dollars bid/ask can lag the book by tens of cents on thin or fast markets, so an "edge" computed from them can be pure fiction.
  2. Parse defensively. A helper that returns 0.0 on 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.