PGA API
Welcome to the BALLDONTLIE PGA API, your comprehensive source for PGA Tour data. This API provides access to player information, tournament results, course details, leaderboards, round-by-round statistics, strokes gained metrics, and detailed scorecards. An API key is required. You can obtain an API key by creating a free account on our website. Read the authentication section to learn how to use the API key.
Take a look at our other APIs.
Join us on discord.
AI-Powered Integration
Using the OpenAPI Specification with AI
Our complete OpenAPI specification allows AI assistants to automatically understand and interact with our API. Simply share the spec URL with your AI assistant and describe what you want to build—the AI will handle the technical implementation.
Getting Started with AI:
- Copy this URL:
https://www.balldontlie.io/openapi/pga.yml - Share it with your preferred AI assistant (ChatGPT, Claude, Gemini, etc.)
- Tell the AI what you want to build (e.g., "Create a dashboard showing FedEx Cup standings")
- The AI will read the OpenAPI spec and write the code for you
Example prompts to try:
- "Using the OpenAPI spec at https://www.balldontlie.io/openapi/pga.yml, show me how to get Scottie Scheffler's tournament results"
- "Read the BALLDONTLIE OpenAPI spec and create a Python script that fetches current PGA Tour leaderboards"
- "Help me understand the available PGA endpoints from this OpenAPI spec: https://www.balldontlie.io/openapi/pga.yml"
This makes it incredibly easy for non-technical users, analysts, and researchers to leverage our PGA data without needing to learn programming from scratch.
Google Sheets Integration
Our Google Sheets integration lets you access all the same data available through our API using simple spreadsheet formulas. Perfect for fantasy sports tracking, betting analysis, and sports research.
Quick Start:
- Get your API key from app.balldontlie.io
- Copy our Google Sheets script
- Paste it into your Google Sheet (Extensions > Apps Script)
- Start using functions in your cells
Example functions:
=BDL_PGA_PLAYERS("Scheffler")- Search for players=BDL_PGA_TOURNAMENTS(2026)- Get tournaments=BDL_PGA_TOURNAMENT_RESULTS(tournamentId)- Get results=BDL_PGA_SCORECARDS(tournamentId)- Get scorecards
For full setup instructions and the complete list of 150+ functions, see our Google Sheets Integration Guide.
Account Tiers
There are three different account tiers which provide you access to different types of data. Visit our website to create an account for free.
Paid tiers do not apply across sports. The tier you purchase for PGA will not automatically be applied to other sports. You can purchase the ALL-ACCESS ($499.99/mo) tier to get access to every endpoint for every sport.
Read the table below to see the breakdown.
| Endpoint | Free | ALL-STAR | GOAT |
|---|---|---|---|
| Players | Yes | Yes | Yes |
| Tournaments | Yes | Yes | Yes |
| Courses | Yes | Yes | Yes |
| Tournament Results | No | Yes | Yes |
| Tournament Course Stats | No | Yes | Yes |
| Course Holes | No | Yes | Yes |
| Tournament Field | No | No | Yes |
| Player Round Results | No | No | Yes |
| Player Round Stats | No | No | Yes |
| Player Season Stats | No | No | Yes |
| Player Scorecards | No | No | Yes |
| Futures | No | No | Yes |
The feature breakdown per tier is shown in the table below.
| Tier | Requests / Min | $USD / mo. |
|---|---|---|
| GOAT | 600 | 39.99 |
| ALL-STAR | 60 | 9.99 |
| Free | 5 | 0 |
Authentication
To authorize, use this code:
curl "api_endpoint_here" -H "Authorization: YOUR_API_KEY"
const response = await fetch("https://api.balldontlie.io/pga/v1/players", {
headers: {
Authorization: "YOUR_API_KEY",
},
});
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/players',
headers={'Authorization': 'YOUR_API_KEY'}
)
if response.status_code == 200:
data = response.json()
print(data)
else:
print(f'Error: {response.status_code}')
Make sure to replace
YOUR_API_KEYwith your API key.
BALLDONTLIE uses API keys to allow access to the API. You can obtain an API key by creating a free account at our website
We expect the API key to be included in all API requests to the server in a header that looks like the following:
Authorization: YOUR_API_KEY
Pagination
This API uses cursor based pagination rather than limit/offset. Endpoints that support pagination will send back responses with a meta key that looks like what is displayed on the right.
{
"meta": {
"next_cursor": 90,
"per_page": 25
}
}
You can use per_page to specify the maximum number of results. It defaults to 25 and doesn't allow values larger than 100.
You can use next_cursor to get the next page of results. Specify it in the request parameters like this: ?cursor=NEXT_CURSOR.
Errors
The API uses the following error codes:
| Error Code | Meaning |
|---|---|
| 401 | Unauthorized - You either need an API key or your account tier does not have access to the endpoint. |
| 400 | Bad Request -- The request is invalid. The request parameters are probably incorrect. |
| 404 | Not Found -- The specified resource could not be found. |
| 406 | Not Acceptable -- You requested a format that isn't json. |
| 429 | Too Many Requests -- You're rate limited. |
| 500 | Internal Server Error -- We had a problem with our server. Try again later. |
| 503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |
Players
Get All Players
curl "https://api.balldontlie.io/pga/v1/players?per_page=2" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/players?per_page=2",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/players',
headers={'Authorization': 'YOUR_API_KEY'},
params={'per_page': 2}
)
players = response.json()['data']
for player in players:
print(f"{player['display_name']} ({player['country']})")
The above command returns JSON structured like this:
{
"data": [
{
"id": 1,
"first_name": "Ludvig",
"last_name": "Åberg",
"display_name": "Ludvig Åberg",
"country": "Sweden",
"country_code": "SWE",
"height": "6'3\"",
"weight": "190",
"birth_date": "Oct 31, 1999",
"birthplace_city": "Eslov",
"birthplace_state": null,
"birthplace_country": "Sweden",
"turned_pro": "2023",
"school": "Texas Tech University",
"residence_city": "Ponte Vedra",
"residence_state": "Florida",
"residence_country": "United States",
"owgr": 18,
"active": true
},
{
"id": 2,
"first_name": "Byeong Hun",
"last_name": "An",
"display_name": "Byeong Hun An",
"country": "Republic of Korea",
"country_code": "KOR",
"height": "6'2\"",
"weight": "240",
"birth_date": "Sep 17, 1991",
"birthplace_city": "Seoul",
"birthplace_state": null,
"birthplace_country": "South Korea",
"turned_pro": "2011",
"school": "University of California-Berkeley",
"residence_city": "Orlando",
"residence_state": "Florida",
"residence_country": "United States",
"owgr": 98,
"active": true
}
],
"meta": {
"next_cursor": 2,
"per_page": 2
}
}
This endpoint retrieves PGA Tour players.
HTTP Request
GET https://api.balldontlie.io/pga/v1/players
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| player_ids | integer[] | No | Filter by player IDs |
| search | string | No | Search players by name |
| first_name | string | No | Filter by first name |
| last_name | string | No | Filter by last name |
| country | string | No | Filter by country |
| active | boolean | No | Filter by active status |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Tournaments
Get All Tournaments
curl "https://api.balldontlie.io/pga/v1/tournaments?season=2025&per_page=2" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/tournaments?season=2025&per_page=2",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/tournaments',
headers={'Authorization': 'YOUR_API_KEY'},
params={'season': 2025, 'per_page': 2}
)
tournaments = response.json()['data']
for tournament in tournaments:
print(f"{tournament['name']} - {tournament['start_date']}")
The above command returns JSON structured like this:
{
"data": [
{
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "United States of America",
"course_name": "Plantation Course at Kapalua",
"purse": "$20,000,000",
"status": "COMPLETED",
"champion": {
"id": 130,
"first_name": "Hideki",
"last_name": "Matsuyama",
"display_name": "Hideki Matsuyama",
"country": "Japan",
"country_code": "JPN",
"active": true
},
"courses": [
{
"course": {
"id": 56,
"name": "Plantation Course at Kapalua",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "USA",
"par": 73
},
"rounds": [1, 2, 3, 4]
}
]
},
{
"id": 3,
"season": 2025,
"name": "The American Express",
"start_date": "2025-01-15T19:00:00.000Z",
"end_date": "Jan 16 - 19",
"city": "La Quinta",
"state": "California",
"country": "United States of America",
"course_name": "Pete Dye Stadium Course",
"purse": "$8,400,000",
"status": "COMPLETED",
"champion": null,
"courses": [
{
"course": {
"id": 53,
"name": "La Quinta Country Club",
"city": "La Quinta",
"state": "California",
"country": "USA",
"par": 72
},
"rounds": [1, 2, 3]
},
{
"course": {
"id": 54,
"name": "Nicklaus Tournament Course",
"city": "La Quinta",
"state": "California",
"country": "USA",
"par": 72
},
"rounds": [1, 2, 3]
},
{
"course": {
"id": 52,
"name": "Pete Dye Stadium Course",
"city": "La Quinta",
"state": "California",
"country": "USA",
"par": 72
},
"rounds": [1, 2, 3, 4]
}
]
}
],
"meta": {
"next_cursor": 46,
"per_page": 2
}
}
This endpoint retrieves PGA Tour tournaments. The courses array shows which courses are used in each tournament and which rounds they're played on. Multi-course tournaments (like The American Express) will have multiple entries where players rotate between courses during the first few rounds before converging on the final course for round 4.
HTTP Request
GET https://api.balldontlie.io/pga/v1/tournaments
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_ids | integer[] | No | Filter by tournament IDs |
| season | integer | No | Filter by season year |
| status | string | No | Filter by status (COMPLETED, IN_PROGRESS, SCHEDULED) |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Courses
Get All Courses
curl "https://api.balldontlie.io/pga/v1/courses?per_page=2" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/courses?per_page=2",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/courses',
headers={'Authorization': 'YOUR_API_KEY'},
params={'per_page': 2}
)
courses = response.json()['data']
for course in courses:
print(f"{course['name']} - Par {course['par']}, {course['yardage']} yards")
The above command returns JSON structured like this:
{
"data": [
{
"id": 1,
"name": "TPC River Highlands",
"city": "Cromwell",
"state": "Connecticut",
"country": "USA",
"par": 70,
"yardage": "6,844",
"established": "1928",
"architect": "Robert J. Ross/Maurice Kearney",
"fairway_grass": "Creeping Bentgrass/Poa Annua",
"rough_grass": "Bluegrass/Ryegrass",
"green_grass": "Poa annua"
},
{
"id": 2,
"name": "Tiburón Golf Club",
"city": "Naples",
"state": "Florida",
"country": "USA",
"par": 72,
"yardage": "7,382",
"established": "1998",
"architect": "Greg Norman",
"fairway_grass": "Bermudagrass",
"rough_grass": null,
"green_grass": "Bermudagrass"
}
],
"meta": {
"next_cursor": 2,
"per_page": 2
}
}
This endpoint retrieves golf courses used in PGA Tour events.
HTTP Request
GET https://api.balldontlie.io/pga/v1/courses
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| course_ids | integer[] | No | Filter by course IDs |
| search | string | No | Search courses by name |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Tournament Results
Get Tournament Results
curl "https://api.balldontlie.io/pga/v1/tournament_results?tournament_ids[]=1201&per_page=3" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/tournament_results?tournament_ids[]=1201&per_page=3",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/tournament_results',
headers={'Authorization': 'YOUR_API_KEY'},
params={'tournament_ids[]': 1201, 'per_page': 3}
)
results = response.json()['data']
for result in results:
player = result['player']
earnings = f"${result['earnings']:,.2f}" if result['earnings'] else "N/A"
print(f"{result['position']} - {player['display_name']}: {result['par_relative_score']} ({earnings})")
The above command returns JSON structured like this:
{
"data": [
{
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"status": "COMPLETED"
},
"player": {
"id": 130,
"first_name": "Hideki",
"last_name": "Matsuyama",
"display_name": "Hideki Matsuyama",
"country": "Japan",
"country_code": "JPN",
"active": true
},
"position": "1",
"position_numeric": 1,
"total_score": 257,
"par_relative_score": -35,
"earnings": 3600000
},
{
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"status": "COMPLETED"
},
"player": {
"id": 142,
"first_name": "Collin",
"last_name": "Morikawa",
"display_name": "Collin Morikawa",
"country": "United States",
"country_code": "USA",
"active": true
},
"position": "2",
"position_numeric": 2,
"total_score": 260,
"par_relative_score": -32,
"earnings": 2160000
},
{
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"status": "COMPLETED"
},
"player": {
"id": 93,
"first_name": "Sungjae",
"last_name": "Im",
"display_name": "Sungjae Im",
"country": "Republic of Korea",
"country_code": "KOR",
"active": true
},
"position": "3",
"position_numeric": 3,
"total_score": 263,
"par_relative_score": -29,
"earnings": 1360000
}
],
"meta": {
"next_cursor": 809,
"per_page": 3
}
}
This endpoint retrieves tournament leaderboards and final results, including prize money earnings in USD. Requires ALL-STAR tier or higher.
HTTP Request
GET https://api.balldontlie.io/pga/v1/tournament_results
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_ids | integer[] | No | Filter by tournament IDs |
| player_ids | integer[] | No | Filter by player IDs |
| season | integer | No | Filter by season year |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Tournament Course Stats
Get Tournament Course Stats
curl "https://api.balldontlie.io/pga/v1/tournament_course_stats?tournament_ids[]=1201&per_page=3" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/tournament_course_stats?tournament_ids[]=1201&per_page=3",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/tournament_course_stats',
headers={'Authorization': 'YOUR_API_KEY'},
params={'tournament_ids[]': 1201, 'per_page': 3}
)
stats = response.json()['data']
for stat in stats:
print(f"Hole {stat['hole_number']}: Avg {stat['scoring_average']} (Difficulty Rank: {stat['difficulty_rank']})")
The above command returns JSON structured like this:
{
"data": [
{
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"status": "COMPLETED"
},
"course": {
"id": 56,
"name": "Plantation Course at Kapalua",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "USA",
"par": 73
},
"hole_number": 1,
"round_number": null,
"scoring_average": 4.111,
"scoring_diff": 0.111,
"difficulty_rank": 1,
"eagles": 0,
"birdies": 17,
"pars": 178,
"bogeys": 38,
"double_bogeys": 1
},
{
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"status": "COMPLETED"
},
"course": {
"id": 56,
"name": "Plantation Course at Kapalua",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "USA",
"par": 73
},
"hole_number": 1,
"round_number": 4,
"scoring_average": 4.103,
"scoring_diff": 0.103,
"difficulty_rank": 1,
"eagles": 0,
"birdies": 4,
"pars": 44,
"bogeys": 10,
"double_bogeys": 0
},
{
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"status": "COMPLETED"
},
"course": {
"id": 56,
"name": "Plantation Course at Kapalua",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "USA",
"par": 73
},
"hole_number": 1,
"round_number": 3,
"scoring_average": 4.051,
"scoring_diff": 0.051,
"difficulty_rank": 1,
"eagles": 0,
"birdies": 5,
"pars": 46,
"bogeys": 8,
"double_bogeys": 0
}
],
"meta": {
"next_cursor": 4843,
"per_page": 3
}
}
This endpoint retrieves hole-by-hole statistics for tournaments, including scoring averages, difficulty rankings, and score distribution. Requires ALL-STAR tier or higher.
HTTP Request
GET https://api.balldontlie.io/pga/v1/tournament_course_stats
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_ids | integer[] | No | Filter by tournament IDs |
| course_ids | integer[] | No | Filter by course IDs |
| hole_number | integer | No | Filter by hole number (1-18) |
| round_number | integer | No | Filter by round number (1-4) |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Course Holes
Get Course Holes
curl "https://api.balldontlie.io/pga/v1/course_holes?course_ids[]=45&per_page=3" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/course_holes?course_ids[]=45&per_page=3",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/course_holes',
headers={'Authorization': 'YOUR_API_KEY'},
params={'course_ids[]': 45, 'per_page': 3}
)
holes = response.json()['data']
for hole in holes:
print(f"Hole {hole['hole_number']}: Par {hole['par']}, {hole['yardage']} yards")
The above command returns JSON structured like this:
{
"data": [
{
"course": {
"id": 1,
"name": "TPC River Highlands",
"city": "Cromwell",
"state": "Connecticut",
"country": "USA",
"par": 70
},
"hole_number": 1,
"par": 4,
"yardage": 434
},
{
"course": {
"id": 1,
"name": "TPC River Highlands",
"city": "Cromwell",
"state": "Connecticut",
"country": "USA",
"par": 70
},
"hole_number": 2,
"par": 4,
"yardage": 341
},
{
"course": {
"id": 1,
"name": "TPC River Highlands",
"city": "Cromwell",
"state": "Connecticut",
"country": "USA",
"par": 70
},
"hole_number": 3,
"par": 4,
"yardage": 431
}
],
"meta": {
"next_cursor": 3,
"per_page": 3
}
}
This endpoint retrieves hole-by-hole course information including par and yardage. Requires ALL-STAR tier or higher.
HTTP Request
GET https://api.balldontlie.io/pga/v1/course_holes
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| course_ids | integer[] | No | Filter by course IDs |
| hole_number | integer | No | Filter by hole number (1-18) |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Tournament Field
Get Tournament Field
curl "https://api.balldontlie.io/pga/v1/tournament_field?tournament_id=6&per_page=3" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/tournament_field?tournament_id=6&per_page=3",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/tournament_field',
headers={'Authorization': 'YOUR_API_KEY'},
params={'tournament_id': 6, 'per_page': 3}
)
entries = response.json()['data']
for entry in entries:
player = entry['player']
status = entry['entry_status']
qualifier = entry['qualifier'] or 'N/A'
print(f"{player['display_name']} ({status}) - {qualifier}")
The above command returns JSON structured like this:
{
"data": [
{
"id": 11245,
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "United States of America",
"course_name": "Plantation Course at Kapalua",
"purse": "$20,000,000",
"status": "COMPLETED",
"champion": {
"id": 130,
"first_name": "Hideki",
"last_name": "Matsuyama",
"display_name": "Hideki Matsuyama",
"country": "Japan",
"country_code": "JPN",
"active": true
}
},
"player": {
"id": 186,
"first_name": "Xander",
"last_name": "Schauffele",
"display_name": "Xander Schauffele",
"country": "United States",
"country_code": "USA",
"active": true
},
"entry_status": "IN",
"qualifier": "Current Tournament Winners",
"owgr": 2,
"is_amateur": false
},
{
"id": 11239,
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "United States of America",
"course_name": "Plantation Course at Kapalua",
"purse": "$20,000,000",
"status": "COMPLETED",
"champion": {
"id": 130,
"first_name": "Hideki",
"last_name": "Matsuyama",
"display_name": "Hideki Matsuyama",
"country": "Japan",
"country_code": "JPN",
"active": true
}
},
"player": {
"id": 142,
"first_name": "Collin",
"last_name": "Morikawa",
"display_name": "Collin Morikawa",
"country": "United States",
"country_code": "USA",
"active": true
},
"entry_status": "IN",
"qualifier": "Top 50 on Prior Year's FedExCup Points List",
"owgr": 4,
"is_amateur": false
},
{
"id": 11235,
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "United States of America",
"course_name": "Plantation Course at Kapalua",
"purse": "$20,000,000",
"status": "COMPLETED",
"champion": {
"id": 130,
"first_name": "Hideki",
"last_name": "Matsuyama",
"display_name": "Hideki Matsuyama",
"country": "Japan",
"country_code": "JPN",
"active": true
}
},
"player": {
"id": 130,
"first_name": "Hideki",
"last_name": "Matsuyama",
"display_name": "Hideki Matsuyama",
"country": "Japan",
"country_code": "JPN",
"active": true
},
"entry_status": "IN",
"qualifier": "Current Tournament Winners",
"owgr": 5,
"is_amateur": false
}
],
"meta": {
"next_cursor": 11235,
"per_page": 3
}
}
This endpoint retrieves the tournament field (player entries) for a specific tournament. Use this to see who is playing in upcoming or current tournaments, including their entry status and qualification method. Results are sorted by Official World Golf Ranking (OWGR). Requires GOAT tier.
HTTP Request
GET https://api.balldontlie.io/pga/v1/tournament_field
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_id | integer | Yes | Tournament ID to get field for |
| entry_status | string | No | Filter by status: IN, WITHDRAWN, ALTERNATE |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Entry Status Values
| Status | Description |
|---|---|
| IN | Player is confirmed to play |
| WITHDRAWN | Player has withdrawn from the tournament |
| ALTERNATE | Player is on the alternate list |
Tee Times
Get Tee Times
curl "https://api.balldontlie.io/pga/v1/tee_times?tournament_id=6&round_number=1&per_page=3" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/tee_times?tournament_id=6&round_number=1&per_page=3",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/tee_times',
headers={'Authorization': 'YOUR_API_KEY'},
params={'tournament_id': 6, 'round_number': 1, 'per_page': 3}
)
tee_times = response.json()['data']
for tt in tee_times:
player = tt['player']
time = tt['tee_time'] or 'TBD'
tee = tt['start_tee']
print(f"{player['display_name']} - {time} (Tee #{tee}, Group {tt['group_number']})")
The above command returns JSON structured like this:
{
"data": [
{
"id": 1,
"round_number": 1,
"group_number": 1,
"tee_time": "2025-01-02T13:00:00.000Z",
"start_tee": 1,
"back_nine": false,
"player": {
"id": 186,
"first_name": "Xander",
"last_name": "Schauffele",
"display_name": "Xander Schauffele",
"country": "United States",
"country_code": "USA",
"active": true
},
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "United States of America",
"course_name": "Plantation Course at Kapalua",
"purse": "$20,000,000",
"status": "COMPLETED",
"champion": {
"id": 130,
"first_name": "Hideki",
"last_name": "Matsuyama",
"display_name": "Hideki Matsuyama",
"country": "Japan",
"country_code": "JPN",
"active": true
}
},
"course": {
"id": 42,
"name": "Plantation Course at Kapalua",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "United States of America",
"par": 73,
"yardage": "7,596"
}
},
{
"id": 2,
"round_number": 1,
"group_number": 1,
"tee_time": "2025-01-02T13:00:00.000Z",
"start_tee": 1,
"back_nine": false,
"player": {
"id": 142,
"first_name": "Collin",
"last_name": "Morikawa",
"display_name": "Collin Morikawa",
"country": "United States",
"country_code": "USA",
"active": true
},
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "United States of America",
"course_name": "Plantation Course at Kapalua",
"purse": "$20,000,000",
"status": "COMPLETED",
"champion": {
"id": 130,
"first_name": "Hideki",
"last_name": "Matsuyama",
"display_name": "Hideki Matsuyama",
"country": "Japan",
"country_code": "JPN",
"active": true
}
},
"course": {
"id": 42,
"name": "Plantation Course at Kapalua",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "United States of America",
"par": 73,
"yardage": "7,596"
}
},
{
"id": 3,
"round_number": 1,
"group_number": 1,
"tee_time": "2025-01-02T13:00:00.000Z",
"start_tee": 1,
"back_nine": false,
"player": {
"id": 130,
"first_name": "Hideki",
"last_name": "Matsuyama",
"display_name": "Hideki Matsuyama",
"country": "Japan",
"country_code": "JPN",
"active": true
},
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "United States of America",
"course_name": "Plantation Course at Kapalua",
"purse": "$20,000,000",
"status": "COMPLETED",
"champion": {
"id": 130,
"first_name": "Hideki",
"last_name": "Matsuyama",
"display_name": "Hideki Matsuyama",
"country": "Japan",
"country_code": "JPN",
"active": true
}
},
"course": {
"id": 42,
"name": "Plantation Course at Kapalua",
"city": "Kapalua, Maui",
"state": "Hawaii",
"country": "United States of America",
"par": 73,
"yardage": "7,596"
}
}
],
"meta": {
"next_cursor": 3,
"per_page": 3
}
}
This endpoint retrieves tee time groupings for a specific tournament. Use this to see which players are grouped together, when they tee off, and from which tee/course. Tee times are updated during live tournaments to reflect re-pairings from weather delays. Results are sorted by round number, tee time, and group number. Requires GOAT tier.
HTTP Request
GET https://api.balldontlie.io/pga/v1/tee_times
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_id | integer | Yes | Tournament ID to get tee times for |
| round_number | integer | No | Filter by round (1-4) |
| player_ids[] | integer[] | No | Filter by player IDs |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Response Fields
| Field | Type | Description |
|---|---|---|
| id | integer | Tee time entry ID |
| round_number | integer | Round number (1-4) |
| group_number | integer | Group number within the round |
| tee_time | string | Tee time in UTC (ISO 8601), null if not yet announced |
| start_tee | integer | Starting tee (1 or 10), null if not yet announced |
| back_nine | boolean | Whether the group starts on the back nine |
| player | object | Player object |
| tournament | object | Tournament object |
| course | object | Course object (useful for multi-course tournaments) |
Player Round Results
Get Player Round Results
curl "https://api.balldontlie.io/pga/v1/player_round_results?tournament_ids[]=1201&player_ids[]=5467" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/player_round_results?tournament_ids[]=1201&player_ids[]=5467",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/player_round_results',
headers={'Authorization': 'YOUR_API_KEY'},
params={'tournament_ids[]': 1201, 'player_ids[]': 5467}
)
results = response.json()['data']
for result in results:
print(f"Round {result['round_number']}: {result['score']} ({result['par_relative_score']})")
The above command returns JSON structured like this:
{
"data": [
{
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"status": "COMPLETED"
},
"player": {
"id": 130,
"first_name": "Hideki",
"last_name": "Matsuyama",
"display_name": "Hideki Matsuyama",
"country": "Japan",
"country_code": "JPN",
"active": true
},
"round_number": 1,
"score": 65,
"par_relative_score": -8
},
{
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"status": "COMPLETED"
},
"player": {
"id": 142,
"first_name": "Collin",
"last_name": "Morikawa",
"display_name": "Collin Morikawa",
"country": "United States",
"country_code": "USA",
"active": true
},
"round_number": 1,
"score": 66,
"par_relative_score": -7
},
{
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"status": "COMPLETED"
},
"player": {
"id": 93,
"first_name": "Sungjae",
"last_name": "Im",
"display_name": "Sungjae Im",
"country": "Republic of Korea",
"country_code": "KOR",
"active": true
},
"round_number": 1,
"score": 69,
"par_relative_score": -4
}
],
"meta": {
"next_cursor": 11698,
"per_page": 3
}
}
This endpoint retrieves round-by-round player scores. Requires GOAT tier.
HTTP Request
GET https://api.balldontlie.io/pga/v1/player_round_results
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_ids | integer[] | No | Filter by tournament IDs |
| player_ids | integer[] | No | Filter by player IDs |
| round_number | integer | No | Filter by round number (1-4) |
| season | integer | No | Filter by season year |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Player Round Stats
Get Player Round Stats
curl "https://api.balldontlie.io/pga/v1/player_round_stats?tournament_ids[]=1201&player_ids[]=5467&round_number=-1" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/player_round_stats?tournament_ids[]=1201&player_ids[]=5467&round_number=-1",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/player_round_stats',
headers={'Authorization': 'YOUR_API_KEY'},
params={'tournament_ids[]': 1201, 'player_ids[]': 5467, 'round_number': -1}
)
stats = response.json()['data']
for stat in stats:
print(f"SG Total: {stat['sg_total']}")
print(f"SG Off Tee: {stat['sg_off_tee']}")
print(f"SG Approach: {stat['sg_approach']}")
print(f"SG Putting: {stat['sg_putting']}")
The above command returns JSON structured like this:
{
"data": [
{
"tournament": {
"id": 6,
"season": 2025,
"name": "The Sentry",
"start_date": "2025-01-01T19:00:00.000Z",
"end_date": "Jan 2 - 5",
"status": "COMPLETED"
},
"player": {
"id": 189,
"first_name": "Adam",
"last_name": "Scott",
"display_name": "Adam Scott",
"country": "Australia",
"country_code": "AUS",
"active": true
},
"round_number": -1,
"sg_off_tee": -1.26,
"sg_off_tee_rank": 46,
"sg_approach": 3.792,
"sg_approach_rank": 9,
"sg_around_green": 1.427,
"sg_around_green_rank": 10,
"sg_putting": 0.019,
"sg_putting_rank": 28,
"sg_total": 3.978,
"sg_total_rank": 15,
"driving_accuracy": 60,
"driving_accuracy_rank": 46,
"driving_distance": 282.4,
"driving_distance_rank": 27,
"longest_drive": 375,
"longest_drive_rank": 54,
"greens_in_regulation": 81.94,
"greens_in_regulation_rank": 27,
"sand_saves": 33.33,
"sand_saves_rank": 24,
"scrambling": 46.15,
"scrambling_rank": 48,
"putts_per_gir": 1.64,
"putts_per_gir_rank": 10,
"eagles": null,
"birdies": 29,
"pars": 35,
"bogeys": 8,
"double_bogeys": null
}
],
"meta": {
"next_cursor": 33023,
"per_page": 1
}
}
This endpoint retrieves detailed player round statistics including strokes gained metrics, driving accuracy, greens in regulation, and more. Use round_number=-1 for tournament totals. Requires GOAT tier.
HTTP Request
GET https://api.balldontlie.io/pga/v1/player_round_stats
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_ids | integer[] | No | Filter by tournament IDs |
| player_ids | integer[] | No | Filter by player IDs |
| round_number | integer | No | Filter by round number (1-4, -1 for tournament total) |
| season | integer | No | Filter by season year |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Player Season Stats
Get Player Season Stats
curl "https://api.balldontlie.io/pga/v1/player_season_stats?player_ids[]=5467&season=2024&per_page=5" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/player_season_stats?player_ids[]=5467&season=2024&per_page=5",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/player_season_stats',
headers={'Authorization': 'YOUR_API_KEY'},
params={'player_ids[]': 5467, 'season': 2024, 'per_page': 5}
)
stats = response.json()['data']
for stat in stats:
print(f"{stat['stat_name']}: Rank {stat['rank']}")
The above command returns JSON structured like this:
{
"data": [
{
"player": {
"id": 185,
"first_name": "Scottie",
"last_name": "Scheffler",
"display_name": "Scottie Scheffler",
"country": "United States",
"country_code": "USA",
"active": true
},
"stat_id": 8,
"stat_name": "SG: Total",
"stat_category": "STROKES_GAINED",
"season": 2025,
"rank": 1,
"stat_value": [
{ "statName": "Avg", "statValue": "2.743" },
{ "statName": "Total SG:T", "statValue": "197.507" },
{ "statName": "Total SG:T2G", "statValue": "169.995" },
{ "statName": "Total SG:P", "statValue": "27.512" },
{ "statName": "Measured Rounds", "statValue": "72" }
]
},
{
"player": {
"id": 185,
"first_name": "Scottie",
"last_name": "Scheffler",
"display_name": "Scottie Scheffler",
"country": "United States",
"country_code": "USA",
"active": true
},
"stat_id": 9,
"stat_name": "SG: Tee-to-Green",
"stat_category": "STROKES_GAINED",
"season": 2025,
"rank": 1,
"stat_value": [
{ "statName": "Avg", "statValue": "2.361" },
{ "statName": "SG:OTT", "statValue": "0.748" },
{ "statName": "SG:APR", "statValue": "1.291" },
{ "statName": "SG:ARG", "statValue": "0.322" },
{ "statName": "Measured Rounds", "statValue": "72" }
]
},
{
"player": {
"id": 31,
"first_name": "Pierceson",
"last_name": "Coody",
"display_name": "Pierceson Coody",
"country": "United States",
"country_code": "USA",
"active": true
},
"stat_id": 10,
"stat_name": "SG: Off-the-Tee",
"stat_category": "STROKES_GAINED",
"season": 2025,
"rank": 1,
"stat_value": [
{ "statName": "Avg", "statValue": "0.789" },
{ "statName": "Total SG:OTT", "statValue": "26.812" },
{ "statName": "Measured Rounds", "statValue": "34" }
]
}
],
"meta": {
"next_cursor": 20770,
"per_page": 3
}
}
This endpoint retrieves player season-level statistics across various categories. Requires GOAT tier.
HTTP Request
GET https://api.balldontlie.io/pga/v1/player_season_stats
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| player_ids | integer[] | No | Filter by player IDs |
| season | integer | No | Filter by season year |
| stat_ids | integer[] | No | Filter by stat IDs |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Available Stat Categories
There are 493 different statistics available, organized into the following categories:
| Category | Description | Example Stats |
|---|---|---|
| STROKES_GAINED | Strokes gained metrics | SG: Total, SG: Tee-to-Green, SG: Off-the-Tee, SG: Approach the Green, SG: Around-the-Green, SG: Putting |
| OFF_TEE | Driving statistics | Driving Distance, Driving Accuracy Percentage, Club Head Speed, Ball Speed, Launch Angle |
| APPROACH_GREEN | Approach shot metrics | Approach from various distances (50-275+ yards), Greens in Regulation |
| AROUND_GREEN | Short game statistics | Sand Save Percentage, Scrambling, Up and Down Percentage |
| PUTTING | Putting metrics | Putts per Round, 3-Putt Avoidance, Putting from various distances |
| SCORING | Scoring statistics | Scoring Average, Birdie Average, Par Breakers, Final Round Scoring |
| MONEY_FINISHES | Earnings and finishes | Official Money, Top 10 Finishes, Wins |
| POINTS_RANKINGS | Rankings and points | FedEx Cup Points, World Golf Ranking |
| STREAKS | Consecutive statistics | Consecutive Cuts Made, Consecutive Birdies |
Player Scorecards
Get Player Scorecards
curl "https://api.balldontlie.io/pga/v1/player_scorecards?tournament_ids[]=1201&player_ids[]=5467&round_number=1&per_page=3" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/player_scorecards?tournament_ids[]=1201&player_ids[]=5467&round_number=1&per_page=3",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/player_scorecards',
headers={'Authorization': 'YOUR_API_KEY'},
params={'tournament_ids[]': 1201, 'player_ids[]': 5467, 'round_number': 1, 'per_page': 3}
)
scorecard = response.json()['data']
for hole in scorecard:
print(f"Hole {hole['hole_number']}: {hole['score']} (Par {hole['par']})")
The above command returns JSON structured like this:
{
"data": [
{
"tournament": {
"id": 8,
"season": 2026,
"name": "The American Express",
"start_date": "2026-01-22T00:00:00.000Z",
"end_date": "Jan 22 - 25",
"status": "COMPLETED",
"courses": [
{
"course": { "id": 53, "name": "La Quinta Country Club" },
"rounds": [1, 2, 3]
},
{
"course": { "id": 54, "name": "Nicklaus Tournament Course" },
"rounds": [1, 2, 3]
},
{
"course": { "id": 52, "name": "Pete Dye Stadium Course" },
"rounds": [1, 2, 3, 4]
}
]
},
"player": {
"id": 65,
"first_name": "Emiliano",
"last_name": "Grillo",
"display_name": "Emiliano Grillo",
"country": "Argentina",
"country_code": "ARG",
"active": true
},
"course": {
"id": 54,
"name": "Nicklaus Tournament Course",
"city": "La Quinta",
"state": "California",
"country": "USA",
"par": 72
},
"round_number": 1,
"hole_number": 1,
"par": 4,
"score": 5
},
{
"tournament": {
"id": 8,
"season": 2026,
"name": "The American Express",
"start_date": "2026-01-22T00:00:00.000Z",
"end_date": "Jan 22 - 25",
"status": "COMPLETED"
},
"player": {
"id": 23,
"first_name": "Bud",
"last_name": "Cauley",
"display_name": "Bud Cauley",
"country": "United States",
"country_code": "USA",
"active": true
},
"course": {
"id": 53,
"name": "La Quinta Country Club",
"city": "La Quinta",
"state": "California",
"country": "USA",
"par": 72
},
"round_number": 1,
"hole_number": 1,
"par": 4,
"score": 4
}
],
"meta": {
"next_cursor": 36868975,
"per_page": 2
}
}
This endpoint retrieves hole-by-hole player scores for specific rounds. The course field indicates which course the player played for that round—this is especially useful for multi-course tournaments (like The American Express) where different players play different courses on the same day. Requires GOAT tier.
HTTP Request
GET https://api.balldontlie.io/pga/v1/player_scorecards
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_ids | integer[] | No | Filter by tournament IDs |
| player_ids | integer[] | No | Filter by player IDs |
| round_number | integer | No | Filter by round number (1-4) |
| hole_number | integer | No | Filter by hole number (1-18) |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Futures
Get Futures Odds
curl "https://api.balldontlie.io/pga/v1/futures?vendors[]=fanduel&per_page=2" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/futures?vendors[]=fanduel&per_page=2",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/futures',
headers={'Authorization': 'YOUR_API_KEY'},
params={'vendors[]': 'fanduel', 'per_page': 2}
)
futures = response.json()['data']
for f in futures:
player = f['player']
tournament = f['tournament']
print(f"{player['display_name']} - {tournament['name']}: {f['american_odds']} ({f['vendor']})")
The above command returns JSON structured like this:
{
"data": [
{
"id": 98747717,
"market_type": "tournament_winner",
"market_name": "2026 Masters Tournament",
"player": {
"id": 185,
"first_name": "Scottie",
"last_name": "Scheffler",
"display_name": "Scottie Scheffler",
"country": "United States",
"country_code": "USA",
"height": "6'3\"",
"weight": "200",
"birth_date": "Jun 21, 1996",
"birthplace_city": "Ridgewood",
"birthplace_state": "New Jersey",
"birthplace_country": "United States",
"turned_pro": "2018",
"school": "University of Texas",
"residence_city": "Dallas",
"residence_state": "Texas",
"residence_country": "United States",
"owgr": 1,
"active": true
},
"tournament": {
"id": 20,
"season": 2026,
"name": "Masters Tournament",
"start_date": "2026-04-09T00:00:00.000Z",
"end_date": "Apr 9 - 12",
"city": "Augusta",
"state": "Georgia",
"country": "United States of America",
"course_name": "Augusta National Golf Club",
"purse": "$0",
"status": "NOT_STARTED",
"champion": null,
"courses": []
},
"vendor": "fanduel",
"american_odds": 280,
"updated_at": "2026-02-19T10:19:02.827Z"
},
{
"id": 98747718,
"market_type": "tournament_winner",
"market_name": "2026 Masters Tournament",
"player": {
"id": 134,
"first_name": "Rory",
"last_name": "McIlroy",
"display_name": "Rory McIlroy",
"country": "Northern Ireland",
"country_code": "NIR",
"height": "5'10\"",
"weight": "160",
"birth_date": "May 4, 1989",
"birthplace_city": "Holywood",
"birthplace_state": null,
"birthplace_country": "Northern Ireland",
"turned_pro": "2007",
"school": null,
"residence_city": "Holywood",
"residence_state": null,
"residence_country": "Northern Ireland",
"owgr": 2,
"active": true
},
"tournament": {
"id": 20,
"season": 2026,
"name": "Masters Tournament",
"start_date": "2026-04-09T00:00:00.000Z",
"end_date": "Apr 9 - 12",
"city": "Augusta",
"state": "Georgia",
"country": "United States of America",
"course_name": "Augusta National Golf Club",
"purse": "$0",
"status": "NOT_STARTED",
"champion": null,
"courses": []
},
"vendor": "fanduel",
"american_odds": 700,
"updated_at": "2026-02-19T10:19:02.827Z"
}
],
"meta": {
"next_cursor": 98747718,
"per_page": 2
}
}
This endpoint retrieves futures betting odds for PGA tournaments. Currently includes tournament winner odds from multiple sportsbooks. Requires GOAT tier.
HTTP Request
GET https://api.balldontlie.io/pga/v1/futures
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| player_ids | integer[] | No | Filter by player IDs |
| tournament_ids | integer[] | No | Filter by tournament IDs |
| vendors | string[] | No | Filter by sportsbook vendors (e.g., fanduel, draftkings) |
| cursor | integer | No | Pagination cursor |
| per_page | integer | No | Results per page (max 100, default 25) |
Available Market Types
| Market Type | Description |
|---|---|
| tournament_winner | Win a tournament outright |
| top_5_finish | Finish in the top 5 |
| top_10_finish | Finish in the top 10 |
| top_20_finish | Finish in the top 20 |
| make_cut | Make the cut |
| miss_cut | Miss the cut |
| first_round_leader | Lead after round 1 |
| matchup | 72-hole head-to-head matchup (Player A vs B) |
| round_matchup | 18-hole round head-to-head matchup |
| first_round_3_ball | 3-ball tee-time group winner |
| nationality_winner | Top finisher from a country/region |
| winning_score | Tournament winning score over/under |
| hole_in_one | Any player to make a hole-in-one |
| top_group | Group winner (5-player group) |
| six_shooter | Group winner (6-player group) |
| season_long | Season-long futures (e.g., To Win a Major) |
Player Props
The Player Props API provides real-time player prop betting odds for PGA tournaments. Player props allow betting on individual player performances such as round scores, birdies, hole-by-hole outcomes, and more.
Market Types
The API supports two market types:
- over_under: Traditional over/under markets (e.g., Round 1 Score Over/Under 69.5)
- milestone: Milestone markets with a single odds value (e.g., Par on Hole 5)
Get Player Props
curl "https://api.balldontlie.io/pga/v1/odds/player_props?tournament_id=20&prop_type=round_1_score" \
-H "Authorization: YOUR_API_KEY"
const response = await fetch(
"https://api.balldontlie.io/pga/v1/odds/player_props?tournament_id=20&prop_type=round_1_score",
{
headers: {
Authorization: "YOUR_API_KEY",
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://api.balldontlie.io/pga/v1/odds/player_props',
headers={'Authorization': 'YOUR_API_KEY'},
params={'tournament_id': 20, 'prop_type': 'round_1_score'}
)
props = response.json()['data']
for prop in props:
print(f"Player {prop['player_id']}: {prop['prop_type']} {prop['line_value']} O:{prop['market']['over_odds']} U:{prop['market']['under_odds']}")
The above command returns JSON structured like this:
{
"data": [
{
"id": 5907182294,
"game_id": 20,
"player_id": 1,
"vendor": "fanduel",
"prop_type": "round_1_score",
"line_value": "69.5",
"market": {
"type": "over_under",
"over_odds": -110,
"under_odds": -120
},
"updated_at": "2026-04-02T19:20:02.650Z"
},
{
"id": 5907182287,
"game_id": 20,
"player_id": 49,
"vendor": "fanduel",
"prop_type": "round_1_score",
"line_value": "67.5",
"market": {
"type": "over_under",
"over_odds": 110,
"under_odds": -138
},
"updated_at": "2026-04-02T19:20:02.650Z"
}
],
"meta": {
"per_page": 2
}
}
This endpoint retrieves player prop betting odds for a specific PGA tournament. The tournament_id parameter is required. Requires GOAT tier.
HTTP Request
GET https://api.balldontlie.io/pga/v1/odds/player_props
Query Parameters
| Parameter | Required | Description |
|---|---|---|
| tournament_id | true | The tournament ID to retrieve player props for |
| player_id | false | Filter props for a specific player |
| prop_type | false | Filter by prop type. See supported prop types below. |
| vendors | false | Filter by specific sportsbook vendors: ?vendors[]=fanduel&vendors[]=draftkings |
Supported Prop Types
Props use round and hole numbers in the type name (e.g., round_1_score, hole_14_par). Available prop types vary by round and tournament stage.
Over/Under Props:
| Prop Type | Description |
|---|---|
| round_N_score | Round score over/under (e.g., 69.5) |
| round_N_birdies | Birdies in round over/under |
| round_N_pars | Pars in round over/under |
| round_N_gir | Greens in regulation over/under |
| round_N_fairways | Fairways hit over/under |
| round_N_putts | Putts in round over/under |
| hole_N_putts | Putts on a hole over/under |
| finishing_position | Finishing position over/under |
Milestone Props (single odds, no under):
| Prop Type | Description |
|---|---|
| hole_N_par | Par on a specific hole |
| hole_N_birdie_plus | Birdie or better on a hole |
| hole_N_bogey_plus | Bogey or worse on a hole |
| hole_N_gir | Hit green in regulation |
| make_cut | Make the cut |
| round_N_bogey_free | Bogey-free round |
| round_N_eagle | Make an eagle in the round |