Pagination
Cursor-based, never offset — and no totals, on purpose.
meta.next_cursor. Do not construct one.The loop#
Ask for a page, do something with data, and follow meta.next_cursor until it comes back null. That is the whole protocol.
let cursor = nulldo { const url = new URL("https://api.zinevu.com/api/public/v1/leads") url.searchParams.set("limit", "100") if (cursor) url.searchParams.set("cursor", cursor) const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.ZINEVU_API_KEY}` }, }) const { data, meta } = await res.json() for (const lead of data) await store(lead) cursor = meta.next_cursor // null on the last page} while (cursor)Why there is no total#
List responses carry no count of the whole matching set. Counting it is the expensive part of a paginated response — a second query over every matching row — and paying it on every page to produce a number most integrations discard is not a trade we make. has_more answers the only question a loop actually asks.
What a cursor guarantees#
- It is ordered by our
id, so a record created while you are paginating appears on a later page rather than shifting the ones you already read. Offset pagination is what makes a row show up twice, or never. - It is opaque. It encodes the position, it is not a record id, and a cursor from one endpoint means nothing to another.
- It has no expiry, but a long pause between pages is still a bad idea: you are holding a view of a list that is being edited by people.
Syncing incrementally#
Store the newest updated_at you have processed and pass it back on the next run. Records are returned when they change, whatever changed about them, so this catches an edit as well as a creation.
curl "https://api.zinevu.com/api/public/v1/offers?updated_since=2026-09-01T00:00:00Z&limit=100" \ -H "Authorization: Bearer $ZINEVU_API_KEY"Rewind your stored timestamp by 60 seconds on each run. Writes land at slightly different instants than the clock you read them with, and re-reading a handful of records costs nothing — missing one costs a lead.