Skip to main content

Query language

ParameterFormWhen omitted in List
filterone expressionno filter
sort-createdAt,nameprimary-key order
limitnon-negative integerengine default
offsetnon-negative integerzero
cursoropaque base64url tokenstart of effective order
countexactly true or falseno count
searchnon-empty UTF-8 textno search

Known parameters occur once. Unknown parameters are ignored. The opt-in WithCompatibilityAliases accepts orderby, top, and skip. cursor and offset cannot be combined.

Filter

expression = or-expression
or = and { "or" and }
and = primary { "and" primary }
primary = comparison | "(" expression ")"
comparison = field operator literal

and binds more tightly than or. Operators and field names are case-sensitive.

KindDefault operators
stringeq, ne, contains, startswith, endswith, in, not in
booleaneq, ne, in, not in
integer, float, time, date, decimaleq, ne, gt, gte, lt, lte, in, not in
UUID/customeq, ne, in, not in

Examples:

name eq 'O''Brien'
active eq true
age gte -18
score lt 1.5e2
createdAt gt '2026-07-16T12:30:00Z'
eventDate eq '2026-07-16'
id in (1, 2, 3)
status not in ('blocked', 'deleted')
deletedAt is null
not active eq true
name startswith 'Ann'

Sorting

sort=-createdAt,name

A leading - means descending. Repeated, unknown, or non-sortable fields are errors. List appends missing primary-key fields as trusted stable tie-breakers. Every effective term uses NULLS LAST in ascending and descending order. See Cursor pagination for forward traversal.

Relationship paths

To-one relationships use slash paths with no surrounding whitespace:

company/country/code eq 'US'
sort=company/name

To-many relationships require lexical quantifiers:

orders/any(o: o/total gt 100)
orders/all(o: o/status eq 'paid')
orders/any(o: o/items/any(i: i/price gte 10))

Predicate paths must start with the declared variable. all is true over an empty collection, while a NULL predicate result does not satisfy all. To-many sorting is not valid.

For normative EBNF and diagnostic positions, see GRAMMAR.md.