The Caddy Scout REST API gives you programmatic access to 40,000+ golf courses across the UK and Europe. All responses are JSON. All authenticated endpoints require a bearer token.
1. Create a free account and copy your API key from the dashboard.
2. Pass it as a Bearer token on every request.
3. Hit the courses endpoint to verify things are working.
curl https://caddyscout.com/api/v1/courses \ -H "Authorization: Bearer sk_live_your_key_here" \ -G \ -d "country=GB" \ -d "courseType=links" \ -d "limit=5"
{
"courses": [
{
"id": "clx9abc123",
"name": "Royal Dornoch Golf Club",
"slug": "royal-dornoch",
"country": "GB",
"city": "Dornoch",
"courseType": "links",
"holes": 18,
"lat": 57.8694,
"lng": -4.0271,
"greenFeeWeekend": 230,
"currency": "GBP",
"hasDrivingRange": false,
"hasProShop": true
}
],
"total": 312,
"page": 1,
"limit": 5
}All endpoints except /api/v1/status require authentication. Pass your API key as a Bearer token in the Authorization header.
Authorization: Bearer sk_live_your_key_here
Key prefixes
sk_live_ — live key, counts against your daily quota
sk_test_ — test key, returns fixture data, quota-free
Never expose your live key in client-side code or public repositories. Rotate compromised keys instantly from the dashboard.
https://caddyscout.com/api/v1
All endpoints are versioned under /v1. Breaking changes will increment the version prefix.
/api/v1/statuspublicHealth check — no authentication required. Returns {"status":"ok"}.
/api/v1/coursesPaginated list of courses. Supports rich filtering across type, location, price, and facilities.
Query parameters
page | integer | Page number (default: 1) |
limit | integer | Results per page, max 100 (default: 20) |
q | string | Free-text search across name, city, and country |
country | string | ISO 3166-1 alpha-2 country code (e.g. GB, IE) |
courseType | string | links · parkland · heathland · coastal · desert · mountain · moorland · woodland |
venueType | string | golf_course · driving_range · simulator · social_golf |
difficulty | string | beginner · intermediate · advanced · championship |
holes | integer | 9, 18, 27, or 36 |
isPublic | boolean | true to return only publicly accessible courses |
hasMembership | boolean | true to return only membership clubs |
maxGreenFee | integer | Maximum weekend green fee in local currency |
minGreenFee | integer | Minimum weekend green fee in local currency |
verified | boolean | true to return only Caddy Scout–verified listings |
GET /api/v1/courses?country=IE&courseType=links&holes=18&limit=10
/api/v1/courses/:idFetch a single course by its Caddy Scout ID or URL slug. Returns all fields including hole-by-hole data where available.
Path parameter
:idrequired | string | Caddy Scout course ID (cuid) or slug, e.g. royal-dornoch |
The search endpoint supports free-text queries and returns both matching courses and geocoded location results (postcodes, cities, Eircodes). Useful for building autocomplete or map-fly-to UIs.
/api/v1/searchQuery parameters
qrequired | string | Search query. Min 2 characters. Supports course names, city names, UK postcodes, Eircodes, and US/CA zip codes. |
limit | integer | Max results returned (default: 8, max: 20) |
country | string | Bias results toward a country (ISO 3166-1 alpha-2) |
lat | number | Latitude for proximity sorting |
lng | number | Longitude for proximity sorting |
{
"results": [ /* CourseSummary[] — matched courses */
{
"id": "...",
"name": "St Andrews Links — Old Course",
"city": "St Andrews",
"country": "GB",
"lat": 56.3402,
"lng": -2.8027,
"holes": 18,
"greenFeeWeekend": 295
}
],
"locations": [ /* geocoded place results */
{
"label": "St Andrews",
"sublabel": "Fife, Scotland",
"lat": 56.3398,
"lng": -2.7967,
"zoom": 13
}
]
}Quotas reset every 24 hours at midnight UTC. Every response includes headers so you can track consumption before hitting a 429.
| Header | Description |
|---|---|
X-RateLimit-Limit | Your plan's daily request limit |
X-RateLimit-Remaining | Requests remaining in the current 24 h window |
X-RateLimit-Reset | ISO 8601 timestamp when the window resets (UTC) |
Retry-After | Seconds to wait — only present on 429 responses |
Plan limits
Free
100 / day
Starter
5,000 / day
Professional
50,000 / day
Enterprise
Unlimited
Need higher limits? Compare plans →
All errors return a JSON body with a error string and an optional message field.
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | Missing or invalid query parameter |
| 401 | unauthorized | Missing or malformed Authorization header |
| 403 | forbidden | Valid key but insufficient plan for this endpoint |
| 404 | not_found | Course ID or slug does not exist |
| 422 | unprocessable | Request understood but validation failed |
| 429 | rate_limit_exceeded | Daily quota exhausted — check Retry-After header |
| 500 | internal_error | Something went wrong on our end |
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
Content-Type: application/json
{
"error": "rate_limit_exceeded",
"message": "Daily quota of 100 requests exhausted. Resets at 2026-05-27T00:00:00Z.",
"retryAfter": 3600
}Free tier, no credit card required. Upgrade any time.