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

ParameterWhat it doesDefault
page[size]Maximum number of results on this page, from 1 to 10025
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
  }
}
FieldMeaning
nextPageTokenPass this as page[token] to get the next page. An empty string ("") means there are no more results.
totalSizeThe 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

  1. 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"
  2. Read pagination.nextPageToken. If it's "", you're done.

  3. 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"
  4. 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 ValidationError for 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

ResponseCauseFix
422 ValidationError with errors[].field naming pagepage[size] is outside 1 to 100, or you used an unsupported parameter such as limitUse page[size] with a value from 1 to 100
422 ValidationError naming an unknown query parameterA parameter the endpoint doesn't declareRemove it. V3 rejects unknown parameters instead of ignoring them
422 ValidationError after you changed filters mid-walk, or after a long pauseThe token doesn't match the query or has expiredStart again from the first page without a token
404 ResourceNotFound on a search snapshot pageThe snapshot has expiredMake a new snapshot. See Search

Related pages


Did this page help you?