Pagination
Lists are paged with a cursor. Each response returns a last_id and a keyset. Send both back to get the next page, and stop when last_id comes back null.
Storefront lists used to be paged by page number only. They now return a cursor too, and it’s the way to page through them. Page numbers still work for numbered page links, but move “load more”, infinite scroll and syncing over to last_id and keyset. A cursor doesn’t skip or repeat records when new ones are added while you page, and it stays fast however far you go.
Request parameters
last_id and keyset are opaque. Don’t parse them or build them yourself. Copy them from one response into the next request.
Send the same filters, search and sort_by on every page as you sent for the first one. To change any of them, start again without a cursor.
Paging through a list
Fetch the first page without last_id or keyset:
Then pass the last_id and keyset you got back as query parameters:
Keep going with the pair from each response. You’ve reached the end when a response comes back with last_id: null, which can arrive with an empty data list. Stop there rather than counting pages.
Core endpoints
Core lists such as invoices, receipts, bills, expenses and journal entries take a cursor only. A page or offset parameter is ignored, so sending one just returns the first page again.
Core lists are always returned newest first (created_at descending). They don’t take sort_by.
Storefront endpoints
These Storefront lists return a cursor:
- List Products
- List Collections
- Get Collection (its products)
- List Articles
- List Comments
- List Reviews
- List Orders
sort_by works with cursors, including price and title sorts. Products with no price sort last in both price orders.
Get Collection and List Reviews put these fields inside data, next to the collection or the rating.
Page numbers
Storefront lists still accept page, starting at 1, so a shop can show numbered pages and jump between them. A page past the last one returns an empty list. When a request has last_id and keyset, page is ignored.
Every response, whether you paged by number or by cursor, includes last_id and keyset. You can switch to the cursor from any numbered page.

