Pagination and querying

Open in the interactive reference

In practice: request pages with page[size], send each response's pagination.nextCursor back as page[cursor], and stop when a response carries no nextCursor. The rest of this section is the detail behind that loop, and the query grammar every collection shares.

Paging through a collection

Collections return their records a page at a time: 25 by default, and at most 100. A larger size is served as 100; zero, a negative number or anything other than a whole number is refused with 400.

Each response reports pagination.hasMore and, when there is a next page to fetch, pagination.nextCursor.

The cursor is opaque: do not parse or construct one. It belongs to the filters and sort of the request that returned it, and is refused with 400 if they change. page[size] and fields can change from page to page.

A walk through a collection ends after about 100,000 records: from there on, a response carries no nextCursor even though hasMore is still true. To read further, narrow the query with a filter.

A page is a position in the result. When records are created or deleted during a walk, later pages shift, and a record can be skipped or returned twice. Without sort, the order itself is not guaranteed, so always sort on a field that orders records uniquely, such as id, and make your processing tolerate a record it has already seen.

Paging through a search

Search endpoints page the same way, in the request body: send page.size and page.cursor, and read data.pagination.hasMore and data.pagination.nextCursor. Each search endpoint states its default and largest page size, and what happens to a larger one.

Filtering, sorting and selecting fields

A collection takes filters, a sort order and a field selection in the query string. Its endpoint lists which fields support which filters, and which can be sorted. A filter or sort on any other field is refused with 400, never ignored.

Filters combine with AND: a record is returned only if it matches every filter. Each parameter can appear once; repeating one, such as sort or the same filter, is refused with 400.

Exact Match a value, or everything except it. filter[field]=value filter[field][ne]=value
Range Bound it from above, below, or both. gte and lte include the bound, gt and lt exclude it; between takes exactly two values and includes both. filter[field][gte]=value filter[field][lte]=value filter[field][gt]=value filter[field][lt]=value filter[field][between]=a,b
Any of Match any value in a list, or none of them. Up to 100 values. filter[field][in]=a,b,c filter[field][notIn]=a,b,c
Pattern Match text against a case-sensitive pattern: % stands for any characters, _ for exactly one. %25 is the URL spelling of %; where a client encodes parameters for you, pass % itself. filter[field][like]=%25part%25 filter[field][like]=part%25
Sort Applied in the order given; a leading - sorts descending. sort=field,-otherField
Trim Return only these fields. The rest are omitted, not null. fields=a,b,c
Page Up to 100 records per page, 25 unless asked. Pass back pagination.nextCursor for as long as a response carries one. page[size]=25&page[cursor]=…

A like pattern works on text fields only and is case-sensitive: % matches any sequence of characters and _ matches exactly one. In a URL, % is written %25, so %25part%25 finds values containing “part” and part%25 values starting with it. A pattern with neither must match the whole field.

The values of in, notIn and between are comma-separated in one parameter, so a value cannot itself contain a comma. in and notIn take up to 100 values, and between exactly two.

URL-encode every value you put in the query string yourself: a literal + as %2B, or it arrives as a space, and a % in a pattern as %25. Where your client encodes parameters for you, pass the characters themselves and let it encode them; encoding twice sends %2525, which matches nothing. The brackets in parameter names can be sent as they are; with curl, pass -g so that it does not treat them as a pattern.

On a collection's endpoint, the chips beside each field show what it supports; hover over one to see its parameter names.

Examples

Reading every page, in Python

params = {"page[size]": 100}
while True:
    body = requests.get(url, params=params, headers=headers).json()
    handle(body["data"])
    cursor = body["pagination"].get("nextCursor")
    if cursor is None:
        break
    params["page[cursor]"] = cursor

A page of a collection

{
  "data": [
    "…"
  ],
  "pagination": {
    "hasMore": true,
    "nextCursor": "…"
  }
}