All systems normalData updated just nowStatusChangelogSupport
badmintonapi

Pages of results

Lists come 50 at a time by default, and up to 200 with per_page. Every list endpoint takes the same three parameters, page, per_page and cursor, and every list answer carries what you need to fetch the next page in meta. There are two ways through a long list; pick the one that fits what you are building.

By page number

Ask for ?page=3&per_page=100 and meta tells you total, total_pages, next_page and prev_page. This suits a table a person pages through, where you need to show "page 3 of 13" and jump straight to any page.

meta on page 3 of 13
"meta": {
  "count": 100, "page": 3, "per_page": 100,
  "total": 1204, "total_pages": 13,
  "next_page": 4, "prev_page": 2,
  "next_cursor": "bzMwMHAxMDA"
}

By cursor

Pass meta.next_cursor back as ?cursor= and keep going until it comes back null. A cursor holds its place even if the list grows while you read it, so it is the right choice for a program that reads everything: a nightly copy of a player's matches, or every draw of a season.

Python: read a whole list
def every(path, **params):
    params["per_page"] = 200
    while True:
        body = get(path, **params)
        yield from body["data"]
        cursor = body["meta"].get("next_cursor")
        if not cursor:
            return
        params["cursor"] = cursor

matches = list(every("/players/pl_XXXXXXXX/matches"))
JavaScript: the same, as an async generator
async function* every(path, params = {}) {
  params.per_page = 200;
  while (true) {
    const q = new URLSearchParams(params);
    const body = await get(`${path}?${q}`);
    yield* body.data;
    if (!body.meta.next_cursor) return;
    params.cursor = body.meta.next_cursor;
  }
}

for await (const m of every("/matches", { year: 2024 })) {
  console.log(m.id);
}

Getting it right

Use the largest page you need: per_page=200 reads a list in a quarter of the calls the default takes, and every call counts against your limits whatever its size. Keep the other parameters the same from page to page, so every page belongs to the same list. Do not build cursors yourself: they are opaque and may change form, so only ever pass back the one meta gave you.

Which way to choose

If you need a count before you start, read meta.total from the first page: it is there whichever way you go on. Page numbers let a person jump to page 9 without reading pages 1 to 8, so they suit screens. Cursors only go forward, one page after another, but they never skip or repeat an item while the list is being added to, so they suit programs. Both use the same per_page, and both cost one call per page.