BALLDONTLIE Lab API
Build, backtest, and deploy betting models programmatically. The Lab API gives you access to pre-built analytical factors, model creation, historical backtesting, and prediction generation across multiple sports.
Quick Start
- Create an account at lab-app.balldontlie.io
- Upgrade to PRO or ALL-ACCESS (free tiers cannot access the API)
- Grab your API key from your account settings
Authentication
All endpoints require authentication via API key in the Authorization header:
curl "https://api.balldontlie.io/lab/v1/factors" \
-H "Authorization: YOUR_API_KEY"
Rate Limits
| Limit | Value |
|---|---|
| Requests per minute | 100 |
Rate limit headers are included in every response:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per minute |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when the limit resets |
Supported Sports
| Sport | Code | Status |
|---|---|---|
| NBA | nba | Available |
| NFL | nfl | Available |
| NHL | nhl | Available |
| MLB | mlb | Available |
Subscription Tiers
| Tier | Backtest History | Models | API Access |
|---|---|---|---|
| ALL-ACCESS | Full available history | Unlimited | Full |
| LAB PRO | Full available history | Unlimited | Full |
Subscribe at lab-app.balldontlie.io to get started.
Base URL
https://api.balldontlie.ioOpenAPI Specification
Download or view the full OpenAPI specification for use with tools like Postman, Swagger UI, or code generators.
Download OpenAPI Spec (YAML)/lab/v1/factorsList all factors
Returns all available factors for building prediction models.
Factors are pre-built analytical components that can be combined to create models.
Parameters
categoryFilter by factor category (team_performance, matchup, situational, player, market)
sportFilter by sport (default nba)
Responses
dataFactor[]{
"data": [
{
"id": 1,
"slug": "team_last_n_pts_avg",
"name": "Team Last N Games Scoring Average",
"description": "Average points scored by team in their last N games.",
"category": "team_performance",
"sport": "nba",
"output_type": "points",
"raw_value_unit": "points per game",
"configurable_params": {
"n_games": {
"type": "integer",
"default": 10,
"min": 3,
"max": 30,
"description": "Number of recent games to average"
}
}
},
{
"id": 2,
"slug": "team_last_n_pts_allowed_avg",
"name": "Team Last N Games Points Allowed Average",
"description": "Average points allowed by team in their last N games.",
"category": "team_performance",
"sport": "nba",
"output_type": "points",
"raw_value_unit": "points per game",
"configurable_params": {
"n_games": {
"type": "integer",
"default": 10,
"min": 3,
"max": 30,
"description": "Number of recent games to average"
}
}
}
]
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/factors" \
-H "Authorization: YOUR_API_KEY"/lab/v1/factors/{id}Get a factor
Returns details of a specific factor.
Parameters
idFactor ID
Responses
dataFactor{
"id": 1,
"slug": "team_last_n_pts_avg",
"name": "Team Last N Games Scoring Average",
"description": "Average points scored by team in their last N games. Higher scoring indicates stronger offense.",
"category": "team_performance",
"sport": "nba",
"output_type": "points",
"raw_value_unit": "points per game",
"configurable_params": {
"n_games": {
"type": "integer",
"default": 10,
"min": 3,
"max": 30,
"description": "Number of recent games to average"
},
"home_only": {
"type": "boolean",
"default": false,
"description": "Only include home games"
},
"away_only": {
"type": "boolean",
"default": false,
"description": "Only include away games"
}
}
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/factors/{id}" \
-H "Authorization: YOUR_API_KEY"/lab/v1/modelsList user's models
Returns all models owned by the authenticated user.
Parameters
sportFilter by sport
bet_typeFilter by bet type
per_pageNumber of results per page
cursorCursor for pagination
Responses
dataModel[]metaCursorPagination{
"data": [
{
"id": 1,
"name": "Momentum Tracker",
"description": "Tracks team momentum",
"sport": "nba",
"bet_type": "spread",
"mode": "simple",
"advanced_config": null,
"created_at": "2026-01-31T22:08:30.516Z",
"updated_at": "2026-01-31T22:08:30.516Z",
"factors": [
{
"factor_id": 1,
"factor_slug": "team_last_n_pts_avg",
"factor_name": "Team Last N Games Scoring Average",
"importance": "high",
"weight": null,
"parameters": null,
"conditions": null
}
]
}
],
"meta": {
"per_page": 25
}
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/models" \
-H "Authorization: YOUR_API_KEY"/lab/v1/modelsCreate a model
Creates a new prediction model.
For weighted mode, factor weights must sum to 100.
Request Body
namestringrequiredModel name
descriptionstringModel description
sportSportSupported sports
nbanhlnflmlbbet_typeBetTyperequiredType of bet the model predicts
spreadmoneylineover_undermodel_typeModelTypeType of model: - game: Predicts game-level outcomes (spread, moneyline, over/under) - player_prop: Predicts individual player stat lines (over/under the prop line)
gameplayer_propprop_typePropTypeStat type for player prop models (required when model_type is player_prop). NBA supports points, rebounds, assists, steals, blocks, and threes. NFL supports passing yards, passing touchdowns, passing attempts, passing completions, interceptions thrown, rushing yards, rushing attempts, receiving yards, receptions, and rushing plus receiving yards. MLB supports hits, total bases, home runs, RBIs, hits+runs+RBIs, runs, walks, stolen bases, singles, doubles, triples, pitcher strikeouts, pitcher outs, pitcher earned runs, pitcher hits allowed, and pitcher walks.
pointsreboundsassistsstealsblocksthreespassing_yardspassing_tdspassing_attemptspassing_completionsinterceptionsrushing_yardsrushing_attemptsreceiving_yardsreceptionsrushing_receiving_yardshitstotal_baseshome_runsrbishits_runs_rbisruns_scoredwalksstolen_basessinglesdoublestriplespitcher_strikeoutspitcher_outspitcher_earned_runspitcher_hits_allowedpitcher_walksmodeModelModerequiredModel calculation mode: - simple: Assign importance (Low/Medium/High) to each factor - weighted: Assign precise weights that must sum to 100%
simpleweightedadvanced_configAdvancedConfigfactorsModelFactorInput[]requiredFactors to include in the model
{
"name": "Momentum Tracker",
"description": "Tracks team momentum using recent scoring and ATS performance",
"bet_type": "spread",
"mode": "simple",
"factors": [
{
"factor_id": 1,
"importance": "high"
},
{
"factor_id": 4,
"importance": "high"
},
{
"factor_id": 10,
"importance": "medium"
}
]
}Responses
dataModel{
"id": 1,
"name": "Momentum Tracker",
"description": "Tracks team momentum using recent scoring and ATS performance",
"sport": "nba",
"bet_type": "spread",
"mode": "simple",
"advanced_config": null,
"created_at": "2026-01-31T22:08:30.516Z",
"updated_at": "2026-01-31T22:08:30.516Z",
"factors": [
{
"factor_id": 1,
"factor_slug": "team_last_n_pts_avg",
"factor_name": "Team Last N Games Scoring Average",
"importance": "high",
"weight": null,
"parameters": null,
"conditions": null
},
{
"factor_id": 4,
"factor_slug": "team_ats_record",
"factor_name": "Team Against The Spread Record",
"importance": "high",
"weight": null,
"parameters": null,
"conditions": null
},
{
"factor_id": 10,
"factor_slug": "rest_days",
"factor_name": "Rest Days Advantage",
"importance": "medium",
"weight": null,
"parameters": null,
"conditions": null
}
]
}Example Request
curl -X POST "https://api.balldontlie.io/lab/v1/models" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Momentum Tracker",
"description": "Tracks team momentum using recent scoring and ATS performance",
"bet_type": "spread",
"mode": "simple",
"factors": [
{
"factor_id": 1,
"importance": "high"
},
{
"factor_id": 4,
"importance": "high"
},
{
"factor_id": 10,
"importance": "medium"
}
]
}'/lab/v1/models/{id}Get a model
Returns details of a specific model owned by the user.
Parameters
idModel ID
Responses
dataModel{
"id": 1,
"name": "Momentum Tracker",
"description": "Tracks team momentum using recent scoring and ATS performance",
"sport": "nba",
"bet_type": "spread",
"mode": "simple",
"advanced_config": null,
"created_at": "2026-01-31T22:08:30.516Z",
"updated_at": "2026-01-31T22:08:30.516Z",
"factors": [
{
"factor_id": 1,
"factor_slug": "team_last_n_pts_avg",
"factor_name": "Team Last N Games Scoring Average",
"importance": "high",
"weight": null,
"parameters": null,
"conditions": null
},
{
"factor_id": 4,
"factor_slug": "team_ats_record",
"factor_name": "Team Against The Spread Record",
"importance": "high",
"weight": null,
"parameters": null,
"conditions": null
},
{
"factor_id": 10,
"factor_slug": "rest_days",
"factor_name": "Rest Days Advantage",
"importance": "medium",
"weight": null,
"parameters": null,
"conditions": null
}
]
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/models/{id}" \
-H "Authorization: YOUR_API_KEY"/lab/v1/models/{id}Update a model
Updates an existing model.
For weighted mode, factor weights must sum to 100.
Note: Editing factors, mode, bet_type, prop_type, or advanced_config clears any existing performance and predictions data.
Parameters
idModel ID
Request Body
namestringModel name
descriptionstringModel description
bet_typeBetTypeType of bet the model predicts
spreadmoneylineover_undermodel_typeModelTypeType of model: - game: Predicts game-level outcomes (spread, moneyline, over/under) - player_prop: Predicts individual player stat lines (over/under the prop line)
gameplayer_propprop_typePropTypeStat type for player prop models (required when model_type is player_prop). NBA supports points, rebounds, assists, steals, blocks, and threes. NFL supports passing yards, passing touchdowns, passing attempts, passing completions, interceptions thrown, rushing yards, rushing attempts, receiving yards, receptions, and rushing plus receiving yards. MLB supports hits, total bases, home runs, RBIs, hits+runs+RBIs, runs, walks, stolen bases, singles, doubles, triples, pitcher strikeouts, pitcher outs, pitcher earned runs, pitcher hits allowed, and pitcher walks.
pointsreboundsassistsstealsblocksthreespassing_yardspassing_tdspassing_attemptspassing_completionsinterceptionsrushing_yardsrushing_attemptsreceiving_yardsreceptionsrushing_receiving_yardshitstotal_baseshome_runsrbishits_runs_rbisruns_scoredwalksstolen_basessinglesdoublestriplespitcher_strikeoutspitcher_outspitcher_earned_runspitcher_hits_allowedpitcher_walksmodeModelModeModel calculation mode: - simple: Assign importance (Low/Medium/High) to each factor - weighted: Assign precise weights that must sum to 100%
simpleweightedadvanced_configAdvancedConfigfactorsModelFactorInput[]Factors to include in the model
{
"name": "string",
"description": "string",
"bet_type": "spread",
"model_type": "game",
"prop_type": "points"
}Responses
dataModel{
"id": 1,
"name": "Momentum Tracker",
"description": "Tracks team momentum using recent scoring and ATS performance",
"sport": "nba",
"bet_type": "spread",
"mode": "simple",
"advanced_config": null,
"created_at": "2026-01-31T22:08:30.516Z",
"updated_at": "2026-01-31T22:08:30.516Z",
"factors": [
{
"factor_id": 1,
"factor_slug": "team_last_n_pts_avg",
"factor_name": "Team Last N Games Scoring Average",
"importance": "high",
"weight": null,
"parameters": null,
"conditions": null
},
{
"factor_id": 4,
"factor_slug": "team_ats_record",
"factor_name": "Team Against The Spread Record",
"importance": "high",
"weight": null,
"parameters": null,
"conditions": null
},
{
"factor_id": 10,
"factor_slug": "rest_days",
"factor_name": "Rest Days Advantage",
"importance": "medium",
"weight": null,
"parameters": null,
"conditions": null
}
]
}Example Request
curl -X PUT "https://api.balldontlie.io/lab/v1/models/{id}" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"description": "string",
"bet_type": "spread",
"model_type": "game",
"prop_type": "points"
}'/lab/v1/models/{id}Delete a model
Deletes a model and all associated data (predictions, performance, jobs).
Parameters
idModel ID
Responses
Example Request
curl -X DELETE "https://api.balldontlie.io/lab/v1/models/{id}" \
-H "Authorization: YOUR_API_KEY"/lab/v1/predictionsList predictions for a model
Returns predictions for a specific model with game details.
Parameters
model_idModel ID (required)
resultFilter by result (win, loss, push)
start_dateFilter by start date (ISO8601)
end_dateFilter by end date (ISO8601)
per_pageNumber of results per page
cursorCursor for pagination
Responses
dataPredictionWithGame[]metaCursorPagination{
"data": [],
"meta": {
"per_page": 25
}
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/predictions" \
-H "Authorization: YOUR_API_KEY"/lab/v1/predictions/statsGet prediction statistics
Returns aggregate statistics for a model's predictions.
Parameters
model_idModel ID (required)
Responses
dataPredictionStats{
"data": {
"total": 0,
"wins": 0,
"losses": 0,
"pushes": 0,
"win_rate": 0
}
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/predictions/stats" \
-H "Authorization: YOUR_API_KEY"/lab/v1/predictions/{id}Get a prediction
Returns details of a specific prediction.
Parameters
idPrediction ID
Responses
dataPrediction{
"data": {
"id": 48,
"model_id": 175,
"game_id": 18447533,
"predicted_value": 5,
"confidence": 0.05,
"market_value": 0,
"edge": null,
"actual_value": null,
"result": null,
"home_ml": -110,
"away_ml": -110,
"created_at": "2026-02-01T20:37:06.510Z",
"resolved_at": null
}
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/predictions/{id}" \
-H "Authorization: YOUR_API_KEY"/lab/v1/models/{id}/predictions/generateGenerate predictions
Creates a background job to generate predictions for upcoming games.
Poll the job endpoint to get results.
Note: Only one prediction generation job can run per model at a time. If a pending
or running job already exists, a 409 Conflict is returned.
Parameters
idModel ID
Responses
dataJob{
"data": {
"id": "6e931b7f-736f-4386-b8a2-1cfa8565e8a8",
"model_id": 175,
"job_type": "generate_predictions",
"status": "pending",
"output": null,
"error_message": null,
"created_at": "2026-02-01T20:36:55.874Z",
"started_at": null,
"completed_at": null
}
}Example Request
curl -X POST "https://api.balldontlie.io/lab/v1/models/{id}/predictions/generate" \
-H "Authorization: YOUR_API_KEY"/lab/v1/performance/previewCreate preview job
Creates a background job to preview model performance without saving.
Returns historical performance. The response retains an empty predictions array for compatibility;
use a saved model's prediction-generation endpoint for upcoming games.
Poll the job endpoint to get results.
Request Body
bet_typeBetTyperequiredType of bet the model predicts
spreadmoneylineover_undermodeModelModerequiredModel calculation mode: - simple: Assign importance (Low/Medium/High) to each factor - weighted: Assign precise weights that must sum to 100%
simpleweightedsportSportSupported sports
nbanhlnflmlbmodel_typeModelTypeType of model: - game: Predicts game-level outcomes (spread, moneyline, over/under) - player_prop: Predicts individual player stat lines (over/under the prop line)
gameplayer_propprop_typePropTypeStat type for player prop models (required when model_type is player_prop). NBA supports points, rebounds, assists, steals, blocks, and threes. NFL supports passing yards, passing touchdowns, passing attempts, passing completions, interceptions thrown, rushing yards, rushing attempts, receiving yards, receptions, and rushing plus receiving yards. MLB supports hits, total bases, home runs, RBIs, hits+runs+RBIs, runs, walks, stolen bases, singles, doubles, triples, pitcher strikeouts, pitcher outs, pitcher earned runs, pitcher hits allowed, and pitcher walks.
pointsreboundsassistsstealsblocksthreespassing_yardspassing_tdspassing_attemptspassing_completionsinterceptionsrushing_yardsrushing_attemptsreceiving_yardsreceptionsrushing_receiving_yardshitstotal_baseshome_runsrbishits_runs_rbisruns_scoredwalksstolen_basessinglesdoublestriplespitcher_strikeoutspitcher_outspitcher_earned_runspitcher_hits_allowedpitcher_walksadvanced_configAdvancedConfigfactorsPreviewFactorInput[]requiredFactors for the preview
seasononeOfNBA/NHL use YYYY-YY; NFL/MLB use YYYY. Game-model history starts in 2020, while NFL and MLB player-prop history starts in 2025. Omit for the account's default access window.
{
"bet_type": "spread",
"mode": "simple",
"factors": [
{
"factor_id": 1,
"importance": "high"
},
{
"factor_id": 2,
"importance": "medium"
}
]
}Responses
dataJob{
"id": "616aacdb-1501-47d9-b09c-ac3164f6885b",
"model_id": null,
"job_type": "preview",
"status": "pending",
"output": null,
"error_message": null,
"created_at": "2026-01-31T22:15:59.724Z",
"started_at": null,
"completed_at": null
}Example Request
curl -X POST "https://api.balldontlie.io/lab/v1/performance/preview" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"bet_type": "spread",
"mode": "simple",
"factors": [
{
"factor_id": 1,
"importance": "high"
},
{
"factor_id": 2,
"importance": "medium"
}
]
}'/lab/v1/models/{id}/performanceGet model performance
Returns performance evaluation results for a model.
Returns null if evaluation has not been run yet.
Parameters
idModel ID
Responses
dataoneOf{
"data": null
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/models/{id}/performance" \
-H "Authorization: YOUR_API_KEY"/lab/v1/models/{id}/performanceTrigger performance evaluation
Creates a background job to run performance evaluation for a model against historical data.
Returns immediately with a job object - poll the job endpoint to get results.
Keeps the last completed performance visible while the new evaluation runs and replaces it only after success.
Season Format: NBA/NHL use "YYYY-YY" (for example "2025-26"); NFL/MLB use "YYYY".
Game-model seasons are supported from 2020 through the current sport season. NFL and MLB player-prop seasons are supported from 2025 onward. The current season rolls over automatically.
Note: Only one evaluation job can run per model at a time. If a pending or running
evaluation job already exists, a 409 Conflict is returned.
Parameters
idModel ID
Request Body
seasononeOfNBA/NHL use YYYY-YY (for example 2025-26); NFL/MLB use YYYY. Game-model history starts in 2020, while NFL and MLB player-prop history starts in 2025. The latest season rolls over automatically at that sport's configured start month.
{
"season": "string"
}Responses
dataJob{
"data": {
"id": "81cea460-5e30-4f15-9e0d-9493541a3c7d",
"model_id": 1,
"job_type": "evaluate",
"status": "pending",
"output": null,
"error_message": null,
"created_at": "2026-01-31T22:14:50.285Z",
"started_at": null,
"completed_at": null
}
}Example Request
curl -X POST "https://api.balldontlie.io/lab/v1/models/{id}/performance" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"season": "string"
}'/lab/v1/models/{id}/performanceClear performance data
Clears all performance evaluation data for a model.
Parameters
idModel ID
Responses
Example Request
curl -X DELETE "https://api.balldontlie.io/lab/v1/models/{id}/performance" \
-H "Authorization: YOUR_API_KEY"/lab/v1/models/{id}/performance/gamesGet per-game performance details
Returns paginated per-game breakdown of performance evaluation.
Parameters
idModel ID
limitNumber of results per page
offsetNumber of results to skip
resultFilter by result
winlosspushpendingResponses
dataPerformanceGameResult[]metaOffsetPagination{
"data": [
{
"date": "2024-10-22",
"result": "loss",
"game_id": 15907439,
"away_team": {
"id": 18,
"name": "Timberwolves",
"abbreviation": "MIN"
},
"home_team": {
"id": 14,
"name": "Lakers",
"abbreviation": "LAL"
},
"is_future": false,
"away_score": 103,
"confidence": 0,
"home_score": 110,
"market_value": 1.5,
"factor_details": {
"away": [
{
"score": 80,
"raw_value": 7,
"parameters": {},
"factor_slug": "rest_days"
},
{
"score": 50,
"raw_value": 50,
"parameters": {
"n_games": 20
},
"factor_slug": "team_ats_record"
}
],
"home": [
{
"score": 80,
"raw_value": 7,
"parameters": {},
"factor_slug": "rest_days"
},
{
"score": 50,
"raw_value": 50,
"parameters": {
"n_games": 20
},
"factor_slug": "team_ats_record"
}
]
},
"predicted_side": "away",
"away_model_score": 53,
"home_model_score": 53
}
],
"meta": {
"total": 1321,
"limit": 25,
"offset": 0
}
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/models/{id}/performance/games" \
-H "Authorization: YOUR_API_KEY"/lab/v1/jobs/{id}Get job status
Returns the status and output of a background job.
Poll this endpoint until status is "completed" or "failed".
Parameters
idJob ID (UUID)
Responses
dataJob{
"id": "81cea460-5e30-4f15-9e0d-9493541a3c7d",
"model_id": 1,
"job_type": "generate_predictions",
"status": "pending",
"output": null,
"error_message": null,
"created_at": "2026-01-31T22:14:50.285Z",
"started_at": null,
"completed_at": null
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/jobs/{id}" \
-H "Authorization: YOUR_API_KEY"/lab/v1/jobs/{id}Cancel a job
Cancels a pending or running job. Only jobs with status "pending" or "running" can be cancelled.
Cancelled jobs have their status set to "cancelled" with error message "Cancelled by user".
Parameters
idJob ID (UUID)
Responses
dataJob{
"id": "81cea460-5e30-4f15-9e0d-9493541a3c7d",
"model_id": 1,
"job_type": "evaluate",
"status": "cancelled",
"output": null,
"error_message": "Cancelled by user",
"created_at": "2026-01-31T22:14:50.285Z",
"started_at": null,
"completed_at": "2026-01-31T22:15:02.123Z"
}Example Request
curl -X DELETE "https://api.balldontlie.io/lab/v1/jobs/{id}" \
-H "Authorization: YOUR_API_KEY"/lab/v1/models/{id}/jobs/activeGet active jobs for a model
Returns all pending and running jobs for a specific model.
Used to determine if a model has jobs in progress that would prevent new jobs from being created.
Parameters
idModel ID
Responses
dataJob[]{
"data": [
{
"id": "81cea460-5e30-4f15-9e0d-9493541a3c7d",
"model_id": 1,
"job_type": "evaluate",
"status": "running",
"output": null,
"error_message": null,
"created_at": "2026-01-31T22:14:50.285Z",
"started_at": "2026-01-31T22:14:51.212Z",
"completed_at": null
}
]
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/models/{id}/jobs/active" \
-H "Authorization: YOUR_API_KEY"