Skip to content

Pagination

Every list endpoint accepts the same two query parameters and returns the same response envelope. Once you’ve integrated one list, you’ve integrated them all.

Parameter Type Default Notes
page int 1 1-based page number. A value below 1 is served as 1.
pageSize int 20 Items per page, at most 500. Above 500 is served as 500; below 1 is served as the endpoint’s default.

A handful of read-heavy endpoints have a different default pageSize, and a few cap lower than 500. The Live API explorer is the source of truth for any specific operation’s defaults — open the operation, look at the query-parameter description.

Both parameters are clamped before the handler runs, on every list endpoint, so the page and pageSize in the response envelope are always the values actually served. Send pageSize=999999 and you get 500 back, with "pageSize": 500 in the body; walk pages using that echoed value rather than the one you sent.

A value that is not a number at all (page=abc, or page= with nothing after it) is a 400 of type errors/bad-request whose detail names the parameter — see Errors.

Every paginated response wraps Items in a PaginatedResult<T>:

{
"items": [
{ "id": 1, "firstName": "Jane", "lastName": "Donor" },
{ "id": 2, "firstName": "Sam", "lastName": "Smith" }
],
"totalCount": 1834,
"page": 1,
"pageSize": 20
}
Field Meaning
items Items on this page in the order the handler returned them.
totalCount Total matching items across all pages (after filters, before paging).
page The page number the server actually served.
pageSize The page size the server actually served — clamped from your input when it was above 500 or below 1.

Compute totalPages = ceil(totalCount / pageSize) and iterate. Don’t rely on an empty items array as the stop signal — request the page you expect to exist and check the count.

Terminal window
PAGE=1
while :; do
body=$(curl -sS \
-H "X-Api-Key: $AURA_API_KEY" \
"https://api.auradonors.com/api/tenants/$TENANT_ID/contacts?page=$PAGE&pageSize=100")
echo "$body" | jq -r '.items[].id'
total=$(echo "$body" | jq '.totalCount')
size=$(echo "$body" | jq '.pageSize')
pages=$(( (total + size - 1) / size ))
[ "$PAGE" -ge "$pages" ] && break
PAGE=$((PAGE + 1))
done

For a typed client:

public record PaginatedResult<T>(List<T> Items, int TotalCount, int Page, int PageSize);
async IAsyncEnumerable<ContactListItem> WalkContactsAsync(HttpClient http, Guid tenantId)
{
var page = 1;
while (true)
{
var url = $"/api/tenants/{tenantId}/contacts?page={page}&pageSize=100";
var result = await http.GetFromJsonAsync<PaginatedResult<ContactListItem>>(url);
if (result is null) yield break;
foreach (var item in result.Items)
yield return item;
var totalPages = (int)Math.Ceiling((double)result.TotalCount / result.PageSize);
if (page >= totalPages) yield break;
page++;
}
}
Terminal window
curl -sS \
-H "X-Api-Key: $AURA_API_KEY" \
"https://api.auradonors.com/api/tenants/$TENANT_ID/contacts?page=2&pageSize=50"

Returns the second page of 50 contacts. The same shape applies whether you’re paging contacts, donations, orders, payments, audit logs, shipments, or any other list endpoint.

Each list endpoint declares its own ordering (most use newest-first by CreatedAt). The order is stable for a given filter set as long as the underlying data doesn’t change between requests. If you need a fully consistent snapshot across pages, page through quickly — the platform does not provide cursor or snapshot semantics today.

  • No cursor pagination. All endpoints are offset-based. A future v2 may introduce cursors for high-volume reads if real integrations need them.
  • No Link header / RFC 5988 navigation. Compute next/prev from totalCount, page, and pageSize.
  • No “page = 0 returns everything” escape hatch. If you need every row, walk every page.