How To Search With Filters, Sorting, And Pagination
When making GET requests to search resources, you can use query parameters to filter, sort, and paginate the results.
Filtering
You can filter search results using the filter query parameter object.
Give it the key from the resource type you're filtering, and the value you want to compare to.
You can filter contacts with a key equal to a value.
GET "/contacts?filter[key]=value"
Depending on the value's type, you can also provide a comparison.
GET "/contacts/filter[created_at][gt]=2026-01-01"
Filter Comparisons
Filters can take one of three formats
1. Explicit Comparison
An explicit comparison is the most verbose way to write out a filter
filter[key][comparison]=value
e.g.
# Search for contacts that were adedd after 2025-01-01
GET "/contacts?filter[addedAt][gt]=2025-01-01"
# Search for contacts that have an email equal to "email@example.com"
GET "/contacts?filter[email][eq]=email@example.com"
2. Implied Equals
An eq comparison is implied when no comparison is provided
filter[key]=value
# Search for contacts that have an email equal to "email@example.com"
GET "/contacts?filter[email]=email@example.com"
3. Implied true
When no = is provided, it implies that the value is true.
This is mostly useful when paired with the exists comparison, but also works well with a key that is a boolean.
# Search for tasks that are repeating
GET "/tasks?filter[isRepeating]"
# Search for contacts that have an email
GET "/contacts?filter[email][exists]"
# Search for contacts that don't have an email
GET "/contacts?filter[email][exists]=false"
Combining Filters
Unique filters are combined with an AND operator.
# Search for contacts added after 2025-01-01 that have an email
GET "/contacts?filter[addedAt][gt]=2025-01-01&filter[email][exists]"
However, multiple values for the same filter key are combined with an OR operator.
Filtering With Lists Of Values
The standard way to filter on multiple values is to simply add the filter again. Each additional filter will be considered an OR comparison.
You can also do a comma separated list if you want to.
# Search for contacts that have the first name "Bob" or "John"
GET "/contacts?filter[firstName]=Bob&filter[firstName]=John"
A more explicit way to show that you are using a is to append [] after the filter.
# Search for contacts that have the first name "Bob" or "John"
GET "/contacts?filter[firstName][]=Bob&filter[firstName][]=John"
Filter Comparisons
| Comparison | Single | Multiple | Usage | Description |
|---|---|---|---|---|
eq | ✅ | ✅ | filter[key][eq]=value or filter[key]=value | resource's key is equal to value |
neq | ✅ | ✅ | filter[key][neq]=value | resource's key is not equal to value |
lt | ✅ | ❌ | filter[key][lt]=value | resource's key is less than the value |
lte | ✅ | ❌ | filter[key][lte]=value | resource's key is less than or equal to value |
gt | ✅ | ❌ | filter[key][gt]=value | resource's key is greater than value |
gte | ✅ | ❌ | filter[key][gte]=value | resource's key is greater than or equal to value |
exists | ✅ | ❌ | filter[key][exists]=true or filter[key][exists] | resource's key exists |
like | ✅ | ✅ | filter[key][like]=value | resource's key (text) is similar to value |
Data Types
| Type | Available Comparisons |
|---|---|
| Date | eq, neq, exists, lt, lte, gt, gte |
| Text | eq, neq, exists, like |
| Number | eq, neq, exists, lt, lte, gt, gte |
| Object | eq, neq, exists |
Sorting Search Results
You can sort search results using the sort query parameter.
You can sort on multiple keys by separating them with a comma. Providing the sort[] parameter multiple times is also supported, but not preferred.
Provide your keys in priority order. You can also think of the sorts as being executed right-to-left.
By default, sorting is ascending. You can switch it to descending order by prefixing it with a -.
# Sort contacts by last name ascending, then first name ascending
GET "/contacts?sort=lastName,firstName" # PREFERRED
GET "/contacts?sort[]=lastName&sort[]=firstName" # Also supported
# Sort contacts in descending creation datetime, if contacts were created at the same time, sort those by ascending last name.
GET "/contacts?sort=-createdAt,lastName"
Paginating Search Results
You can paginate search results using the page query parameter object.
It has two keys:
| Key | Description |
|---|---|
size | Number of results to return |
cursor | Pagination cursor for next page |
If a search endpoint has more results than the provided size
interface PageParams {
size?: number; // Number of results to return
cursor?: string; // Pagination cursor for next page
}
interface SuccessfulSearchResponse<T> {
data: T[]; // Array of results
meta: {
total: number; // Total number of results
[key: string]: any; // Additional metadata
};
links: {
self: string; // URL that was just requested
next?: string; // If there are more results, URL for the next page
};
}
let all_contacts = [];
let next_page_url = '/contacts?page[size]=10';
do {
let {
data: page_of_contacts,
meta,
links,
error
} = await fetch(next_page_url).then(res => res.json());
if (error){
// handle error
return;
}
all_contacts.push(...page_of_contacts);
next_page_url = links.next;
} while (next_page_url);