Skip to main content

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​

ComparisonSingleMultipleUsageDescription
eq✅✅filter[key][eq]=value or filter[key]=valueresource's key is equal to value
neq✅✅filter[key][neq]=valueresource's key is not equal to value
lt✅❌filter[key][lt]=valueresource's key is less than the value
lte✅❌filter[key][lte]=valueresource's key is less than or equal to value
gt✅❌filter[key][gt]=valueresource's key is greater than value
gte✅❌filter[key][gte]=valueresource'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]=valueresource's key (text) is similar to value

Data Types​

TypeAvailable Comparisons
Dateeq, neq, exists, lt, lte, gt, gte
Texteq, neq, exists, like
Numbereq, neq, exists, lt, lte, gt, gte
Objecteq, 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:

KeyDescription
sizeNumber of results to return
cursorPagination 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);