Pagination
Lists are the one place we don't strip the envelope. Every list() call returns { data, pagination, hasMore } because the page metadata is part of the answer,
not metadata about it.
List shape
Page params
Pass page and pageSize on any list call. Defaults: page 1, pageSize 20,
max pageSize 100.
paginate.js
// First page
const { data, pagination, hasMore } = await cstar.tickets.list({
status: 'open',
page: 1,
pageSize: 20
});
console.log(`Page ${pagination.page} — ${data.length} of ${pagination.total} tickets`);
if (hasMore) {
// Fetch the next page
const next = await cstar.tickets.list({ status: 'open', page: 2, pageSize: 20 });
}Walk every page
hasMore is the loop sentinel. Drive a while loop off it instead of comparing
computed totals — pagination math drifts if rows are written between requests.
walk-all.js
async function* allTickets(filter) {
let page = 1;
while (true) {
const { data, hasMore } = await cstar.tickets.list({ ...filter, page, pageSize: 100 });
yield* data;
if (!hasMore) return;
page += 1;
}
}
for await (const ticket of allTickets({ status: 'open' })) {
await mirrorToWarehouse(ticket);
}Pagination on lastMeta
The same pagination object also lands on cstar.lastMeta.pagination after every list
call, so middleware that wraps the SDK can grab it without re-reading the response shape.