Pagination
Lists page in one of two ways. Each endpoint's parameters in the REST API reference say which it takes.
Cursor paging
Send limit, then pass the previous answer's nextCursor as cursor until
hasMore is false (or nextCursor is null).
| List | Page size (default / max) |
|---|---|
GET /events | 20 / 100 |
GET /products (also takes offset) | 20 / 100 |
GET /me/directory | 24 / 100 |
GET /me/friends | 50 / 100 |
GET /me/members/{usertag}/friends | 24 / 100 |
GET /me/notifications | 20 / 100 |
GET /finance/entries, GET /finance/payouts | 100 / 500 (a larger value is clamped, not refused) |
let cursor: string | undefined;
do {
const page = await cobuntu.events.list({ upcoming: true, limit: 50, cursor });
render(page.events);
cursor = page.nextCursor ?? undefined;
} while (cursor);- Treat the cursor as opaque. Do not build one from an
id. - Keep the same filters and
sortacross pages. - A malformed cursor is a
400, deliberately: restarting silently from the top would look like it worked and duplicate everything downstream. - Finance entries come back oldest first, so a cursor walks forward in
time and an incremental sync never re-reads the head of the list. Every
entry also carries its own
cursorto resume from.
Offset paging
Send limit and offset. Answers carry a pagination object
{ total, limit, offset, hasMore } where the endpoint reports one.
| List | Page size (default / max) |
|---|---|
GET /members | see the reference |
GET /articles, GET /courses | see the reference |
GET /me/purchases | 20 / 50 |
GET /me/ledger | 20 / 100 |
GET /api/v1/users/me/products, GET /api/v1/users/me/events | 20 / 100 |
Filters apply before paging
Filters are applied before the page is cut, so every page is full. An unknown
category id narrows to nothing and returns an empty page rather than a 400,
so a filter pointed at a deleted category does not break the page.