Skip to content

Pagination

Most lists answer everything at once, up to 1,000 rows. The ones that can grow far past that come a page at a time, with a cursor:

ListRequestPermission
Page through the audit logGET /api/v1/audit/pagesettings:read
Page through contactsGET /api/v1/contacts/pagecrm:read
Page through ordersGET /api/v1/commerce/orders/pagecommerce:read
Page through a domain's sent emailGET /api/v1/email-sending/domains/{domain}/activity/pagesites:read
Page through tapsGET /api/v1/cards/tapsreviews:read

Send limit, from 1 to 100 rows (50 when left out), and nothing else new. The answer has the rows and a nextCursor; send it back as cursor for the next page, with the same other parameters, until nextCursor is null.

{
"rows": [{ "id": "ctc_01JD7QJ9M2N4P6R8T0V2X4Z6AB", "firstName": "Maya" }],
"nextCursor": "eyJ2IjoiMDFKRDdRSjlNMk40UDZSOFQwVjJYNFo2QUIifQ",
"total": 1840
}

total is how many rows match in all. The logs (the audit log, email activity and card taps) can’t count cheaply, so their pages have no total.

async function* contacts(apiKey) {
let cursor = null;
do {
const url = new URL("https://digize.com/api/v1/contacts/page");
url.searchParams.set("limit", "100");
if (cursor) url.searchParams.set("cursor", cursor);
const response = await fetch(url, { headers: { "x-api-key": apiKey } });
if (!response.ok) throw new Error(`Digize answered ${response.status}`);
const page = await response.json();
yield* page.rows;
cursor = page.nextCursor;
} while (cursor);
}
for await (const contact of contacts(process.env.DIGIZE_API_KEY)) {
console.log(contact.id);
}

A cursor is opaque: pass it back as it came, and don’t build or change one.