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 | 6 years | Unlimited | Full |
| LAB PRO | 6 years | Unlimited | Full |
Subscribe at lab-app.balldontlie.io to get started.
Base URL
https://api.balldontlie.io/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": "string",
"name": "string",
"description": "string",
"category": "string"
}
]
}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{
"data": {
"id": 1,
"slug": "string",
"name": "string",
"description": "string",
"category": "string"
}
}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": [
null
],
"meta": {
"next_cursor": 1,
"prev_cursor": 1,
"per_page": 1
}
}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_underplayer_propprop_typestringSpecific prop type (for player_prop bet_type)
modeModelModerequiredModel calculation mode: - simple: Assign importance (Low/Medium/High) to each factor - weighted: Assign precise weights that must sum to 100%
simpleweightedfactorsModelFactorInput[]requiredFactors to include in the model
{
"name": "string",
"description": "string",
"sport": "nba",
"bet_type": "spread",
"prop_type": "string"
}Responses
dataModel{
"data": 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": "string",
"description": "string",
"sport": "nba",
"bet_type": "spread",
"prop_type": "string"
}'/lab/v1/models/{id}Get a model
Returns details of a specific model owned by the user.
Parameters
idModel ID
Responses
dataModel{
"data": 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, or advanced_config clears any existing performance data.
Parameters
idModel ID
Request Body
namestringModel name
descriptionstringModel description
bet_typeBetTypeType of bet the model predicts
spreadmoneylineover_underplayer_propprop_typestringSpecific prop type (for player_prop bet_type)
modeModelModeModel calculation mode: - simple: Assign importance (Low/Medium/High) to each factor - weighted: Assign precise weights that must sum to 100%
simpleweightedfactorsModelFactorInput[]Factors to include in the model
{
"name": "string",
"description": "string",
"bet_type": "spread",
"prop_type": "string",
"mode": "simple"
}Responses
dataModel{
"data": 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",
"prop_type": "string",
"mode": "simple"
}'/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": [
null
],
"meta": {
"next_cursor": 1,
"prev_cursor": 1,
"per_page": 1
}
}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": 1,
"wins": 1,
"losses": 1,
"pushes": 1,
"win_rate": 0.5
}
}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": 1,
"model_id": 1,
"game_id": 1,
"predicted_value": 0.5,
"confidence": 0.5
}
}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": "550e8400-e29b-41d4-a716-446655440000",
"model_id": 1,
"job_type": "preview",
"status": "pending",
"output": 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 and predictions for upcoming games.
Poll the job endpoint to get results.
Request Body
bet_typeBetTyperequiredType of bet the model predicts
spreadmoneylineover_underplayer_propmodeModelModerequiredModel calculation mode: - simple: Assign importance (Low/Medium/High) to each factor - weighted: Assign precise weights that must sum to 100%
simpleweightedsportSportSupported sports
nbanhlnflmlbadvanced_configAdvancedConfigfactorsPreviewFactorInput[]requiredFactors for the preview
start_seasonstringStart season (format "YYYY-YY", e.g., "2023-24")
end_seasonstringEnd season (format "YYYY-YY", e.g., "2024-25")
{
"bet_type": "spread",
"mode": "simple",
"sport": "nba",
"advanced_config": null,
"factors": [
{
"factor_id": 1,
"importance": "low",
"weight": 0,
"parameters": {}
}
]
}Responses
dataJob{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"model_id": 1,
"job_type": "preview",
"status": "pending",
"output": 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",
"sport": "nba",
"advanced_config": null,
"factors": [
{
"factor_id": 1,
"importance": "low",
"weight": 0,
"parameters": {}
}
]
}'/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.
Clears any existing performance data before running.
Season Format: "YYYY-YY" (e.g., "2024-25")
Allowed Seasons: 2020-21 through 2025-26
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
start_seasonstringStart season (format "YYYY-YY", e.g., "2024-25"). Allowed range 2020-21 to 2025-26.
end_seasonstringEnd season (format "YYYY-YY", e.g., "2024-25"). Allowed range 2020-21 to 2025-26.
{
"start_season": "string",
"end_season": "string"
}Responses
dataJob{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"model_id": 1,
"job_type": "preview",
"status": "pending",
"output": 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 '{
"start_season": "string",
"end_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": [
{
"game_id": 1,
"date": "2024-01-15",
"home_team": {
"id": "...",
"abbreviation": "...",
"name": "..."
},
"away_team": {
"id": "...",
"abbreviation": "...",
"name": "..."
},
"home_score": 1
}
],
"meta": {
"total": 1,
"limit": 1,
"offset": 1
}
}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{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"model_id": 1,
"job_type": "preview",
"status": "pending",
"output": 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 pending job
Cancels a pending job. Only jobs with status "pending" can be cancelled.
Running jobs cannot be cancelled as they are already being processed.
Cancelled jobs have their status set to "failed" with error message "Cancelled by user".
Parameters
idJob ID (UUID)
Responses
dataJob{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"model_id": 1,
"job_type": "preview",
"status": "pending",
"output": null
}
}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": "550e8400-e29b-41d4-a716-446655440000",
"model_id": 1,
"job_type": "preview",
"status": "pending",
"output": null
}
]
}Example Request
curl -X GET "https://api.balldontlie.io/lab/v1/models/{id}/jobs/active" \
-H "Authorization: YOUR_API_KEY"