Pagination
Page through any Wingspan V3 list with page[size] and page[token], and stop when nextPageToken is an empty string.
Read every result from a Wingspan V3 list endpoint by requesting pages until nextPageToken is an empty string. Every list uses the same parameters and response shape.
Parameters
| Parameter | What it does | Default |
|---|---|---|
page[size] | Maximum number of results on this page, from 1 to 100 | 25 |
page[token] | The nextPageToken from the previous page. Leave it out for the first page. | none |
The brackets are part of the parameter name. Send ?page[size]=50, not ?pageSize=50 or ?limit=50. When you build the URL with curl, pass -g so curl doesn't treat the brackets as a pattern, or URL-encode them (page%5Bsize%5D=50).
Audit logs allow at most 25 per page. A few platform lists accept larger values but may return fewer rows; always follow nextPageToken.
Response
Every list response has a data array and a pagination object. This is a trimmed response:
{
"data": [
{ "id": "Rw5Nc2Hk8LqZ4tVp9XmBsa", "status": "Activated" },
{ "id": "e8GtY3pLq6Wz1KxN4vRcMd", "status": "Activated" }
],
"pagination": {
"nextPageToken": "eyJrIjpbIjIwMjYtMDQtMDFUMTQ6MDI6MTFaIl19",
"totalSize": 1042
}
}| Field | Meaning |
|---|---|
nextPageToken | Pass this as page[token] to get the next page. An empty string ("") means there are no more results. |
totalSize | The number of matching results, when the endpoint can count them. It may be missing on endpoints where counting is expensive. |
An empty nextPageToken is the only end-of-list signal. Don't stop because a page came back with fewer than page[size] results, and don't stop because data is empty. Keep going until nextPageToken is "".
Read every page
-
Request the first page with your filters and page size:
curl -g "https://api.wingspan.app/v3/payments/payees?page[size]=100&filter[status][eq]=Activated" \ -H "Authorization: Bearer $WINGSPAN_TOKEN" -
Read
pagination.nextPageToken. If it's"", you're done. -
Otherwise, repeat the same request with the token added. Keep every other parameter the same:
curl -g "https://api.wingspan.app/v3/payments/payees?page[size]=100&filter[status][eq]=Activated&page[token]=eyJrIjpbIjIwMjYtMDQtMDFUMTQ6MDI6MTFaIl19" \ -H "Authorization: Bearer $WINGSPAN_TOKEN" -
Go back to step 2.
Here is the same loop in JavaScript:
async function listAll(path, params = {}) {
const results = [];
let token = "";
do {
const query = new URLSearchParams({ ...params, "page[size]": "100" });
if (token) query.set("page[token]", token);
const res = await fetch(`https://api.wingspan.app${path}?${query}`, {
headers: { Authorization: `Bearer ${process.env.WINGSPAN_TOKEN}` },
});
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
const body = await res.json();
results.push(...body.data);
token = body.pagination.nextPageToken;
} while (token !== "");
return results;
}
const payees = await listAll("/v3/payments/payees", { "filter[status][eq]": "Activated" });Rules for page tokens
- Treat tokens as opaque. Don't decode them, build them, or store data in them. Their format can change at any time.
- Reuse a token only with the same query. A token belongs to the filter and sort that produced it. If you change a filter or the sort, start again from the first page without a token. Most lists return
422 ValidationErrorfor a token that doesn't match the query or has expired. A few platform lists, such as Accounts and Persons, don't return an error: they start again from the first page or carry on under the new filters. Don't rely on an error to tell you a token is stale. - Don't store tokens for later. Tokens expire. Use them to walk a list now, not to resume days later. If you need to pick up where you left off over time, filter on a timestamp such as
filter[createdAt][gte]where the endpoint supports it. - Expect change between pages. Pages read live data. A record created or updated while you page may appear on a later page or not at all. If you need a complete, current set, finish the walk and then reconcile using webhooks or a second pass.
Search endpoints under /v3/search use the same parameters, but their tokens and counts behave a little differently. They also accept page[mode]=materialized, which freezes the results into a snapshot you page through with page[resultSetId]. See Search.
What can go wrong
| Response | Cause | Fix |
|---|---|---|
422 ValidationError with errors[].field naming page | page[size] is outside 1 to 100, or you used an unsupported parameter such as limit | Use page[size] with a value from 1 to 100 |
422 ValidationError naming an unknown query parameter | A parameter the endpoint doesn't declare | Remove it. V3 rejects unknown parameters instead of ignoring them |
422 ValidationError after you changed filters mid-walk, or after a long pause | The token doesn't match the query or has expired | Start again from the first page without a token |
404 ResourceNotFound on a search snapshot page | The snapshot has expired | Make a new snapshot. See Search |
Related pages
Updated 10 days ago