> 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/live-data/live-sessions.md).

# Live sessions

This guide covers how to retrieve currently active sessions using the Live endpoints, what data is available during a live session, and how to structure your polling strategy.

#### When to use this

Use the Live endpoints when you want to:

* Display sessions that are currently in progress or starting within the next 15 minutes
* Build a live race tracker that updates as the session unfolds
* Receive the most recent lap, pitstop, and result data without querying fixtures directly
* Detect when a session has recently finished (within the past 15 minutes)

For sessions outside this window (past results, upcoming fixtures), use the [Fixtures endpoints](https://docs.sportmonks.com/v3/motorsport-api/endpoints-and-entities/endpoints/fixtures) instead.

#### The Live endpoints

The Live entity has two endpoints:

**GET All Livescores** - returns all sessions that are live, starting within 15 minutes, or finished within the past 15 minutes:

```http
GET https://api.sportmonks.com/v3/motorsport/livescores
?api_token={your_token}
```

**GET Latest Updated Livescores** - returns all livescores that have received an update within the past 10 seconds:

```http
GET https://api.sportmonks.com/v3/motorsport/livescores/latest
?api_token={your_token}
```

Use `GET Latest Updated Livescores` for your main polling loop. It returns only sessions with recent changes, which means smaller payloads and faster responses compared to fetching all active sessions on every poll.

#### The response structure

The Live entity returns the same fields as the Fixture entity, since a livescore is a fixture filtered by its active time window:

```json
{
  "data": [
    {
      "id": 19408487,
      "sport_id": 2,
      "league_id": 3468,
      "season_id": 25273,
      "stage_id": 77475992,
      "state_id": 3,
      "venue_id": 343575,
      "name": "Race",
      "starting_at": "2025-03-16 15:00:00",
      "leg": "1/1",
      "placeholder": false,
      "starting_at_timestamp": 1742137200
    }
  ]
}
```

`state_id` tells you the current session state. Include `state` to get the human-readable label alongside it. See [Session states](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/live-data/session-states) for the full state reference.

#### Available includes

The Live endpoint supports the following includes:

`sport` `stage` `league` `season` `venue` `state` `lineups` `participants` `metadata` `results` `latestLaps` `pitstops` `latestPitstops` `stints` `latestStints`

Note `latestLaps`, `latestPitstops`, and `latestStints`. These return only the most recent entry per driver, rather than the full session history. Use them during active polling to keep payloads small. Use `laps`, `pitstops`, and `stints` (via the Fixtures endpoint) when you need the complete session dataset after a race is finished.

#### Enriching the live response

A minimal live request with state and current positions:

```http
GET https://api.sportmonks.com/v3/motorsport/livescores/latest
?api_token={your_token}&include=state;results
```

With driver names attached:

```http
GET https://api.sportmonks.com/v3/motorsport/livescores/latest
?api_token={your_token}&include=state;lineups.driver;results
```

With the latest lap per driver:

```http
GET https://api.sportmonks.com/v3/motorsport/livescores/latest
?api_token={your_token}&include=state;results;latestLaps
```

#### Working with the data

**Poll for live session updates**

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

```javascript
const API_TOKEN = 'your_token';

async function pollLiveSessions() {
  const response = await fetch(
    `https://api.sportmonks.com/v3/motorsport/livescores/latest?api_token=${API_TOKEN}&include=state;results;latestLaps`
  );
  const { data } = await response.json();
  return data ?? [];
}

setInterval(async () => {
  const sessions = await pollLiveSessions();
  sessions.forEach(session => {
    console.log(`${session.name} - state_id: ${session.state_id}`);
  });
}, 10000);
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
import time

API_TOKEN = "your_token"

def poll_live_sessions():
    url = "https://api.sportmonks.com/v3/motorsport/livescores/latest"
    params = {
        "api_token": API_TOKEN,
        "include": "state;results;latestLaps"
    }
    response = requests.get(url, params=params)
    return response.json().get("data", [])

while True:
    sessions = poll_live_sessions()
    for session in sessions:
        print(f"{session['name']} - state_id: {session['state_id']}")
    time.sleep(10)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
function pollLiveSessions(string $apiToken): array {
    $url = "https://api.sportmonks.com/v3/motorsport/livescores/latest?api_token={$apiToken}&include=state;results;latestLaps";
    $response = json_decode(file_get_contents($url), true);
    return $response['data'] ?? [];
}

while (true) {
    $sessions = pollLiveSessions('your_token');
    foreach ($sessions as $session) {
        echo "{$session['name']} - state_id: {$session['state_id']}\n";
    }
    sleep(10);
}
```

{% endtab %}
{% endtabs %}

**Detect when a session goes live**

Rather than inspect `state_id` directly against a magic number, include `state` and check the `developer_name` field, which is the stable string identifier for each state:

```python
def is_live(session):
    state = session.get("state")
    if not state:
        return False
    return state.get("developer_name") == "INPLAY"
```

```javascript
function isLive(session) {
  return session.state?.developer_name === 'INPLAY';
}
```

See [Session states](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/live-data/session-states) for all `developer_name` values.

#### Polling strategy

Keep your polling requests lean. Each include adds to payload size and query complexity.

**Recommended split:**

* **Every 10 seconds:** `livescores/latest` with `state;results` for position and gap data.
* **Every 30-60 seconds:** `livescores/latest` with `latestLaps` for lap timing.
* **Once per session:** Fetch `lineups.driver` from the Fixtures endpoint at session start and cache driver names locally. Do not include this on every live poll.

Caching reference data (driver names, team names, state labels) locally reduces both payload size and query complexity on every poll.

See [Query complexity](https://docs.sportmonks.com/v3/motorsport-api/welcome/query-complexity) for how each include affects your complexity score.

#### Common pitfalls

**Querying `GET All Livescores` instead of `GET Latest Updated Livescores` for polling.** `GET All Livescores` returns everything in the 15-minute window, including sessions with no recent changes. For a polling loop, `latest` is almost always the right choice.

**Including `laps` instead of `latestLaps` during a live session.** `laps` returns the complete lap history for the session, which grows with every lap completed. Use `latestLaps` during live polling and switch to `laps` via the Fixtures endpoint when you want the full dataset post-race.

**Expecting live data outside the 15-minute window.** The livescores endpoints do not return historical or future sessions. If a race finished more than 15 minutes ago, query the Fixtures endpoint by ID instead.

**Not handling an empty `data` array.** Between sessions there may be no active livescores. Always check that `data` is non-empty before trying to read session fields.

#### Common errors

| Status | Likely cause                                                                              |
| ------ | ----------------------------------------------------------------------------------------- |
| `401`  | Missing or invalid `api_token`                                                            |
| `429`  | Rate limit exceeded - reduce polling frequency or split includes across separate requests |
| `422`  | Query complexity exceeded - remove includes until the request succeeds                    |

#### See also

**Related tutorials**

* [Session states](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/live-data/session-states)
* [Retrieving results](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/retrieving-results)
* [How to Track Lap-by-Lap Timing for a Race](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/enrich-your-response/how-to-track-lap-by-lap-timing-for-a-race)
* [How to Fetch Pit Stop Data for a Race](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/enrich-your-response/how-to-fetch-pit-stop-data-for-a-race)

**Reference**

* [Live entity](https://docs.sportmonks.com/v3/motorsport-api/endpoints-and-entities/entities/live.md)
* [Query complexity](https://docs.sportmonks.com/v3/motorsport-api/welcome/query-complexity)
* [Results and Live Data Type Reference](https://docs.sportmonks.com/v3/motorsport-api/welcome/results-and-live-data-type-reference)

#### FAQ

**What is the difference between `GET All Livescores` and `GET Latest Updated Livescores`?** `GET All Livescores` returns everything in the 15-minute active window regardless of when it last changed. `GET Latest Updated Livescores` returns only sessions updated in the past 10 seconds. Use the latter for polling.

**What happens if no sessions are live?** Both endpoints return a `200` response with an empty `data` array. This is expected behaviour between sessions.

**Can I filter live sessions by league?** The Live endpoints share the same filter architecture as Fixtures. Check the Live endpoint's own Dynamic Filters tab for confirmed filter support.

**Does the live endpoint count against the Fixture entity rate limit?** Yes. The Live endpoints use the same underlying Fixture entity, so calls against `/livescores` count toward the same hourly rate limit bucket as calls against `/fixtures`.


---

# 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/live-data/live-sessions.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.
