Load historical odds into a data warehouse
An ETL pattern for pulling closing lines and historical odds into pandas, DuckDB, or a warehouse without pagination glue.
Who this is for
Data engineers and quants who want the odds archive next to their own tables: closing lines in a warehouse, joined to results and model outputs, refreshed on a schedule instead of queried ad hoc.
- Check /historical/coverage so the load window matches the archive
- Loop the prop closing CSV export one day at a time into your store
- Pull game-line closes per sport with the closing-odds endpoint
- Join to your results tables and grade models in SQL
The three endpoints this build uses
GET /v1/historical/closing-lines.csvDaily prop closing-line dump as CSV, one day per request, metered per 1,000 delivered rows and built for flat-file loads into pandas or DuckDB.GET /v1/historical/sports/{sport_key}/closing-oddsGame-line and prop closing prices per event, market, and book, with date-range filters for the JSON side of the load.GET /v1/historical/coveragePublic, no-auth coverage stats: rows, span, and sources per sport, so the pipeline never assumes data that is not there.Working code
import pandas as pd
# The CSV export is a daily dump: one day per request, so loop the range.
frames = [
pd.read_csv(
"https://parlay-api.com/v1/historical/closing-lines.csv"
f"?date={day.date()}&sport_key=baseball_mlb&apiKey=YOUR_KEY"
)
for day in pd.date_range("2026-06-01", "2026-06-07")
]
closes = pd.concat(frames)
# duckdb.sql("CREATE TABLE closes AS SELECT * FROM closes")
Which tier fits
Every tier includes the historical read endpoints inside its lookback window, 48 hours on free keys and deeper on each paid tier listed at /pricing, so warehouse backfills want the longer windows. Historical odds requests meter at ten times live odds. The coverage endpoint is public, so scope the load before paying anything. Current limits are on the pricing page.
Example repo
Start from sports-odds-datasets, an open-source starting point for this exact build.
Build links
/answers/get-historical-closing-lines/answers/historical-player-props-api/historical-coverage