Skip to the guide

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.

MatchOne canonical event
PriceBid and ask ladders
CostSize and estimated fees
TimeSource freshness

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.

QuestionFieldsUse
Which market is this?provider, provider_market_id, market_key, periodKeep source IDs while joining the market to one sports event.
What can I buy or sell?probability_bids, probability_asksRead ordered price levels and the size available at each level.
What is at the top?best_bid_probability, best_ask_probability, size fieldsRender the current top of book without discarding depth.
What did the last trade show?last_trade_probabilityShow context without treating an old trade as an executable quote.
What does the price mean in odds?gross_decimal_odds, fee_adjusted_decimal_oddsCompare normalized prediction prices with decimal sportsbook odds.
How current is it?source_ts, observed_at, as_of_ts_msApply 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.

Kalshi + Polymarket snapshotREST
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"
Trimmed response shapeJSON
{
  "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 levelSize takenCost
0.5340 contracts21.20
0.5560 contracts33.00
Weighted fill100 contracts54.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
executable_price.pyPython
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.

Sportsbook oddsGET /v1/events/{event_id}/odds/snapshot
Prediction marketsGET /v1/events/{event_id}/prediction-markets/orderbook/snapshot

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

  1. Match the event

    Use the same canonical event_id. Do not join on team names alone.

  2. Match the contract

    Confirm outcome, period, market type, line and settlement wording.

  3. Price the required size

    Walk the ask ladder instead of copying the top ask or last trade.

  4. Apply fees

    Compare the returned fee-adjusted prediction price with the available sportsbook odds.

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

The recovery-safe loop
  1. 01SnapshotLoad the current ladders
  2. 02Save resumePersist the stream position
  3. 03ConnectSSE or WebSocket
  4. 04Apply deltaReplace the changed book
  5. 05ResyncReload after a resync event
Resume with SSEStreaming
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.

Compare REST, SSE and WebSocket delivery.

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.

One event IDSportsbooks + prediction markets

Request separate data surfaces without rebuilding the event join for every provider.

One order-book shapeKalshi + Polymarket

Read probability ladders, size, liquidity, fees and freshness through consistent fields.

Three delivery modesREST + SSE + WebSocket

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.