Sports prediction market API: Kalshi vs Polymarket
Read both order books against the same sports event, then compare the price you can execute rather than the last number on screen.
The last trade is not your price
A prediction market can display 50%, quote an ask at 53% and fill a larger order at an average of 54.2%. All three numbers are correct. Only one describes what the full order could cost now.
Kalshi and Polymarket are order books. A buyer takes available asks. A seller takes available bids. The last trade records an earlier transaction, while the midpoint sits between the current bid and ask. Neither proves that enough size is available at that number.
A useful sports prediction market API therefore needs more than a headline probability. It needs the bid and ask ladders, size at each level, fees, freshness and a reliable way to match the contract to the corresponding sports event.
What the normalized contract returns
The prediction-market endpoint keeps the provider identity intact while giving both sources the same response shape. You can filter by provider, market key, contract ID and ladder depth.
| Question | Fields | Use |
|---|---|---|
| Which market is this? | provider, provider_market_id, market_key, period | Keep source IDs while joining the market to one sports event. |
| What can I buy or sell? | probability_bids, probability_asks | Read ordered price levels and the size available at each level. |
| What is at the top? | best_bid_probability, best_ask_probability, size fields | Render the current top of book without discarding depth. |
| What did the last trade show? | last_trade_probability | Show context without treating an old trade as an executable quote. |
| What does the price mean in odds? | gross_decimal_odds, fee_adjusted_decimal_odds | Compare normalized prediction prices with decimal sportsbook odds. |
| How current is it? | source_ts, observed_at, as_of_ts_ms | Apply a freshness rule before displaying or comparing the quote. |
Kalshi's official order-book documentation exposes active bid orders for the YES and NO sides; the opposite side can be derived in a binary contract. Polymarket's official order-book response includes bids, asks, size and last trade price. odds-api.net converts the supported sports contracts into one explicit probability-ladder model while retaining the original provider and contract IDs.
Request both order books
Find the sports event first. Then request the dedicated prediction-market snapshot for its event_id. Keep the API key on your server.
curl --request GET \
--header "X-API-Key: $ODDS_API_KEY" \
"https://api.odds-api.net/v1/events/{event_id}/prediction-markets/orderbook/snapshot?providers=kalshi,polymarket&depth=5&include_unavailable=true"
{
"event_id": "{event_id}",
"items": [
{
"provider": "polymarket",
"provider_market_id": "{provider_market_id}",
"market_key": "moneyline",
"source_ts": "{source_timestamp}",
"contracts": [
{
"contract_id": "{contract_id}",
"outcome": "home",
"probability_bids": [{"price": 0.51, "size": 80}],
"probability_asks": [
{"price": 0.53, "size": 40},
{"price": 0.55, "size": 60}
],
"best_bid_probability": 0.51,
"best_ask_probability": 0.53,
"last_trade_probability": 0.50,
"gross_decimal_odds": 1.8868,
"fee_adjusted_decimal_odds": 1.84
}
]
}
],
"resume": "{resume_token}"
}
The values are illustrative. The field names and nesting follow the current public API schema.
Open the live reference for current parameters, response codes and schemas.
Price the order you intend to fill
Assume a buyer wants 100 YES contracts. The visible ladder offers 40 at 0.53 and 60 at 0.55.
| Ask level | Size taken | Cost |
|---|---|---|
| 0.53 | 40 contracts | 21.20 |
| 0.55 | 60 contracts | 33.00 |
| Weighted fill | 100 contracts | 54.20 |
Average entry probability54.20 ÷ 100 = 0.542
Gross decimal odds1 ÷ 0.542 = 1.845
Displayed last trade0.50 = 2.00 decimal
The 2.00 last-trade conversion overstates the current executable return. Even the 1.887 top ask applies only to the first 40 contracts. The full order reaches the second level and produces gross decimal odds of 1.845 before fees.
Use fee_adjusted_decimal_odds when it is present. Provider fees can depend on the market and fee model, so a single hard-coded percentage is not a safe substitute.
View the Python ladder calculation
def executable_buy(asks, contracts):
remaining = contracts
cost = 0.0
for level in sorted(asks, key=lambda row: row["price"]):
filled = min(remaining, level["size"])
cost += filled * level["price"]
remaining -= filled
if remaining == 0:
break
if remaining:
return None # not enough displayed size
average_probability = cost / contracts
return {
"contracts": contracts,
"cost": cost,
"average_probability": average_probability,
"gross_decimal_odds": 1 / average_probability,
}
Reject the comparison when the visible ladder cannot fill the requested size.
Compare the same contract with sportsbooks
The shared event_id removes one difficult join. It does not prove that two markets settle identically. Match the outcome, period, line and settlement terms before placing prices in the same row.
GET /v1/events/{event_id}/odds/snapshotGET /v1/events/{event_id}/prediction-markets/orderbook/snapshotBack and lay exchanges use a different order-book model. The betting exchange API covers normalized exchange ladders, while the Betfair API guide documents the exchanges=betfair filter and Betfair-specific fields.
- Match the event
Use the same canonical
event_id. Do not join on team names alone. - Match the contract
Confirm outcome, period, market type, line and settlement wording.
- Price the required size
Walk the ask ladder instead of copying the top ask or last trade.
- Apply fees
Compare the returned fee-adjusted prediction price with the available sportsbook odds.
- Reject stale data
Use source and observation timestamps. Missing freshness means no comparison.
Snapshot first. Stream the changes.
The REST response gives you a complete starting state and a resume token. Pass that token as since when opening the SSE or WebSocket route.
- 01SnapshotLoad the current ladders
- 02Save resumePersist the stream position
- 03ConnectSSE or WebSocket
- 04Apply deltaReplace the changed book
- 05ResyncReload after a resync event
curl --no-buffer \
--header "X-API-Key: $ODDS_API_KEY" \
"https://api.odds-api.net/v1/events/{event_id}/prediction-markets/orderbook/stream?providers=kalshi,polymarket&depth=5&since={resume_token}"
Handle delta, heartbeat and resync. Reload the REST snapshot after resync.
Build the comparison with one API account
Direct provider integrations leave your product responsible for event matching, source-specific authentication, response translation, fee handling and stream recovery. odds-api.net keeps the source IDs but gives the supported sports contracts one event-level API shape.
Request separate data surfaces without rebuilding the event join for every provider.
Read probability ladders, size, liquidity, fees and freshness through consistent fields.
Prototype with snapshots, then add resumable updates when the product needs them.
Know the boundary
- The prediction-market routes provide market data. They do not place, cancel or manage trades.
- Supported contracts are limited to prediction markets linked to covered canonical sports events.
- A normalized event link does not override the provider's contract wording or settlement rules.
- Liquidity can change before an order reaches a venue. Displayed size is evidence, not an execution guarantee.
- Access to a market or trading venue depends on the provider's rules and the user's jurisdiction.
Sources and method
The endpoint names, filters and response fields were checked against the live odds-api.net OpenAPI document on 17 September 2026. The fill example is illustrative and shows order-book maths, not a recorded market, performance claim or betting recommendation.
Sports prediction market API questions
Can one API return Kalshi and Polymarket sports order books?
Yes. odds-api.net links supported Kalshi and Polymarket contracts to one canonical sports event and returns normalized probability bid and ask ladders through one event-level endpoint.
How do I compare prediction-market prices with sportsbook odds?
Match the same event, outcome, period, line and settlement terms. Use the prediction market's executable ask ladder and fee-adjusted decimal odds, then compare that value with the available sportsbook price for the same contract.
Why should I not compare the last trade price?
The last trade records an earlier transaction. It does not show the current price or the size available now. A new buy should be priced from the current ask ladder.
Does the API include prediction-market liquidity and fees?
Covered contracts can include bid and ask size, top-of-book size, total liquidity, the applicable fee model, estimated fee per contract and fee-adjusted decimal odds.
Can I stream Kalshi and Polymarket order-book updates?
Yes. Load the REST snapshot first, keep its resume token, then connect to the matching SSE or WebSocket route. Apply delta events and reload the snapshot after a resync event.
Can odds-api.net place prediction-market trades?
No. odds-api.net provides market data for supported sports events. It does not place, cancel or manage orders on Kalshi, Polymarket or a sportsbook.