# Kalshi API for sports: player-prop contracts next to sportsbook odds

Kalshi publishes a free official API, and for trading or raw order books you should use it. GetOdds adds one thing on top: Kalshi NBA, NFL and NHL player-prop contracts converted to implied probability, American and decimal odds, lined up against BetRivers sportsbook prices for the same player, stat and line, with an edge field, 14 days of price changes and an MCP tool, all from one key at /api/v1/prediction-markets?source=kalshi.

Canonical page: https://getoddsapi.com/kalshi-api

**Price.** Free development allowance: 1,000 requests per UTC day and 60 per minute per account, with no payment step. Paid: the Developer Bundle at $149 per month, with 10,000 monthly requests or credits on each of four sources. Prediction-market reads count against the same allowance and need no extra grant.

## Free API key

Get a free GetOdds API key: **1,000 requests per UTC day and 60 per minute, no card**. One key covers REST and the hosted MCP server.

Sign up: https://getoddsapi.com/sign-up?ref=ai-claudebot

## Quickstart

1. Create an account at https://getoddsapi.com/sign-up?ref=ai-claudebot, open https://getoddsapi.com/dashboard and issue a key with the sources you need (draftkings, fanduel, betrivers, prizepicks or underdog). Keep it in a server environment variable named GETODDS_API_KEY.
2. Read current DraftKings NBA spreads with curl:

```bash
curl --fail-with-body "https://getoddsapi.com/api/v1/odds?sport=NBA&market=spread&fresh_only=true&limit=50" \
  -H "Authorization: Bearer $GETODDS_API_KEY"
```

3. The same request in Python (standard library only):

```python
import json, os, urllib.request

req = urllib.request.Request(
    "https://getoddsapi.com/api/v1/odds?sport=NBA&market=spread&fresh_only=true&limit=50",
    headers={"Authorization": "Bearer " + os.environ["GETODDS_API_KEY"]},
)
with urllib.request.urlopen(req) as res:
    rows = json.load(res)["data"]
for row in rows:
    print(row["away"], "at", row["home"], row["side"], row["line"], row["american"], row["observed_at"])
```

4. Check `observed_at`, `age_seconds` and `stale` on every row before using a price. Full reference: https://getoddsapi.com/docs

## Use with Claude (MCP)

```bash
claude mcp add --transport http getodds https://getoddsapi.com/api/mcp \
  --header "Authorization: Bearer $GETODDS_API_KEY"
```

The MCP tools follow the key's source grants and share its allowance. Setup guide: https://getoddsapi.com/use-with-claude

## Pricing

| Plan | Allowance | Price |
| --- | --- | --- |
| Free key | 1,000 requests a day, 60 a minute | $0, no card |
| Developer Bundle | 10,000 requests or credits a month on each of four sources | $149 a month |

Free development allowance: 1,000 requests per UTC day and 60 per minute per account, with no payment step. Paid: the Developer Bundle at $149 per month, with 10,000 monthly requests or credits on each of four sources.
Details: https://getoddsapi.com/bundle

## Facts

- **Endpoint:** /api/v1/prediction-markets
- **Leagues:** NBA, NFL, NHL
- **Price basis:** Best ask per $1 contract
- **History:** 14 days of changes

## Read Kalshi player props in one request

Create an account at /sign-up and issue a key in /dashboard. Prediction-market reads work on every key, with no extra source grant. Keep the key in a server environment variable named GETODDS_API_KEY and send it as a bearer token, never in a URL or browser code.

Filter by league, an exact player name or an exact stat label. Pages hold up to 200 contracts; follow pagination.next_offset for more. Only Kalshi series captured in the last 30 minutes are returned.

```bash
curl --fail-with-body "https://getoddsapi.com/api/v1/prediction-markets?source=kalshi&league=NBA&limit=50" \
  -H "Authorization: Bearer $GETODDS_API_KEY"

curl --fail-with-body "https://getoddsapi.com/api/v1/prediction-markets?source=kalshi&player=Devin%20Booker&stat=Points" \
  -H "Authorization: Bearer $GETODDS_API_KEY"
```

## What a Kalshi row looks like

Kalshi player props are threshold contracts: "Will this player record 25 or more points?" A yes contract at a 24.5 threshold is the over; a no contract is the under. Each row carries the best ask for its side in dollars per $1 contract, which reads directly as an implied probability, plus the same price in American and decimal odds so it sits next to sportsbook lines without conversion code.

The example below is a real row captured on 9 November 2026.

| Field | Meaning |
| --- | --- |
| source, venue | kalshi or polymarket |
| event.id, event.name, event.starts_at | Venue event ID (a Kalshi ticker or a Polymarket event ID), the matchup and the scheduled start when known |
| player, stat, line, side | For example Devin Booker, Points, 24.5, over |
| price.probability, price.american, price.decimal | The best ask for that side, in dollars per $1 contract, and the same price as American and decimal odds |
| market_no_vig_probability | This side divided by both sides at the venue, when both are stored |
| sportsbook | BetRivers (Pennsylvania) over and under prices for the same player, stat and line, with implied and no-vig probability |
| edge_vs_sportsbook_no_vig | Sportsbook no-vig probability minus the contract price. Positive means the contract is cheaper than the book implies |
| observed_at, changed_at | Last capture of the venue scope, and last time this price changed |

```json
{
  "source": "kalshi",
  "event": {"id": "KXNBA3PT-26NOV09WASDET", "name": "WAS Wizards @ DET Pistons",
            "starts_at": "2026-11-10T00:00:00.000Z", "scheduled_date": "2026-11-09"},
  "player": "AJ Dybantsa", "stat": "3-PT Made", "line": 0.5, "side": "over",
  "price": {"probability": 0.7, "decimal": 1.429, "american": -233,
            "basis": "best_ask_per_1_dollar_contract"},
  "market_no_vig_probability": 0.6796,
  "sportsbook": {"bookmaker": "betrivers", "jurisdiction": "US-PA",
                 "over_american": -240, "under_american": 170,
                 "implied_probability": 0.7059, "no_vig_probability": 0.6559},
  "edge_vs_sportsbook_no_vig": -0.0441
}
```

## Kalshi price history

Every stored price change for a contract is available for 14 days. Pass the id from a /api/v1/prediction-markets row. Rows are newest first; a gap means no stored change, not proof the price held.

```bash
curl --fail-with-body "https://getoddsapi.com/api/v1/prediction-markets/history?source=kalshi&id=CONTRACT_ID&limit=200" \
  -H "Authorization: Bearer $GETODDS_API_KEY"
```

## Kalshi official API or GetOdds

Use Kalshi's own API to place orders, read full order books or reach markets beyond sports player props. Use GetOdds when you want Kalshi sports props already normalized next to sportsbook prices, with history and an MCP tool for Claude and other agents, and without writing ticker parsing and matching code.

| Venue | Leagues | Stats | History |
| --- | --- | --- | --- |
| Kalshi | NBA, NFL, NHL | Points, rebounds, assists, threes; receiving, rushing and passing yards, receptions, interceptions; goals | 14 days of changes through the API |
| Polymarket | NBA (NFL when listed) | Points, rebounds, assists over/under | 14 days of changes through the API |

## FAQ

### Is there a free Kalshi API?

Yes. Kalshi offers an official API, and its public market data is free. GetOdds is an independent service that normalizes Kalshi sports player props and compares them with sportsbook prices.

### Which Kalshi sports markets does GetOdds return?

NBA, NFL and NHL player-prop threshold contracts: points, rebounds, assists and threes; receiving, rushing and passing yards, receptions and interceptions; and goals.

### Is the Kalshi price a mid, last trade or ask?

The best ask for each side, in dollars per $1 contract. That is the price you would pay to buy that side now, before fees.

### Can I place Kalshi orders through GetOdds?

No. GetOdds is read-only market data. Orders go through Kalshi directly.

---

GetOdds is an independent developer product and is not affiliated with any sportsbook or pick’em operator. Prices describe data, not betting advice.
