> For the complete documentation index, see [llms.txt](https://docs.sportmonks.com/v3/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/standings/championship-standings.md).

# Championship standings

This guide covers how to retrieve driver and constructor championship standings, enrich them with participant and round context, and use them to build championship tables and season dashboards.

#### When to use this

Use the Standings endpoints when you want to:

* Display the current drivers' championship table
* Display the current constructors' championship table
* Show which race weekend standings are current as of
* Track points gaps between drivers or constructors
* Build a season summary page with final championship positions

#### Driver standings vs constructor standings

The Motorsport API provides **separate endpoints** for the World Drivers' Championship and the World Constructors' Championship. They share the same response shape but resolve `participant_id` to different entity types.

|                              | Driver standings                           | Constructor standings           |
| ---------------------------- | ------------------------------------------ | ------------------------------- |
| Endpoint                     | `/standings/drivers/seasons/{id}`          | `/standings/teams/seasons/{id}` |
| `participant_id` resolves to | Driver profile                             | Team/constructor profile        |
| Points source                | Individual race finishes and sprint points | Combined points of both drivers |

#### The Standing entity fields

<table data-search="false"><thead><tr><th>Field</th><th>Description</th><th>Type</th></tr></thead><tbody><tr><td><code>id</code></td><td>Unique ID of the standing entry</td><td>integer</td></tr><tr><td><code>participant_id</code></td><td>ID of the driver or team</td><td>integer</td></tr><tr><td><code>sport_id</code></td><td>Sport ID</td><td>integer</td></tr><tr><td><code>league_id</code></td><td>The championship this standing belongs to</td><td>integer</td></tr><tr><td><code>season_id</code></td><td>The season this standing belongs to</td><td>integer</td></tr><tr><td><code>stage_id</code></td><td>The most recently completed race weekend this standing reflects</td><td>integer</td></tr><tr><td><code>position</code></td><td>Championship position (1 = leader)</td><td>string</td></tr><tr><td><code>points</code></td><td>Total accumulated points</td><td>integer</td></tr></tbody></table>

`result`, `group_id`, `round_id`, and `standing_rule_id` are not used in the Motorsport API.

#### Available includes

`sport` `participant` `season` `league` `stage`

`participant` resolves to the full driver or team profile depending on which endpoint you call. `stage` resolves `stage_id` to the race weekend name and date, useful for displaying "Standings after Round X" context.

Maximum include depth: 2 nested includes.

#### Retrieving standings

**Current drivers' championship:**

```http
GET https://api.sportmonks.com/v3/motorsport/standings/drivers/seasons/{season_id}
?api_token={your_token}&include=participant
```

**Current constructors' championship:**

```http
GET https://api.sportmonks.com/v3/motorsport/standings/teams/seasons/{season_id}
?api_token={your_token}&include=participant
```

**With round context (which race they reflect):**

```http
GET https://api.sportmonks.com/v3/motorsport/standings/drivers/seasons/{season_id}
?api_token={your_token}&include=participant;stage
```

**Lightweight (position and points only):**

```http
GET https://api.sportmonks.com/v3/motorsport/standings/drivers/seasons/{season_id}
?api_token={your_token}&select=position,points,participant_id&include=participant
```

For all seasons rather than a specific one, use `GET All Driver Standings` or `GET All Team Standings` without the season path. The by-season endpoints are the right choice for most use cases to avoid fetching unnecessary historical data.

#### Working with the data

**Build a drivers' championship table**

{% tabs %}
{% tab title="JavaScript" %}

```javascript
const API_TOKEN = 'your_token';

async function getDriverStandings(seasonId) {
  const response = await fetch(
    `https://api.sportmonks.com/v3/motorsport/standings/drivers/seasons/${seasonId}?api_token=${API_TOKEN}&include=participant;stage`
  );
  const { data } = await response.json();
  return data.sort((a, b) => parseInt(a.position) - parseInt(b.position));
}

const standings = await getDriverStandings(25273);
standings.forEach(entry => {
  console.log(`P${entry.position} ${entry.participant.display_name} - ${entry.points} pts`);
});
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

API_TOKEN = "your_token"

def get_driver_standings(season_id):
    url = f"https://api.sportmonks.com/v3/motorsport/standings/drivers/seasons/{season_id}"
    params = {
        "api_token": API_TOKEN,
        "include": "participant;stage"
    }
    response = requests.get(url, params=params)
    standings = response.json()["data"]

    return sorted(standings, key=lambda s: int(s["position"]))

standings = get_driver_standings(25273)
for entry in standings:
    driver = entry["participant"]
    print(f"P{entry['position']} {driver['display_name']} - {entry['points']} pts")
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
function getDriverStandings(string $apiToken, int $seasonId): array {
    $url = "https://api.sportmonks.com/v3/motorsport/standings/drivers/seasons/
           {$seasonId}?api_token={$apiToken}&include=participant;stage";
    $standings = json_decode(file_get_contents($url), true)['data'];
    usort($standings, fn($a, $b) => (int)$a['position'] <=> (int)$b['position']);
    return $standings;
}
```

{% endtab %}
{% endtabs %}

**Build a constructors' championship table**

{% tabs %}
{% tab title="JavaScript" %}

```javascript
async function getConstructorStandings(seasonId) {
  const response = await fetch(
    `https://api.sportmonks.com/v3/motorsport/standings/teams/seasons/${seasonId}
     ?api_token=${API_TOKEN}&include=participant`
  );
  const { data } = await response.json();
  return data.sort((a, b) => parseInt(a.position) - parseInt(b.position));
}
```

{% endtab %}

{% tab title="Python" %}

```python
def get_constructor_standings(season_id):
    url = f"https://api.sportmonks.com/v3/motorsport/standings/teams/seasons/
          {season_id}"
    params = {
        "api_token": API_TOKEN,
        "include": "participant"
    }
    response = requests.get(url, params=params)
    standings = response.json()["data"]
    return sorted(standings, key=lambda s: int(s["position"]))
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
function getConstructorStandings(string $apiToken, int $seasonId): array {
    $url = "https://api.sportmonks.com/v3/motorsport/standings/teams/seasons/
            {$seasonId}?api_token={$apiToken}&include=participant";
    $standings = json_decode(file_get_contents($url), true)['data'];
    usort($standings, fn($a, $b) => (int)$a['position'] <=> (int)$b['position']);
    return $standings;
}
```

{% endtab %}
{% endtabs %}

**Show points gap to championship leader**

{% tabs %}
{% tab title="JavaScript" %}

```javascript
function getPointsGap(standings) {
  const leaderPoints = standings[0]?.points ?? 0;
  return standings.map(s => ({
    position: s.position,
    name: s.participant.display_name,
    points: s.points,
    gap: leaderPoints - s.points
  }));
}
```

{% endtab %}

{% tab title="Python" %}

```python
def get_points_gap(standings):
    leader_points = standings[0]["points"] if standings else 0
    return [
        {
            "position": s["position"],
            "name": s["participant"]["display_name"],
            "points": s["points"],
            "gap": leader_points - s["points"]
        }
        for s in standings
    ]
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
function get_points_gap($standings) {
    $leaderPoints = $standings[0]["points"] ?? 0;
    return array_map(function ($standing) use ($leaderPoints) {
        $points = $standing["points"] ?? 0;
        return [
            "position" => $standing["position"] ?? null,
            "name" => $standing["participant"]["display_name"] ?? null,
            "points" => $points,
            "gap" => $leaderPoints - $points
        ];
    }, $standings);
}
```

{% endtab %}
{% endtabs %}

**Display which round standings are current as of**

{% tabs %}
{% tab title="JavaScript" %}

```javascript
function getStandingsContext(standings) {
  const stage = standings[0]?.stage;
  return stage ? `Standings after Round ${stage.sort_order}: ${stage.name}` : null;
}
```

{% endtab %}

{% tab title="Second Tab" %}

```python
def get_standings_context(standings):
    if not standings:
        return None
    stage = standings[0].get("stage")
    if stage:
        return f"Standings after Round {stage['sort_order']}: {stage['name']}"
    return None
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
function get_standings_context($standings) {
    $stage = $standings[0]["stage"] ?? null;
    if (!$stage) {
        return null;
    }
    $sortOrder = $stage["sort_order"] ?? null;
    $stageName = $stage["name"] ?? "";
    return "Standings after Round " . $sortOrder . ": " . $stageName;
}
```

{% endtab %}
{% endtabs %}

#### Common pitfalls

**Using a single `/standings` endpoint to get both driver and constructor standings.** These are separate endpoints: `/standings/drivers/seasons/{id}` for drivers and `/standings/teams/seasons/{id}` for constructors. You cannot get both from one call.

**Using the "all standings" endpoints for current standings.** `GET All Driver Standings` and `GET All Team Standings` return standings across every season. Always use the by-season-ID endpoints for a specific season's current standings.

**`position` is a string, not an integer.** Convert to integer before sorting: `int(s["position"])` in Python, `parseInt(s.position)` in JavaScript.

**Expecting `result` to show position movement.** The `result` field is not used in the Motorsport API and is always null. Do not build UI logic around it.

**Polling standings during a live race.** Standings update after a session is marked as finished, not during. Fetch standings once after you detect the session state has changed to finished. See [Session states](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/live-data/session-states).

#### Common errors

| Status | Likely cause                                                |
| ------ | ----------------------------------------------------------- |
| `401`  | Missing or invalid `api_token`                              |
| `404`  | The season ID does not exist or is not in your subscription |

#### See also

**Related tutorials**

* [Leagues and seasons](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/schedule-and-calendar/leagues-and-seasons)
* [Session states](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/live-data/session-states)
* [Drivers](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/drivers-and-teams/drivers)
* [Teams](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/drivers-and-teams/teams)

**Reference**

* [Standing entity](https://docs.sportmonks.com/v3/motorsport-api/endpoints-and-entities/entities/standing.md)
* [Standings endpoints](https://docs.sportmonks.com/v3/motorsport-api/endpoints-and-entities/endpoints/standings)
* [Race Results endpoints](https://docs.sportmonks.com/v3/motorsport-api/endpoints-and-entities/endpoints/race-results)

#### FAQ

**How do I get the season ID to pass to the standings endpoint?** See [Leagues and seasons](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/schedule-and-calendar/leagues-and-seasons). The 2025 F1 season ID is `25273`.

**What is `stage_id` on a standing entry?** It is the ID of the most recently completed race weekend that this standing reflects. Include `stage` to resolve it to the weekend name and round number, useful for displaying "Standings after Round X" in your UI.

**Can I get standings after a specific race round?** Use `standingStages` filter with the stage ID of the race weekend to get standings as they stood after that round.

**How do I link a standing entry back to lap or result data?** The `participant_id` on a standing entry is the same value as `participant_id` across laps, pitstops, stints, and race results endpoints. Use it directly to join standings data with session-level performance data.

**Are sprint race points included in standings?** Yes. Points from sprint races (where `SPRINT_RACE` metadata is true) are included in the season standings totals.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/standings/championship-standings.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
