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 usersGET /v1/connections— their authorizationsGET /v1/activities— the workouts you have been granted
GET /v1/activities?limit=100 HTTP/1.1{
"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:
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.