← Back to blog

The Complete Guide to Prediction Market APIs (Polymarket, Kalshi, and Sportsbooks)

api polymarket kalshi tutorial reference python

There are four major sources of prediction market data for sports events. Each has a different API, different authentication, different data format, and different strengths. This guide covers all of them with working Python code.

1. Polymarket CLOB API

Polymarket runs a Central Limit Order Book (CLOB) on Polygon. You can read orderbooks, place trades, and stream real-time prices.

Official docs: docs.polymarket.com Python client: py-clob-client Authentication: API key + secret + passphrase + Polygon private key Rate limits: ~100 requests/second (generous) Data format: JSON Fee: ~2% on fills

Best for: Live trading, real-time orderbook data, sports moneylines

from py_clob_client.client import ClobClient
from py_clob_client.clob_types import ApiCreds
import os

client = ClobClient(
    "https://clob.polymarket.com",
    key=os.environ["POLY_PRIVATE_KEY"],
    chain_id=137,
    creds=ApiCreds(
        api_key=os.environ["POLY_API_KEY"],
        api_secret=os.environ["POLY_API_SECRET"],
        api_passphrase=os.environ["POLY_PASSPHRASE"],
    ),
)

# Read orderbook
book = client.get_order_book("TOKEN_ID_HERE")
best_bid = float(book.bids[0].price) if book.bids else 0
best_ask = float(book.asks[0].price) if book.asks else 1

Market discovery uses the Gamma API (separate from CLOB):

import requests
markets = requests.get(
    "https://gamma-api.polymarket.com/markets",
    params={"tag": "sports", "active": True, "limit": 50}
).json()

WebSocket streaming for real-time prices:

import websockets, json

async def stream(token_ids):
    async with websockets.connect("wss://ws-subscriptions-clob.polymarket.com/ws/market") as ws:
        await ws.send(json.dumps({"type": "subscribe", "markets": token_ids}))
        async for msg in ws:
            print(json.loads(msg))

Strengths: Real-time data, full orderbook depth, direct execution Weaknesses: Thin liquidity on esports/minor sports, 10-30s price lag after score changes

Full tutorial: Polymarket API Python Tutorial


2. Kalshi REST API

Kalshi is a CFTC-regulated event contract exchange. They offer sports markets alongside political, economic, and weather events.

Official docs: trading-api.readme.io Authentication: Email + password → JWT token Rate limits: 10 requests/second Data format: JSON Fee: Variable (typically 7-10% of profit on winning trades)

Best for: Regulated event contracts, spread/total markets, US-regulated trading

import requests

# Login
resp = requests.post("https://trading-api.kalshi.com/trade-api/v2/login", json={
    "email": "your@email.com",
    "password": "your_password"
})
token = resp.json()["token"]
headers = {"Authorization": f"Bearer {token}"}

# Get markets
markets = requests.get(
    "https://trading-api.kalshi.com/trade-api/v2/markets",
    headers=headers,
    params={"series_ticker": "KXNBAGAME", "status": "open"}
).json()

# Get orderbook
ticker = "KXNBAGAME-26APR21-LAL-BOS"
book = requests.get(
    f"https://trading-api.kalshi.com/trade-api/v2/markets/{ticker}/orderbook",
    headers=headers
).json()

Strengths: Regulated (CFTC), spread/total markets available, clean REST API Weaknesses: Lower liquidity than Polymarket, higher fees, fewer sports


3. ESPN Scoreboard API (Free Sports Data)

ESPN has an undocumented API that powers their website. Free, no authentication, covers every major sport.

Docs: None (undocumented) Authentication: None required Rate limits: ~1 request/second per endpoint Data format: JSON Fee: Free

Best for: Live scores, game state, win probability estimates, historical data collection

import requests

# Today's NBA games
data = requests.get(
    "https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard"
).json()

for event in data["events"]:
    game = event["competitions"][0]
    home = game["competitors"][0]
    away = game["competitors"][1]
    print(f"{away['team']['abbreviation']} @ {home['team']['abbreviation']}: "
          f"{away['score']}-{home['score']}")

Supported sports: | Sport | Endpoint | |-------|----------| | NBA | basketball/nba | | NFL | football/nfl | | NCAAMB | basketball/mens-college-basketball | | NHL | hockey/nhl | | MLB | baseball/mlb | | CFB | football/college-football | | Soccer | soccer/eng.1 (EPL), soccer/esp.1 (La Liga) |

Strengths: Free, comprehensive, includes ESPN win probability, all major sports Weaknesses: Undocumented (could change), 10-15s latency, no guaranteed uptime

Full tutorial: ESPN API Python Tutorial


4. The Odds API (Sportsbook Aggregator)

The Odds API aggregates real-time odds from DraftKings, FanDuel, BetMGM, Caesars, and 15+ other sportsbooks.

Official docs: the-odds-api.com/liveapi Authentication: API key (free tier: 500 requests/month) Rate limits: Per-plan (free: 500/month, $5: 100K/month) Data format: JSON Fee: $0-$5/month for API access

Best for: Cross-venue price comparison, devigging sportsbook lines, CLV tracking

import requests

API_KEY = "your_key_here"
resp = requests.get(
    "https://api.the-odds-api.com/v4/sports/basketball_nba/odds",
    params={
        "apiKey": API_KEY,
        "regions": "us",
        "markets": "h2h",
        "oddsFormat": "american",
        "bookmakers": "draftkings,fanduel,betmgm",
    }
).json()

for event in resp:
    print(f"{event['away_team']} @ {event['home_team']}")
    for bm in event["bookmakers"]:
        for market in bm["markets"]:
            for outcome in market["outcomes"]:
                print(f"  {bm['key']}: {outcome['name']} {outcome['price']}")

Devigging (removing the bookmaker's margin):

def american_to_implied(odds):
    if odds > 0:
        return 100.0 / (odds + 100.0)
    return abs(odds) / (abs(odds) + 100.0)

def devig(home_odds, away_odds):
    home_raw = american_to_implied(home_odds)
    away_raw = american_to_implied(away_odds)
    total = home_raw + away_raw  # >1.0 because of vig
    return home_raw / total, away_raw / total  # true probabilities

Strengths: Aggregates 15+ sportsbooks, clean format, affordable Weaknesses: No execution (read-only), 30-60s latency on live odds

Full guide: Multi-Venue Edge Detection


Comparison Table

Feature Polymarket Kalshi ESPN The Odds API
Auth API key + wallet Email + JWT None API key
Execution Yes Yes No No
Real-time WebSocket Polling Polling Polling
Free tier Full access Full access Unlimited 500 req/mo
Sports 9+ 6 7+ 6
Best for Trading Regulated trading Data/scores Odds comparison
Python lib py-clob-client requests requests requests
Latency <1s (WS) 1-2s 10-15s 30-60s

Building a Multi-Source Pipeline

The most powerful approach combines all four:

  1. ESPN for live scores and game state (free, comprehensive)
  2. Your ML model trained on ESPN data to predict fair win probability
  3. Polymarket for real-time market prices and execution
  4. The Odds API for sportsbook prices as confirmation signals

When your model disagrees with Polymarket AND DraftKings/FanDuel agree with your model, you have a high-confidence edge. When your model disagrees with everyone, you're probably wrong.

We built this exact pipeline. It runs on a $7/month VPS, polls ESPN every 5 seconds, receives Polymarket prices via WebSocket, and checks sportsbook odds every 2 minutes. The complete system is taught step-by-step in our course.


This guide is maintained by ZenHodl. Last updated April 2026. API endpoints and authentication methods may change — check official documentation for the latest.

Related reading

Get ZenHodl Weekly

One weekly email with live results, one model insight, and product updates.

Tuesday mornings. No spam.

Want to build this yourself?

The ZenHodl course teaches you to build a complete prediction market bot in 6 notebooks.

Join the community

Discuss strategies, share results, get help.

Join Discord