For the complete documentation index, see llms.txt. This page is also available as Markdown.

Season Dashboard Guide

🏎️ Motorsport API Required

This guide requires an active Motorsport API subscription (€79/mo, 3,000 API calls/hr).

View pricing β†’

This guide walks through how to build a season dashboard using the Motorsport API - combining championship standings, race results, and the season schedule into a complete season overview.

What you'll learn:

  • How to retrieve the current season and its key IDs in a single call

  • How to fetch driver and constructor standings with participant data

  • How to retrieve the season schedule and race results

  • How to structure and cache data efficiently for a dashboard

Prerequisites: Active Motorsport API subscription, API token, familiarity with REST APIs

1. When to use a season dashboard approach

This approach is well suited to:

  • Season overview pages showing standings, completed results, and upcoming races

  • Fantasy F1 applications needing current championship positions and points

  • Data tools comparing driver or constructor performance across a season

  • Press and media dashboards tracking championship progression

It is a read-heavy, low-frequency data pattern. Unlike live timing, season dashboard data changes only after each race weekend - typically once every two weeks. Cache aggressively.

2. Step 1: Get the current season ID

Everything in the season dashboard is keyed on the season ID. The most efficient way to get it without hardcoding:

The currentSeason include returns the active season object embedded in the league response. Extract currentSeason.id - this is your season ID for all subsequent calls.

Alternatively, if you already know the season ID (e.g. 25273 for 2025), you can skip this call and hardcode it. The season ID is stable - it will not change once assigned.

You can also confirm the season is still current and check when standings were last updated:

The standings_recalculated_at field tells you exactly when the standings data was last updated - use this as a cache invalidation signal. If the timestamp has not changed since your last fetch, standings have not been updated and you do not need to re-fetch.

3. Step 2: Fetch driver and constructor standings

With the season ID in hand, fetch both championship tables in parallel:

World Drivers' Championship:

World Constructors' Championship:

Both endpoints share the same response shape. The participant include resolves participant_id to a full driver or team profile. The stage include resolves stage_id to the most recently completed race weekend - use this to display "Standings after Round X: [Grand Prix Name]" context in your UI.

Both endpoints support pagination - iterate through all pages to get the full grid (20 drivers, 10 teams).

4. Step 3: Fetch the season schedule

The Schedules endpoint returns the complete season calendar - all race weekends, all sessions, and circuit data - in a single paginated response:

The response is nested: stages (race weekends) containing fixtures (sessions) containing venues (circuits with metadata). No includes needed - all data is pre-embedded.

Paginate through all stages and separate them into completed and upcoming rounds:

Cache this response aggressively - schedule data changes infrequently. Refresh it at the start of each race weekend and after any official FIA calendar revision.

5. Step 4: Fetch race results

For a season results table showing each driver's finish position per race, use the Race Results endpoint. It returns all race and sprint race fixtures with full lineup data for a specific driver or team:

This endpoint has no includes available - all data is pre-embedded. The response is nested: stages containing fixtures containing lineups containing details.

Each detail object in the lineup has a type_id identifying the data point (position, points, grid position, etc.). Resolve these via the Results & Live Data Type Reference.

The player_id in lineup objects is the same value as participant_id in standings responses - use it as the join key to match standings data with race result data for the same driver.

For a full season results grid across all drivers, you would need to call this endpoint once per driver. For most dashboard use cases, fetch results on demand when a user selects a specific driver rather than pre-fetching all 20 drivers upfront.

6. Step 5: Assemble the dashboard

A typical season dashboard requires four data sets:

Data
Endpoint
Refresh frequency

Season ID + metadata

leagues/3468?include=currentSeason

Once per session / on load

Driver standings

standings/drivers/seasons/SEASON_ID

After each race weekend

Constructor standings

standings/teams/seasons/SEASON_ID

After each race weekend

Season schedule

schedules/seasons/SEASON_ID

Weekly / on FIA calendar change

Driver race results

results/seasons/SEASON_ID/drivers/DRIVER_ID

On demand per driver

Fetch the first four in parallel on dashboard load. Use standings_recalculated_at from the season endpoint to decide whether a standings re-fetch is needed:

7. Common pitfalls

Fetching standings without paginating

Standings endpoints paginate. A 20-driver grid will return results across multiple pages. Always paginate to get all standings entries - stopping at page 1 will miss drivers further down the championship.

Not using standings_recalculated_at as a cache signal

Standings are recalculated after each race. The standings_recalculated_at field on the season object is the correct signal to check before re-fetching. Polling standings on a fixed timer wastes API calls between race weekends when nothing has changed.

Expecting race results to include practice and qualifying

The Race Results endpoint returns race sessions and sprint race sessions only. Practice, qualifying, and sprint qualifying fixtures are excluded. Use GET Fixture by ID with ?include=lineups.details for session-level results from non-race sessions.

Using starting_at string order for race results

The Race Results response contains stages in the order returned by the API. Always use sort_order on the stage to order rounds chronologically in your results table - do not rely on starting_at string sorting.

Pre-fetching all driver race results on load

With 20 drivers, fetching all race results upfront means 20 paginated API calls. Fetch race results on demand when a user selects a driver, not on initial dashboard load.

9. FAQ

Q: How do I know when standings have been updated after a race?

Check standings_recalculated_at on the season object. This timestamp updates after each race weekend once points have been processed. If it has changed since your last fetch, re-fetch standings. If it has not changed, your cached data is still current.

Q: How do I display "Standings after Round X"?

Include ?include=stage on the standings endpoints. The stage object embedded on each standing record is the most recently completed race weekend. Use its name and sort_order to display "Standings after Round 12: Formula 1 British Grand Prix".

Q: Can I get the full season results grid for all drivers in one call?

No. The Race Results endpoint is scoped to a single driver or team per call. For a full grid, call it once per driver. For a more efficient alternative, use the Fixtures endpoint with ?include=lineups.details on individual race fixtures, which returns all drivers' results for that specific session in a single call.

Q: How do I find a driver's ID to use in the race results endpoint?

Use the search endpoint: GET /v3/motorsport/drivers/search/norris?api_token=YOUR_TOKEN. The id returned is the same value used as player_id in race results responses and participant_id in standings responses.

Q: Is this available in all subscription plans?

All Motorsport API endpoints require an active Motorsport API subscription (€79/mo). View pricing β†’

Last updated

Was this helpful?