Appearance
Filtering
Filter records by field values using bracket notation in query parameters. Filters work with pagination, sorting, relationship expansion, and field selection.
Syntax
?filter[field]=value # Equality (default)
?filter[field.operator]=value # With operatorMultiple filters are combined with AND logic:
?filter[status]=active&filter[age.gte]=18Operators
| Operator | Syntax | Description | Example |
|---|---|---|---|
eq | filter[field]=value | Equal to (default) | filter[status]=active |
neq | filter[field.neq]=value | Not equal to | filter[status.neq]=inactive |
gt | filter[field.gt]=value | Greater than | filter[age.gt]=18 |
gte | filter[field.gte]=value | Greater than or equal | filter[age.gte]=18 |
lt | filter[field.lt]=value | Less than | filter[price.lt]=100 |
lte | filter[field.lte]=value | Less than or equal | filter[price.lte]=100 |
like | filter[field.like]=value | Contains substring (case-sensitive) | filter[name.like]=Ali |
in | filter[field.in]=a,b,c | In list (comma-separated) | filter[status.in]=active,pending |
notIn | filter[field.notIn]=a,b | Not in list (comma-separated) | filter[status.notIn]=archived,void |
between | filter[field.between]=a,b | Inclusive range, exactly two bounds | filter[age.between]=18,65 |
isNull | filter[field.isNull]= | Is null | filter[email.isNull]= |
isNotNull | filter[field.isNotNull]= | Is not null | filter[email.isNotNull]= |
Combining filters with OR
Several filter[...] parameters are combined with AND. To express alternatives, put conditions into numbered OR groups:
filter[or][<group>][field]=value
filter[or][<group>][field.operator]=valueConditions inside one group are AND-ed, the groups are OR-ed with each other, and the whole disjunction is AND-ed with any plain filters outside it.
bash
# region = 'EU' AND ( (status='paid' AND total>=100) OR priority='urgent' )
curl ".../api/v1/acme-corp/sales/orders\
?filter[region]=EU\
&filter[or][0][status]=paid\
&filter[or][0][total.gte]=100\
&filter[or][1][priority]=urgent" \
-H "Authorization: Bearer sk_live_abc123..."Group numbers only separate the groups — they do not rank them, and they need not start at zero or be contiguous.
Malformed groups are refused
filter[or][field]=value (no group number) or a non-numeric group number returns a 400. Ignoring a malformed group would widen the result — you would be handed rows you meant to filter out — so it is refused instead.
Row-level security is never widened by OR
If the workspace uses row-level security, those conditions are applied outside your groups. customer_id = you AND (your alternatives) — an OR in your filter can never reach another user's rows.
Examples
Basic Equality Filter
bash
curl ".../api/v1/acme-corp/sales/customers?filter[name]=Alice" \
-H "Authorization: Bearer sk_live_abc123..."Numeric Range
bash
# Customers aged 18-65
curl ".../api/v1/acme-corp/sales/customers?filter[age.gte]=18&filter[age.lte]=65" \
-H "Authorization: Bearer sk_live_abc123..."Substring Search
bash
# Customers with "smith" in their name
curl ".../api/v1/acme-corp/sales/customers?filter[name.like]=smith" \
-H "Authorization: Bearer sk_live_abc123..."Multiple Values (IN)
bash
# Orders with status "pending" or "processing"
curl ".../api/v1/acme-corp/sales/orders?filter[status.in]=pending,processing" \
-H "Authorization: Bearer sk_live_abc123..."Null Checks
bash
# Customers without an email address
curl ".../api/v1/acme-corp/sales/customers?filter[email.isNull]=" \
-H "Authorization: Bearer sk_live_abc123..."Combining with Other Features
Filters work seamlessly with pagination, sorting, expansion, and field selection:
bash
# Active customers, sorted by name, page 2, with order count
curl ".../api/v1/acme-corp/sales/customers\
?filter[status]=active\
&sort=name,asc\
&page=1&size=10\
&expand=orders\
&fields=id,name,email,orders" \
-H "Authorization: Bearer sk_live_abc123..."Type Conversion
Filter values are automatically converted to match the column type:
| Column Type | Filter Value | Converted To |
|---|---|---|
INTEGER, BIGINT | "42" | 42 (Long/Integer) |
DECIMAL, NUMERIC | "19.99" | 19.99 (BigDecimal) |
BOOLEAN | "true" | true (Boolean) |
VARCHAR, TEXT | "hello" | "hello" (String) |
A value that will not convert matches nothing
A value that cannot be converted to the column's type does not currently return an error. filter[age]=abc on an INTEGER column answers 200 with an empty result set, as though no row matched.
This is a known defect — it should be a 400 — and this page described it as one until it was checked against the running API. A filter that silently matches nothing is easy to mistake for a filter that legitimately found nothing, so validate values before you send them.
Unknown Fields
Filtering by a field that doesn't exist on the entity returns 400 BAD_REQUEST:
json
{
"error": {
"code": "BAD_REQUEST",
"message": "Unknown filter field: 'nonexistent'"
}
}Filterable Fields Whitelist
Workspace admins can restrict which fields are filterable per entity via the API configuration. When a whitelist is set, only the listed fields accept filter queries. Attempting to filter on a non-whitelisted field returns 400 BAD_REQUEST.