Guides/Build a tennis player profile page

Build a tennis player profile page

Bio, form, match log, ranking chart and biggest rivalries in five parallel calls

1. From a name to an id

/players/search matches typos ("alcarez") and nicknames ("Nole"). Store the canonical_id it returns. If you ever call a route with a wrong id, the 404 lists the ids you most likely meant in error.suggestions.

bash
curl "https://api.citoapi.com/api/v1/tennis/players/search?q=alcarez&limit=3" -H "x-api-key: YOUR_API_KEY"
# items[0].id -> "atp_207989" (Carlos Alcaraz)

2. Everything for the page, in parallel

javascript
const BASE = "https://api.citoapi.com/api/v1/tennis";
const headers = { "x-api-key": process.env.CITO_API_KEY };
const get = (path) => fetch(BASE + path, { headers }).then((r) => r.json());

export async function playerPage(id) {
  const [profile, stats, form, log, ranks] = await Promise.all([
    get(`/players/${id}`),                                   // bio, country, current rank, career high
    get(`/players/${id}/stats`),                             // career record, surfaces, serve and return
    get(`/players/${id}/form?limit=10`),                     // last 10 results with opponent ranks
    get(`/players/${id}/matches?view=summary&page_size=20`), // match log, one slim row per match
    get(`/rankings/history/${id}?limit=520&order=asc`),      // ~10 years of weekly ranks for a chart
  ]);
  return { profile, stats, form, log: log.items, ranks: ranks.history };
}
SectionFields
Headerfull_name, ioc, iso_alpha2 (flag), dob, hand, current_rank (null when off the list: show last_rank), career_high_rank and career_high_date, portrait_url with its credit
Recordcareer_summary (titles, Grand Slam titles, win %), surface_breakdown, by_level
Game styleserving_stats and return_stats (first-serve won %, break points saved %, return games won %), clutch_and_situational (tiebreaks, deciding sets, vs top 10)
Form stripform.matches[]: result W/L, score, opponent_rank, surface
Ranking chartranks[] (the response's history): date, rank, points per published week, plus total_weeks_at_no_1

Filter the record with /players/{id}/stats?surface=Clay, level=G or year_from / year_to for surface tabs or a season selector.

3. Rivalries

One call gives a rivalry with surface, level, format, tiebreak and deciding-set splits. For a grid of a player against several rivals, use the matrix (2 to 16 players).

bash
curl "https://api.citoapi.com/api/v1/tennis/h2h?players=atp_206173,atp_207989" -H "x-api-key: YOUR_API_KEY"
curl "https://api.citoapi.com/api/v1/tennis/h2h/matrix?player_ids=atp_206173,atp_207989,atp_100644,atp_104925" -H "x-api-key: YOUR_API_KEY"

4. Match statistics on the log

To show serve stats next to each match in the log, add include=stats to the same call instead of calling /matches/{id}/stats for every row:

bash
curl "https://api.citoapi.com/api/v1/tennis/players/atp_206173/matches?page_size=20&include=stats" -H "x-api-key: YOUR_API_KEY"

Caching

  • Profile, career stats and ranking history change at most weekly (rankings publish on Mondays): cache for a day.
  • Form and the match log change when the player plays: cache for an hour, or refresh on a tennis.match.completed webhook for that player.
  • A cached page costs 0 calls. Five calls per uncached page view.

Find any player's id

Search is typo-tolerant and knows nicknames, so a search box can feed this page directly.

bash
curl "https://api.citoapi.com/api/v1/tennis/players/search?q=sinner&limit=5" \
  -H "x-api-key: YOUR_API_KEY"
Was this page helpful?