Stridee
Stridee Docs

Paging

Every list on this API pages the same way — a cursor naming the last row you saw, not an offset counting rows you skipped.

Three endpoints return more rows than fit in one response, and all three page identically:

  • GET /v1/accounts — your users
  • GET /v1/connections — their authorizations
  • GET /v1/activities — the workouts you have been granted
HTTP
GET /v1/activities?limit=100 HTTP/1.1
200
{
  "activities": [ "…" ],
  "has_more": true,
  "next_starting_after": "7e14a9c3-2b60-4f85-9d3a-6c081ef47b52",
  "total": 1284
}

Send next_starting_after back as starting_after and you get the next page. Keep going while has_more is true:

reconcile.ts
let cursor: string | undefined;

do {
  const page = await stridee.get('/v1/activities', { since, until, limit: 200, starting_after: cursor });
  for (const activity of page.activities) await handle(activity);
  cursor = page.next_starting_after;
} while (cursor);

starting_after takes the id of the last row you received — a value you already have and can read in a log line, not an opaque token. It must name a row of yours, or you get a 400: an unknown cursor is a bug in a loop, and answering it with an empty page would look exactly like reaching the end.

Two fields worth reading carefully

has_more is the paging control, not total. It is exact; stop when it is false.

total is on the first page only (the one without starting_after) and null after it. It is for the number above a table, not for the loop.

Why there is no offset

Every list is newest-first over data that keeps arriving. With an offset, a new row pushes everything down and page two repeats page one. A cursor names a row, so nothing arriving above it moves you — and it costs the same on page 5,000 as on page one.

For a fixed window, such as a nightly reconcile of activities, see Listing what you were sent.

Something wrong or missing on this page? Tell us in Discord. Need something the API doesn’t do yet? Request it on the roadmap.