Pagination

Pagination

Most list endpoints in the eLabNext API return paginated responses using the Paged<T> envelope. This guide explains how pagination works and how to navigate through result sets.

Response format

All paginated endpoints return a JSON object with the following structure:

{
  "data": [...],
  "recordCount": 10,
  "totalRecords": 150,
  "currentPage": 0,
  "maxRecords": 10,
  "hasNextPage": true
}
FieldTypeDescription
dataarrayThe items for the current page
recordCountintegerNumber of items in the current page
totalRecordsintegerTotal number of items across all pages
currentPageintegerThe current page index (0-based)
maxRecordsintegerMaximum number of items per page
hasNextPagebooleanWhether there are more pages after the current one. Set on the samples endpoints, where it can be used as a loop terminator. Other list endpoints use the totalRecords / maxRecords pattern (see Iterating through all pages).

Query parameters

Use these query parameters to control pagination:

ParameterTypeDefaultDescription
$pageinteger0The page to retrieve (0-based)
$recordsinteger10Number of records per page (maximum 1000)

Example

Retrieve the second page of samples with 25 records per page:

GET /api/v1/samples?$page=1&$records=25

Iterating through all pages

The API supports two iteration patterns. Both are first-class — pick the one that matches the endpoint you're calling.

Using totalRecords and maxRecords (works on every paginated endpoint)

Request page 0, compute the total page count from the response, then request the remaining pages:

totalPages = ceil(totalRecords / maxRecords)

Then request pages 1 through totalPages - 1.

Worked example. Suppose a first request returns totalRecords: 153 and maxRecords: 100:

ceil(153 / 100) = 2

So there are 2 pages total (indices 0 and 1), and you need one more request for page 1.

const first = await fetch('/api/v1/storage?$page=0&$records=100').then(r => r.json());
const totalPages = Math.ceil(first.totalRecords / first.maxRecords);

const allRecords = [...first.data];
for (let page = 1; page < totalPages; page++) {
    const next = await fetch(`/api/v1/storage?$page=${page}&$records=100`).then(r => r.json());
    allRecords.push(...next.data);
}

Because totalPages is known after the first response, the remaining pages can also be fetched in parallel instead of sequentially — significantly faster for large result sets.

Using hasNextPage (samples endpoints)

The samples list endpoints (GET /api/v1/samples and the internal samples-and-series variants) populate hasNextPage, which can be used as a loop terminator:

let page = 0;
while (true) {
    const res = await fetch(`/api/v1/samples?$page=${page}&$records=100`).then(r => r.json());
    // process res.data
    if (!res.hasNextPage) break;
    page++;
}

For all other list endpoints, use the totalRecords / maxRecords pattern above.

Notes

  • The maximum value for $records is 1000. Requests exceeding this limit will be capped at 1000.
  • Pages are 0-based: the first page is $page=0.
  • When no pagination parameters are provided, the API defaults to $page=0 and $records=10.