Pagination
List endpoints use cursor-based pagination. Ask for up to limit items; if there are more, we return has_more: true and a next_cursor to continue.
Query parameters
| Param | Default | Max | Meaning |
|---|---|---|---|
| limit | 50 | 100 | Items per page |
| starting_after | . | . | Pass the previous next_cursor value |
Response envelope
{
"object": "list",
"data": [ ... ], // up to 'limit' items
"has_more": true, // false when this is the last page
"next_cursor": "1893", // pass to next request as starting_after
"meta": { "request_id": "b28f..." }
}Full-scan loop
Idiomatic pattern to iterate an entire resource:
async function* listAllContacts(apiKey) {
let cursor;
do {
const params = new URLSearchParams({ limit: '100' });
if (cursor) params.set('starting_after', cursor);
const res = await fetch(
`https://app.staffifyai.com/api/workspace/v1/contacts?${params}`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
const page = await res.json();
for (const item of page.data) yield item;
cursor = page.has_more ? page.next_cursor : null;
} while (cursor);
}
for await (const contact of listAllContacts(process.env.STAFFIFY_KEY)) {
console.log(contact.email);
}Ordering
List endpoints return items ordered by id descending (newest first). This ordering is stable. a contact created between two page fetches will show up as a duplicate on the first page if you re-fetch; use updated_after or created_after filters for incremental sync.