Pagination

Large lists of resources can be read iteratively through pagination. This allows the systematic consumption of many resources in manageable pages of 30 items each. If a request returns more than 30 items, the response contains a Link header pointing to the next page of results.

πŸ“˜

Note

When paginating actions, property histories, Thngs, or products, the parameters shown below can be used to request successive pages of a resource type.

Other resource types (such as collections, accounts, applications, batches, files, jobs, places, users, projects, and so on) paginate slightly differently: a page parameter in the Link header, and an extra x-result-count header.

This is subject to change in the future to align all resource types to paginate in the same manner. Don't rely on these extra pieces of information. Consider them deprecated.


Query Parameters

The following query parameters are available for pagination requests for most resource types.

  • sortOrder - Enum
    Choose the sort order. Resources are returned in descending order by default. To specify a preference, include a value of DESCENDING or ASCENDING.

  • perPage - Integer
    Choose the page size from a minimum of 1 item to a maximum of 100 items. The default page size is 30 items.


Getting the Next Page

The response from a paginated request includes a Link header. This header includes the URL-encoded address indicating where the next page of items can be found, if available.

Your application uses this URL to request the next page. This URL must not be modified (except to be decoded as needed).

An example is shown below:

HTTP/1.1 200 OK
Content-Type: application/json
link: <https%3A%2F%2Fapi.evrythng.com%2Fthngs%3FperPage%3D5%26sortOrder%3DDESCENDING%26nextPageToken%3DU2w3sSntqVrbcCX6MEXraqTq>; rel="next"

πŸ“˜

Note

The Link header only contains the URL of the next page.

Example Request

To retrieve two items per page:

GET /thngs?perPage=2&sortOrder=ASCENDING
Content-Type: application/json
Authorization: $OPERATOR_API_KEY
curl -i -H "Content-Type: application/json" \
  -H "Authorization: $OPERATOR_API_KEY" \
  -X GET 'https://api.evrythng.com/thngs?perPage=2&sortOrder=ASCENDING'
const params = { perPage: 2 };
operator.thng().read({ params })
  .then(console.log);

// Or with param setters
operator.thng().setPerPage(2)
  .read()
  .then(console.log);
Iterator<PVector<Thng>> thngs = apiManager.thngService().iterator()
        .perPage(2)
        .sortOrder(SortOrder.ascending())
        .execute();
while (thngs.hasNext()) {
    PVector<Thng> page = thngs.next();
    for (Thng thng : page) {
        System.out.println("Thng: " + thng);
    }
}
HTTP/1.1 200 OK
Content-Type: application/json
link: <https%3A%2F%2Fapi.evrythng.com%2Fthngs%3FperPage%3D2%26sortOrder%3DASCENDING%26nextPageToken%3DUh6RAddC4DT3bNRKRaARMCfc>; rel="next"

[
  {
    "id": "UE5N4YhHmDxcK4xAdrqpQrbr",
    "createdAt": 1472046970112,
    "updatedAt": 1472046970112,
    "name": "Plug #43789",
    "description": "A smart plug connected to the web",
  }, 
  {
    "id": "Uh6RAddC4DT3bNRKRaARMCfc",
    "createdAt": 1472213813953,
    "updatedAt": 1472213813953,
    "name": "Plug #43790",
    "description": "A smart plug connected to the web",
  }
]

Using JavaScript Iterators

The evrythng.js SDK enables you to iterate through all items in a collection without manually paginating. An example is shown below:

const readAllProducts = async () => {
  const products = [];
  const iterator = app.product().setPerPage(100).pages();

  // Iterate through all pages
  let page;
  while (!(page = await iterator.next()).done) {
    products.push(...page.value);
  }
  
  return products;
};

To iterate and perform operations on a list of resources, use the stream() or streamPages() methods instead:

const deleteProduct = async (product, totalSoFar) => {
  await operator.product(product.id).delete();
  
  console.log(`Deleted product ${totalSoFar}`);
};

// One resource at a time
operator.product().setProject(projectId)
  .stream(deleteProduct);
  .then(() => console.log('Complete!'));

// Or, one page of items at a time
operator.product().setProject(projectId)
  .streamPages((page) => Promise.all(page.map(deleteProduct)))
  .then(() => console.log('Complete!'));