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-fees

All pricing tiers (weekday, weekend, twilight, etc.)

3
GET /clubs/{id}/facilities

19 boolean flags — driving range, buggy hire, pro shop, bar, etc.

4
GET /courses/{id}/scorecard

Hole-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