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": "…"
}
}