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.

ParameterTypeDefaultNotes
pageint11-based page number. Page 0 is invalid.
pageSizeint20Items per page. Per-handler caps apply; large values are clamped or rejected with 400.

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

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
}
FieldMeaning
itemsItems on this page in the order the handler returned them.
totalCountTotal matching items across all pages (after filters, before paging).
pageThe page number the server actually served.
pageSizeThe page size the server actually served (may be clamped from your input).

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.