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:

  • fairways array 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

FieldTypeDescription
idstringParkdly course ID
externalCourseIdstringYour app's course identifier
namestringCourse name
fairwaysarrayArray of fairway objects (see below)
createdAtstringISO 8601 timestamp
updatedAtstringISO 8601 timestamp

Fairway Object

FieldTypeDescription
idstringFairway ID
numbernumberFairway number (1-18+)
parnumber | nullPar for this fairway
distancenumber | nullDistance in meters
teePositionobject | nullTee coordinates {lat, lng}
targetPositionobject | nullTarget coordinates {lat, lng}
flightPatharray | nullOrdered control points for PRIMARY flight path (see below)

Flight Path Control Point

FieldTypeDescription
ordernumberControl point sequence (0-indexed, ascending from tee to target)
latnumberLatitude
lngnumberLongitude

Notes:

  • All distance values are in meters
  • flightPath returns the PRIMARY flight path only (used for recommended disc flight trajectory)
  • flightPath is null if no flight path is defined for the fairway
  • teePosition and targetPosition are null if not set
  • Control points are ordered by the order field (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