API Endpoints
All API requests require authentication via OAuth 2.0 access token.
Base URL: https://parkdly.com/api/v1
Authentication
Include your access token in the Authorization header:
Authorization: Bearer {access_token}
Courses
List User's Courses
Get all courses linked to your app for the authenticated user.
GET /api/v1/courses
Response:
{
"courses": [
{
"id": "course_123",
"externalCourseId": "your-app-course-id",
"name": "Example DGC",
"fairways": [
{
"id": "fairway_1",
"number": 1,
"par": 3,
"distance": 100,
"teePosition": {
"lat": 60.1699,
"lng": 24.9384
},
"targetPosition": {
"lat": 60.17,
"lng": 24.94
},
"flightPath": [
{
"order": 0,
"lat": 60.1699,
"lng": 24.9384
},
{
"order": 1,
"lat": 60.16995,
"lng": 24.9392
},
{
"order": 2,
"lat": 60.17,
"lng": 24.94
}
]
}
],
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T12:00:00Z"
}
],
"total": 1
}
Get Course Details
Get detailed information about a specific course linked to your app.
GET /api/v1/courses/{courseId}
Response:
{
"id": "course_123",
"externalCourseId": "your-app-course-id",
"name": "Example DGC",
"fairways": [
{
"id": "fairway_1",
"number": 1,
"par": 3,
"distance": 100,
"teePosition": {
"lat": 60.1699,
"lng": 24.9384
},
"targetPosition": {
"lat": 60.17,
"lng": 24.94
},
"flightPath": [
{
"order": 0,
"lat": 60.1699,
"lng": 24.9384
},
{
"order": 1,
"lat": 60.16995,
"lng": 24.9392
},
{
"order": 2,
"lat": 60.17,
"lng": 24.94
}
]
},
{
"id": "fairway_2",
"number": 2,
"par": 4,
"distance": 150,
"teePosition": {
"lat": 60.1701,
"lng": 24.9386
},
"targetPosition": {
"lat": 60.1702,
"lng": 24.9402
},
"flightPath": null
}
],
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T12:00:00Z"
}
Create Course
Create a new course and link it to your app. Optionally include fairway data with tee and target positions.
POST /api/v1/courses
Request Body:
{
"externalCourseId": "your-app-course-id",
"name": "New Course Name",
"fairways": [ // Optional: Include fairway data
{
"number": 1,
"teePosition": {
"lat": 60.1699,
"lng": 24.9384
},
"targetPosition": {
"lat": 60.1708,
"lng": 24.9384
}
},
{
"number": 2,
"teePosition": {
"lat": 60.1708,
"lng": 24.9384
},
"targetPosition": {
"lat": 60.1718,
"lng": 24.9384
}
}
]
}
Minimal Request (without fairways):
{
"externalCourseId": "your-app-course-id",
"name": "New Course Name"
}
Response (with fairways):
{
"id": "course_123",
"externalCourseId": "your-app-course-id",
"name": "New Course Name",
"fairways": [
{
"id": "fairway_1",
"number": 1,
"par": 3,
"distance": 100,
"teePosition": {
"lat": 60.1699,
"lng": 24.9384
},
"targetPosition": {
"lat": 60.1708,
"lng": 24.9384
},
"flightPath": null
},
{
"id": "fairway_2",
"number": 2,
"par": 3,
"distance": 111,
"teePosition": {
"lat": 60.1708,
"lng": 24.9384
},
"targetPosition": {
"lat": 60.1718,
"lng": 24.9384
},
"flightPath": null
}
],
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T10:00:00Z"
}
Response (without fairways):
{
"id": "course_123",
"externalCourseId": "your-app-course-id",
"name": "New Course Name",
"fairways": [],
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T10:00:00Z"
}
Fairway Validation Rules:
fairwaysarray is optional (can be omitted or empty)- Maximum 27 fairways per course
- Fairway numbers must be unique within the course
- Fairway numbers must be between 1 and 27
- Coordinates must be valid: latitude (-90 to 90), longitude (-180 to 180)
- Tee and target must not be at the same position (minimum 0.1m apart)
- Maximum distance between tee and target: 1000 meters
- All fairways must fit within a 5 km² area (to ensure compatibility with map area selection)
- Calculated values (set automatically):
distance: Calculated using haversine formula from tee to target position (in meters)par: Estimated based on distance (< 150m = 3, < 250m = 4, otherwise = 5)
Data Model
Course Object
| Field | Type | Description |
|---|---|---|
id | string | Parkdly course ID |
externalCourseId | string | Your app's course identifier |
name | string | Course name |
fairways | array | Array of fairway objects (see below) |
createdAt | string | ISO 8601 timestamp |
updatedAt | string | ISO 8601 timestamp |
Fairway Object
| Field | Type | Description |
|---|---|---|
id | string | Fairway ID |
number | number | Fairway number (1-18+) |
par | number | null | Par for this fairway |
distance | number | null | Distance in meters |
teePosition | object | null | Tee coordinates {lat, lng} |
targetPosition | object | null | Target coordinates {lat, lng} |
flightPath | array | null | Ordered control points for PRIMARY flight path (see below) |
Flight Path Control Point
| Field | Type | Description |
|---|---|---|
order | number | Control point sequence (0-indexed, ascending from tee to target) |
lat | number | Latitude |
lng | number | Longitude |
Notes:
- All
distancevalues are in meters flightPathreturns the PRIMARY flight path only (used for recommended disc flight trajectory)flightPathisnullif no flight path is defined for the fairwayteePositionandtargetPositionarenullif not set- Control points are ordered by the
orderfield (ascending): order 0 is closest to tee, higher numbers closer to target - The complete flight path is: tee → control points (ordered) → target
Response Format
Success (2xx): Returns the data object directly
Error (4xx/5xx):
{
"error": "error_code",
"message": "Human readable error message"
}
Rate Limiting
See Rate Limits for details on request limits.
Next Steps
- Webhooks - Set up real-time notifications
- Error Handling - Handle API errors
- Rate Limits - Request limits and throttling