All tutorials
Intermediate10 min read
Build a Club Profile Page
Chain 4 API calls to display a complete club page: contact info, green fees, facilities, and hole-by-hole scorecard.
Endpoint chain
1
GET /clubs/{id}Club overview: name, county, coordinates, phone, website, rating, courses list
2
GET /clubs/{id}/green-feesAll pricing tiers (weekday, weekend, twilight, etc.)
3
GET /clubs/{id}/facilities19 boolean flags — driving range, buggy hire, pro shop, bar, etc.
4
GET /courses/{id}/scorecardHole-by-hole data: par, yardage, stroke index for each tee set
Steps 1–3 run in parallel. Step 4 requires the course ID from step 1.
Club response
{
"id": "3b4c5d6e-...",
"name": "Wentworth Club",
"county": "Surrey",
"postcode": "GU25 4LS",
"latitude": 51.3972,
"longitude": -0.5672,
"google_rating": 4.5,
"google_review_count": 312,
"phone": "+44 1344 842201",
"website": "https://www.wentworthclub.com",
"email": "info@wentworthclub.com",
"course_type": "heathland",
"opening_hours": {
"monday": "07:00–18:00",
"saturday": "07:00–18:00"
},
"courses": [
{ "id": "c1d2e3f4-...", "name": "West Course" },
{ "id": "c5d6e7f8-...", "name": "East Course" }
]
}Scorecard response
{
"id": "c1d2e3f4-...",
"name": "West Course",
"designed_by": "Harry Colt",
"year_opened": 1924,
"tee_sets": [
{
"name": "White",
"gender": "M",
"par": 72,
"slope_rating": 139,
"course_rating": 74.8,
"holes": [
{ "hole_number": 1, "par": 4, "yardage": 471, "stroke_index": 7 },
{ "hole_number": 2, "par": 5, "yardage": 535, "stroke_index": 15 }
]
}
]
}Full example
JavaScript (async/await + Promise.all)
async function getClubProfile(clubId) {
const headers = {
'X-RapidAPI-Key': process.env.RAPIDAPI_KEY,
'X-RapidAPI-Host': 'uk-golf-course-data-api.p.rapidapi.com',
};
const base = 'https://uk-golf-api.vercel.app';
// Fetch all data in parallel — only 3 requests
const [clubRes, feesRes, facilitiesRes] = await Promise.all([
fetch(`${base}/clubs/${clubId}`, { headers }),
fetch(`${base}/clubs/${clubId}/green-fees`, { headers }),
fetch(`${base}/clubs/${clubId}/facilities`, { headers }),
]);
const [{ data: club }, { data: fees }, { data: facilities }] = await Promise.all([
clubRes.json(),
feesRes.json(),
facilitiesRes.json(),
]);
// If the club has courses, fetch the first course's scorecard
let scorecard = null;
if (club.courses?.length > 0) {
const courseId = club.courses[0].id;
const scRes = await fetch(`${base}/courses/${courseId}/scorecard`, { headers });
const { data } = await scRes.json();
scorecard = data;
}
return { club, fees, facilities, scorecard };
}
const profile = await getClubProfile('YOUR_CLUB_ID');
console.log(profile.club.name, '—', profile.club.county);
console.log('Green fees:', profile.fees.length, 'pricing tiers');
console.log('Has driving range:', profile.facilities?.driving_range);
if (profile.scorecard?.tee_sets?.length > 0) {
const tee = profile.scorecard.tee_sets[0];
console.log(`${tee.name} tees: par ${tee.par}, ${tee.holes.length} holes`);
}Python (asyncio + httpx)
import asyncio
import httpx
API_KEY = "YOUR_API_KEY"
HEADERS = {
"X-RapidAPI-Key": API_KEY,
"X-RapidAPI-Host": "uk-golf-course-data-api.p.rapidapi.com",
}
BASE = "https://uk-golf-api.vercel.app"
async def get_club_profile(club_id: str):
async with httpx.AsyncClient() as client:
# Fetch all data in parallel
club_r, fees_r, facilities_r = await asyncio.gather(
client.get(f"{BASE}/clubs/{club_id}", headers=HEADERS),
client.get(f"{BASE}/clubs/{club_id}/green-fees", headers=HEADERS),
client.get(f"{BASE}/clubs/{club_id}/facilities", headers=HEADERS),
)
club = club_r.json()["data"]
fees = fees_r.json()["data"]
facilities = facilities_r.json()["data"]
# Fetch scorecard if courses exist
scorecard = None
if club.get("courses"):
course_id = club["courses"][0]["id"]
sc_r = await client.get(
f"{BASE}/courses/{course_id}/scorecard",
headers=HEADERS
)
scorecard = sc_r.json()["data"]
return {
"club": club,
"fees": fees,
"facilities": facilities,
"scorecard": scorecard,
}
profile = asyncio.run(get_club_profile("YOUR_CLUB_ID"))
club = profile["club"]
print(f"{club['name']} — {club['county']}, {club['country_name']}")
print(f"Rating: {club.get('google_rating', 'N/A')} ({club.get('google_review_count', 0)} reviews)")
print(f"Green fees: {len(profile['fees'])} pricing tiers")
if profile["scorecard"] and profile["scorecard"]["tee_sets"]:
tee = profile["scorecard"]["tee_sets"][0]
print(f"Scorecard: {tee['name']} tees, par {tee['par']}, {len(tee['holes'])} holes")Finding club IDs
Use GET /clubs?search=Wentworth to search by name, or GET /clubs/nearby to find clubs by location. Both return a list of clubs with their id field.
Next steps
- → Find clubs near a postcode to feed IDs into this flow
- → Add WHS handicap integration using the slope/course_rating data