Pagination (legacy)

Large lists of resources can be read iteratively through pagination. This allows the systematic consumption of a large number of resources in manageable pages of limited quantity. If the results of a request number above 30, the response will contain 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.

However, other resource types such as collections, accounts, applications, batches, files, jobs, places, users, projects, etc. paginate in a slightly different way, i.e.: 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, so these extra pieces of information should not be relied upon and are considered deprecated.


Query Parameters

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

  • sortOrder - Enum
    Choose the sorting order. Resources are returned in descending order by default, but ascending is also available. To specify a preference, use with a value of DESCENDING or ASCENDING.

  • perPage - Integer
    Choose the page size from a minimum of 1 item to a maximum of 100 items, with 30 items used as a default value.


Getting the Next Page

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

Your application must simply use this URL as-is to request the next page, and should not modify it (beyond purely decoding it if necessary).

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 will only ever contain the URL of the next page.


## Example Request

To retrieve only 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 allows 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;
};

If all that is required is to iterate and perform operations on some list of resources, the stream() or streamPages() methods should be used 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!'));