Skip to main content

Production-grade alternative sports data feed — odds, events, futures, settlement for 30 leagues

Project description

AltSportsData SDK

PyPI Python 3.8+

Production-grade alternative sports data feed — odds, events, futures, settlement for 30 leagues.

Original model-generated probabilities for sports nobody else can price. Built for prediction markets, DFS platforms, and sportsbooks.

pip install altsportsdata

Quick Start

from altsportsdata import AltSportsData

client = AltSportsData(api_key="your_key")

# Discover what's available — every response is a DataFrame
leagues = client.get_leagues()
print(leagues)
league      name                                data_shape  archetype         market_count  markets
──────────  ──────────────────────────────────  ──────────  ────────────────  ────────────  ────────────────────────
spr         Supercross                          field       racing            6             matchup, moneyline, ...
wsl         World Surf League                   bracket     heat_elimination  6             heat_winner, matchup...
bkfc        Bare Knuckle Fighting Championship  match       combat            1             heat_winner
f1          Formula 1                           field       racing            9             matchup, moneyline, ...
# Scope to a league — instant self-documenting discovery
spr = client.get_league("spr")
spr.data_shape       # → "field"  (large field, position markets)
spr.archetype        # → "racing"
spr.markets          # → ["matchup", "moneyline", "podium", "show", ...]
spr.describe()       # → pretty ASCII market menu with method names

# Get odds — straight to DataFrame
events = spr.get_events(status="upcoming")
odds = spr.get_moneylines(events[0].id)
print(odds)          # clean table
odds.df              # pandas DataFrame

For Prediction Markets (Kalshi, Polymarket)

Fair probabilities, vig-free, summing to 1.0. Ready for contract creation.

client = AltSportsData(api_key="your_key", odds_format="probability")
spr = client.get_league("spr")

# What kind of contracts should I create?
spr.data_shape          # → "field" — many binary contracts per event
hints = spr.contract_hints
hints["contract_types"]     # → ["outright_winner", "top_n_finish", "exacta", "head_to_head"]
hints["probability_shape"]  # → "long-tail (favorite ~15-40%, field ~1-10% each)"
hints["settlement"]         # → "Position-based — clear winner, top-N verifiable"

Fair Probabilities (vig-removed)

Raw API odds include bookmaker margin. get_fair_probabilities() removes the vig so probabilities sum to exactly 1.0 — ready for contract pricing.

probs = spr.get_fair_probabilities(event_id)
print(probs)
Fair Probabilities (margin=61.0%)

athlete             fair_probability  raw_odds  margin  outcome_id
──────────────────  ────────────────  ────────  ──────  ──────────────────────────────────
Eli Tomac           0.3069            2.02      61      7247a2d1-6a0e-4ef1-...
Hunter Lawrence     0.2333            2.66      61      69a9aa04-3ea4-416d-...
Ken Roczen          0.1459            4.26      61      d31567d2-65da-48aa-...
Cooper Webb         0.0908            6.84      61      682ab924-2572-46ac-...
# Probabilities sum to exactly 1.0
total = sum(p["fair_probability"] for p in probs)
# → 1.000000

# Create contracts from the data
for p in probs:
    create_contract(
        question=f"Will {p['athlete']} win Indianapolis Supercross?",
        probability=p["fair_probability"],
        settlement_id=p["outcome_id"],
    )

Fair Matchup Probabilities

Head-to-head matchups devigged per pair — each pair sums to 1.0:

matchups = spr.get_fair_matchup_probabilities(event_id)
print(matchups)
Fair Matchup Probabilities

player1           fair_prob1  player2          fair_prob2  margin
────────────────  ──────────  ───────────────  ──────────  ──────
Cooper Webb       0.4046      Ken Roczen       0.5954      6.98
Eli Tomac         0.5620      Hunter Lawrence  0.4380      7.19

Data Shapes — Know What Contracts to Create

Every league has a data shape that tells you the contract structure:

Shape Leagues Contract Pattern
field F1, Supercross, NHRA, Disc Golf... (12) Many binary: "Will X win?", "Top 3?", "Exacta?"
match BKFC, MASL, Power Slap, NLL... (12) One binary per matchup: "Will A beat B?"
bracket WSL, SLS, Formula Drift (3) Layered: heat-level + event-level contracts
f1 = client.get_league("f1")
f1.data_shape       # → "field"
f1.contract_hints   # → full contract guidance

bkfc = client.get_league("bkfc")
bkfc.data_shape     # → "match"

wsl = client.get_league("wsl")
wsl.data_shape      # → "bracket"

Settlement for Contract Resolution

result = client.get_settlement(event_id)
for name, mkt in result["markets"].items():
    for o in mkt.get("winners", []):
        print(f"  ✅ {o['athlete']} — settled at {result['settled_at']}")

For DFS Platforms (PrizePicks, Underdog)

client = AltSportsData(api_key="your_key")

# Head-to-head matchups — ready for pick'em
matchups = client.get_matchups(event_id)
for m in matchups:
    print(f"{m.player1} ({m.odds1:.2f})  vs  {m.player2} ({m.odds2:.2f})")
Cooper Webb (2.31)  vs  Ken Roczen (1.57)
Eli Tomac (1.66)  vs  Hunter Lawrence (2.13)
# Player props + totals
props = client.get_player_props(event_id)
totals = client.get_player_totals(event_id, stat="finishingPosition")

# Everything is a DataFrame
matchups.df.to_csv("matchups.csv")

For Sportsbooks (DraftKings, Bet365, Stake)

# American odds
client = AltSportsData(api_key="your_key", odds_format="american")
odds = client.get_moneylines(event_id)
print(odds)

# Fractional odds (UK books)
client = AltSportsData(api_key="your_key", odds_format="fractional")

Market-First Discovery

Sportsbooks think market-first: "Give me all matchups" — not "give me WSL, then check matchups."

# All head-to-head matchups across every league
client.get_markets(market="matchup")

# All moneylines in racing sports
client.get_markets(market="moneyline", archetype="racing")

# All upcoming markets for one league
wsl = client.get_league("wsl")
wsl.get_markets()

Odds Format Conversion

Set once on the client — all responses auto-convert:

client = AltSportsData(api_key="key", odds_format="probability")  # Kalshi
client = AltSportsData(api_key="key", odds_format="american")     # DraftKings
client = AltSportsData(api_key="key", odds_format="decimal")      # Stake (default)
client = AltSportsData(api_key="key", odds_format="fractional")   # Bet365

Or convert individual values:

from altsportsdata import convert_odds

convert_odds(2.50, "decimal", "american")     # → 150.0
convert_odds(2.50, "decimal", "probability")  # → 0.4
convert_odds(150, "american", "decimal")      # → 2.5
convert_odds("3/2", "fractional", "probability")  # → 0.4

Async Client (Production Infrastructure)

from altsportsdata import AsyncAltSportsData
import asyncio

async def main():
    async with AsyncAltSportsData(api_key="key", odds_format="probability") as client:
        wsl = client.get_league("wsl")
        events = await wsl.get_events(status="upcoming")

        # Batch fetch — all events concurrently
        ids = [e.id for e in events[:20]]
        batch = await client.get_odds_batch(ids, "moneyline")
        for eid, odds in batch.items():
            if "error" not in odds:
                print(f"{eid}: {len(odds.get('eventWinner', []))} outcomes")

asyncio.run(main())

Requires: pip install altsportsdata[async]


Enterprise Reliability

Built for production — automatic retry, rate limit handling, request tracing.

client = AltSportsData(
    api_key="key",
    max_retries=3,        # exponential backoff on 429, 5xx
    retry_backoff=0.5,    # base delay in seconds
    timeout=30,           # per-request timeout
)
  • Automatic exponential backoff with jitter on 429/5xx
  • Respects Retry-After headers
  • Request IDs (X-Request-ID) for debugging
  • Thread-safe session management
  • Context manager support: with AltSportsData(...) as client:

Full API Reference

Setup

from altsportsdata import AltSportsData

# General client
client = AltSportsData(api_key="your_key")

# League-scoped — auto-filters everything
wsl = client.get_league("wsl")
f1  = client.get_league("f1")
spr = client.get_league("spr")

# With options
client = AltSportsData(
    api_key="your_key",
    league="wsl",
    odds_format="probability",
    max_retries=3,
)

Discovery

# All leagues with data shapes and market menus
leagues = client.get_leagues()
print(leagues)        # clean table
df = leagues.df       # pandas DataFrame

# Filter by archetype or market support
client.get_leagues(archetype="racing")
client.get_leagues(market="matchup")
client.get_leagues(archetype="racing", market="exacta")

# League details
info = client.get_league_info("f1")
info["data_shape"]      # → "field"
info["contract_hints"]  # → {contract_types, probability_shape, ...}
info["markets"]         # → ["moneyline", "matchup", ...]

# Self-documenting league card
spr = client.get_league("spr")
spr.describe()          # pretty-prints market menu with methods
spr.data_shape          # → "field"
spr.contract_hints      # → contract creation guidance

# All market types
client.list_market_types()

# Market catalog with event counts
for lg in client.get_market_catalog():
    print(f"{lg['league']:12} upcoming={lg['upcoming_events']}")

Events

events = client.get_events(status="upcoming")        # ResultSet with .df
events = client.get_events(status="live")
events = client.get_events(status="completed")
events = client.get_events(status=["live", "upcoming"])

print(events)        # clean table
df = events.df       # pandas DataFrame
events.to_csv("events.csv")

event = client.get_event("event_id")
participants = client.get_participants("event_id")

Markets (cross-league, prices included)

# Market-first — filter by market type across all leagues
markets = client.get_markets(market="matchup")              # all H2H matchups
markets = client.get_markets(market="moneyline", archetype="racing")

# League-scoped
wsl = client.get_league("wsl")
markets = wsl.get_markets()                                 # all market types
markets = wsl.get_markets(status="live")                    # live only

print(markets)       # clean table
df = markets.df      # pandas DataFrame

Odds (per event) — all return OddsResult with .df

# Sportsbook
odds = client.get_moneylines("event_id")    # event winner
odds = client.get_matchups("event_id")      # head-to-head
odds = client.get_totals("event_id")        # over/under
odds = client.get_exactas("event_id")       # exacta
odds = client.get_podiums("event_id")       # top-3
odds = client.get_heat_winners("event_id")  # heat winner
odds = client.get_fastest_lap("event_id")   # fastest lap

# Prediction market — fair probabilities
probs = client.get_fair_probabilities("event_id")        # vig-removed, sums to 1.0
probs = client.get_fair_matchup_probabilities("event_id") # per-matchup devig
probs = client.get_market_probabilities("event_id")      # raw probs (with vig)
probs = client.get_podium_probabilities("event_id")
probs = client.get_top_finish_probabilities("event_id", top_n=5)

# DFS
odds = client.get_player_props("event_id")
odds = client.get_player_matchups("event_id")
odds = client.get_player_totals("event_id", stat="points")

# Generic — any market by name or alias
odds = client.get_odds("event_id", "moneyline")

# Every OddsResult has .df
print(odds)          # clean table
df = odds.df         # pandas DataFrame
odds.to_csv("odds.csv")

Batch Operations

events = client.get_events(league="spr", status="upcoming")
ids = [e.id for e in events]
batch = client.get_odds_batch(ids, "moneyline", max_concurrent=5)

Settlement

result = client.get_settlement("event_id")
# → {event_id, event_name, league, status, settled_at,
#    markets: {eventWinner: {outcomes, winners}, headToHead: {...}}}

Live Polling

for update in client.poll_odds(event_id, "moneyline", interval=5, max_polls=60):
    print(update)

Futures

client.list_futures()
client.get_futures(tour="tour_id", type="winner")

Odds Conversion (Static)

AltSportsData.convert(2.50, "decimal", "american")     # → 150.0
AltSportsData.convert(2.50, "decimal", "probability")  # → 0.4

30 Leagues × 3 Data Shapes

Field (large competitor pools)

Code League Markets
f1 Formula 1 moneyline, matchup, top_3, top_5, top_10, exacta, over_under, trifecta
spr Supercross moneyline, matchup, podium, show, over_under
motocrs Pro Motocross moneyline, matchup, podium, show, over_under, heat_winner
nhra NHRA Drag Racing moneyline, matchup, heat_winner, over_under
dgpt Disc Golf Pro Tour moneyline, matchup, top_3, top_5, over_under, heat_winner
nrx Nitrocross moneyline, matchup, podium, show, over_under, heat_winner
worldoutlaws World of Outlaws moneyline, matchup, heat_winner, over_under
hlrs High Limit Racing moneyline, matchup, heat_winner, over_under
usac USAC Racing moneyline, matchup, heat_winner, over_under
motoamerica MotoAmerica moneyline, matchup, over_under
sprmtcrs Supermotocross moneyline, matchup, podium, heat_winner, over_under
xgame X Games moneyline, matchup, heat_winner, over_under

Match (two-sided contests)

Code League Markets
bkfc Bare Knuckle FC heat_winner
powerslap Power Slap heat_winner
masl Major Arena Soccer moneyline
nll National Lacrosse League
jaialai Jai Alai moneyline
byb BYB Extreme Fighting heat_winner
lux LUX Fight League heat_winner
raf Real American Freestyle heat_winner
athletesunlimited Athletes Unlimited moneyline, matchup
gsoc Global Soccer
mltt Major League Table Tennis
spectation Spectation heat_winner

Bracket (heat elimination)

Code League Markets
wsl World Surf League moneyline, matchup, heat_winner, podium, props, show
sls Street League Skateboarding moneyline, matchup, heat_winner, podium, props, show
fdrift Formula Drift moneyline, matchup, heat_winner

Links

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

altsportsdata-3.2.1.tar.gz (63.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

altsportsdata-3.2.1-py3-none-any.whl (54.2 kB view details)

Uploaded Python 3

File details

Details for the file altsportsdata-3.2.1.tar.gz.

File metadata

  • Download URL: altsportsdata-3.2.1.tar.gz
  • Upload date:
  • Size: 63.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for altsportsdata-3.2.1.tar.gz
Algorithm Hash digest
SHA256 eef07fbcf0277739000de97a71fd28a4db39857f67ac977de37e1f7ce6e9be3b
MD5 e9a6f7cfe300d49e991faffdf540f186
BLAKE2b-256 47c9248af3d18ff0a11145262087a3084dfeae82297ff95b8b05edd1f4c150ba

See more details on using hashes here.

File details

Details for the file altsportsdata-3.2.1-py3-none-any.whl.

File metadata

  • Download URL: altsportsdata-3.2.1-py3-none-any.whl
  • Upload date:
  • Size: 54.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for altsportsdata-3.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 18b439d85e7aee39617ee074af0ee4c055854cb3ba87f73550bacfc45eab4fa9
MD5 8069d86466c58e260d3fb3f475cf9a2b
BLAKE2b-256 5119dc8e150e2accbf92c825c1748e4454bf23be4d14b1348067640336ff66b0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page