Facebook Pixel
Fit'DistanceDocumentation
Open the app
On this page

Pagination

Read a list page by page with limit and cursor, reread only the changes with since, and handle deleted objects.

A list never returns everything at once. It returns one page, sorted by date of change and then by id, and tells you whether another page remains. A page costs one credit, whatever its number of objects.

The parameters of a list

ParameterRole
limitObjects per page, from 1 to 200. Default: 50.
cursorThe next_cursor of the previous page.
sinceISO 8601 date. Returns the objects with updated_at >= since.
include_deletedWith true, adds the deleted objects.
student_id, statusFilters, on the lists that know them only.

A parameter that a list does not know, or a limit outside 1 to 200, is refused with a 400 VALIDATION, and the call stays billed.

Follow the pages

Every response has the same shape:

{
  "data": [ … ],
  "has_more": true,
  "next_cursor": "MjAyNi0xMC0yNVQwOToxMjowMC4wMDBafDQzMTg"
}

While has_more is true, call the same route again with cursor set to next_cursor. On the last page, next_cursor is null. The cursor is opaque: it encodes the position of the last object received, so do not build one. Keep the same filters (since, student_id, status, include_deleted) from one page to the next.

These loops use the call function from Write a script:

Python

def read_all(path, **filters):
    items, cursor = [], None
    while True:
        params = {**filters, "limit": 200}
        if cursor:
            params["cursor"] = cursor
        page = call("GET", path, params=params)
        items += page["data"]
        if not page["has_more"]:
            return items
        cursor = page["next_cursor"]

JavaScript

async function readAll(path, filters = {}) {
  const items = [];
  let cursor;
  do {
    const query = new URLSearchParams({ ...filters, limit: "200" });
    if (cursor) query.set("cursor", cursor);
    const page = await call("GET", `${path}?${query}`);
    items.push(...page.data);
    cursor = page.has_more ? page.next_cursor : undefined;
  } while (cursor);
  return items;
}

Reread only the changes

After a first full read, keep the largest updated_at you received. Pass it as since on the next read, with include_deleted=true: you receive what changed, deletions included. Without it, a read by since never sees a deleted object.

The test is inclusive. The object with exactly that date comes back a second time, and an object modified while you read may come back further on. Deduplicate by id and keep the last one received.

The updated_at of a student also moves on each login of the student. A daily sync therefore sees again the students who logged in since the day before, with no visible change.

Deleted objects

Without include_deleted, a deleted object simply disappears from the list. With include_deleted=true, it comes back with a deleted_at set: remove it from your copy. The field exists only on the resources that carry it, not on Student: a student who leaves your coaching is read in GET /students/departures, described in the reference.

Next pageWrites and idempotencyWrite with POST /operations, retry without duplicates using Idempotency-Key and preview an effect with dry_run.