> 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/introduction/pagination.md).

# Pagination

Responses to broad requests can return more results than fit in a single page. This tutorial covers how to walk through large result sets using cursor-based pagination.

10 minutes Skill level: Beginner Prerequisites: Make your first request

### Why pagination exists

A request like "all drivers" or "all fixtures" can return thousands of records. Returning everything in one response would be slow and difficult to work with. Instead, the API splits results into pages and gives you a cursor to fetch the next one.

### The pagination object

Every paginated response includes a `pagination` object at the end of the response body:

```json
{
  "data": [ ... ],
  "pagination": {
    "count": 25,
    "per_page": 25,
    "current_page": 1,
    "next_cursor": "WzEsMixbMTk3MTAxMDBdLFtbInNwb3J0cy5maXh0dXJlcy5pZCIsMV1dXQ",
    "has_more": true
  }
}
```

`has_more` tells you whether there are additional pages. `next_cursor` is the value you pass on your next request to retrieve them.

### Walking through pages

1. Make a standard request with no cursor.
2. Use `per_page` to control how many results come back per page (range 1-50, default 25).
3. Take the `next_cursor` value from the response and pass it as a `cursor` parameter on your next request.
4. Repeat until `has_more` is `false`.

```
https://api.sportmonks.com/v3/motorsport/fixtures
?api_token=YOUR_TOKEN&order=desc&per_page=25&cursor=WzEsMixbMTk3MTAxMD...
```

When there are no more pages, the response looks like this:

```json
{
  "pagination": {
    "count": 14,
    "per_page": 25,
    "current_page": 1,
    "next_cursor": null,
    "has_more": false
  }
}
```

### Code example

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

```javascript
async function fetchAllFixtures(apiToken) {
  const baseUrl = 'https://api.sportmonks.com/v3/motorsport/fixtures';
  let cursor = null;
  let allFixtures = [];

  do {
    const url = new URL(baseUrl);
    url.searchParams.set('api_token', apiToken);
    url.searchParams.set('order', 'desc');
    url.searchParams.set('per_page', '25');
    if (cursor) url.searchParams.set('cursor', cursor);

    const response = await fetch(url.toString());
    const data = await response.json();
    allFixtures = allFixtures.concat(data.data);
    cursor = data.pagination.has_more ? data.pagination.next_cursor : null;
  } while (cursor);

  return allFixtures;
}
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

def fetch_all_fixtures(api_token):
    base_url = "https://api.sportmonks.com/v3/motorsport/fixtures"
    cursor = None
    all_fixtures = []

    while True:
        params = {
            "api_token": api_token,
            "order": "desc",
            "per_page": 25,
        }

        if cursor:
            params["cursor"] = cursor

        response = requests.get(base_url, params=params)
        response.raise_for_status()

        data = response.json()

        all_fixtures.extend(data.get("data", []))

        pagination = data.get("pagination", {})
        cursor = pagination.get("next_cursor") if pagination.get("has_more") else None

        if not cursor:
            break

    return all_fixtures
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
function fetchAllFixtures(string $apiToken): array {
  $baseUrl = 'https://api.sportmonks.com/v3/motorsport/fixtures';
  $cursor = null;
  $allFixtures = [];

  do {
    $params = [
      'api_token' => $apiToken,
      'order' => 'desc',
      'per_page' => 25,
    ];
    if ($cursor) {
      $params['cursor'] = $cursor;
    }

    $url = $baseUrl . '?' . http_build_query($params);
    $response = json_decode(file_get_contents($url), true);
    $allFixtures = array_merge($allFixtures, $response['data']);
    $cursor = $response['pagination']['has_more'] ? $response['pagination']['next_cursor'] : null;
  } while ($cursor);

  return $allFixtures;
}
```

{% endtab %}
{% endtabs %}

### Populating a database

If you are populating your own database rather than displaying live results, add `filters=populate` to raise the pagination limit to a maximum of 1000 per page. Note that includes are disabled when this filter is used, to prevent overloading the API.

```http
https://api.sportmonks.com/v3/motorsport/drivers
?api_token=YOUR_TOKEN&filters=populate&per_page=1000
```

### Common pitfalls

**Treating the cursor as reusable.** A `next_cursor` value is only valid for the next request in the sequence. Do not store it and reuse it after fetching other pages.

**Forgetting that every page counts against your rate limit.** Fetching pages 1 through 10 counts as 10 calls against the relevant entity's hourly limit, not one.

**Mixing page-number pagination with cursor pagination.** The older `page=` parameter is still supported for existing integrations, but mixing it with `cursor=` in the same request produces undefined behaviour. Pick one approach per integration.

### FAQ

**Is the old page-number pagination still supported?** Yes, for existing integrations. New integrations should use cursor-based pagination since it is faster and puts less load on the API.

**What is the maximum `per_page` value?** 50 by default, or up to 1000 when using `filters=populate` (with includes disabled).

### Related

* [Make your first request](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/introduction/make-your-first-request)
* [Filter and select fields](https://docs.sportmonks.com/v3/motorsport-api/tutorials-and-guides/tutorials/filter-and-select-fields)


---

# 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/introduction/pagination.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.
