CodeFix Solution

How to Build a Sports Prediction Model with Python and a Live API

April 14, 2026 · 8 min read · Python, API, Machine Learning

Most tutorials on sports prediction stop at "train a model on historical data." That's the easy part. The hard part is getting live, calibrated probabilities during an actual game — the kind you can trade on or build alerts around.

This guide shows you how to go from zero to a working sports prediction system in under 30 minutes using Python and a real-time sports prediction API.

What We're Building

By the end of this tutorial, you'll have:

Prerequisites

Step 1: Get Your API Key

We'll use the ZenHodl Fair Probability API, which serves calibrated ML predictions across 10 sports. It has a 7-day free trial — no credit card required to start.

  1. Go to zenhodl.net/signup and create a free account
  2. Copy your API key from the dashboard

Step 2: Fetch Live Game Predictions

import requests

API_KEY = "your_api_key_here"
BASE_URL = "https://zenhodl.net/v1"

headers = {"X-API-Key": API_KEY}

# Get all live games with fair win probabilities
response = requests.get(f"{BASE_URL}/games", headers=headers)
games = response.json()

for game in games[:5]:
    print(f"{game['away_team']} @ {game['home_team']}")
    print(f"  Score: {game.get('score', 'N/A')}")
    print(f"  Fair WP (home): {game['fair_wp']:.1%}")
    print(f"  Period: {game.get('period', 'N/A')}")
    print()

The fair_wp field is the model's calibrated estimate of the home team's win probability, updated every time the score changes. These aren't raw model outputs — they're post-hoc isotonic-calibrated predictions trained on tens of thousands of resolved games.

Step 3: Detect Edges Against the Market

An "edge" is the gap between what the model thinks a team's true win probability is and what the market is pricing it at:

# Get live edges
response = requests.get(f"{BASE_URL}/edges", headers=headers)
edges = response.json()

print(f"Found {len(edges)} active edges:\n")

for edge in edges:
    print(f"  {edge['team']} ({edge['sport']})")
    print(f"    Market price: {edge['market_price_c']}c")
    print(f"    Fair value:   {edge['fair_prob_c']:.0f}c")
    print(f"    Edge:         +{edge['edge_c']:.1f}c")
    print()

An edge of +8c means the model thinks the team is 8 percentage points more likely to win than the market price implies.

Step 4: Build a Simple Alert System

import time

MIN_EDGE = 8  # Only alert on 8c+ edges

while True:
    response = requests.get(f"{BASE_URL}/edges", headers=headers)
    edges = response.json()

    for edge in edges:
        if edge['edge_c'] >= MIN_EDGE:
            print(f"EDGE ALERT: {edge['team']} ({edge['sport']})")
            print(f"   Market: {edge['market_price_c']}c")
            print(f"   Fair: {edge['fair_prob_c']:.0f}c")
            print(f"   Edge: +{edge['edge_c']:.1f}c")
            print()

    time.sleep(60)

How the Model Works

The API uses XGBoost models trained on historical play-by-play data:

All models are calibrated with isotonic regression so that when the model outputs "70%", the team actually wins ~70% of the time historically.

Step 5: Filter by Sport

# Get only NBA games
response = requests.get(
    f"{BASE_URL}/games",
    headers=headers,
    params={"sport": "NBA"}
)
nba_games = response.json()
print(f"Live NBA games: {len(nba_games)}")

Available sports: NBA, NFL, MLB, NHL, NCAAMB, NCAAWB, CFB, ATP, CS2, LOL, SOCCER

Next Steps

Start building with live sports predictions

Get Free API Key →