Queries
The query language over HTTP: where, order, limits, cursors.
The shape of a query
GET /v1/projects/{project}/collections/{collection}/records
?where=[["status","==","open"],["priority",">",2]]
&orderBy=created_at&direction=desc
&limit=50
&cursor=…
where is a JSON array of [field, operator, value] triples, combined with AND.
Operators
| Operator | Meaning |
|---|---|
==, != | Equality. |
>, >=, <, <= | Ordering — numeric for number, chronological for datetime. |
contains | Substring match on text. |
in | Value is one of a list. |
Only fields in the collection's schema can be filtered or sorted, and only these operators are
accepted. Values are always bound, never interpolated — the query language is not a SQL
passthrough and cannot be made into one.
Paging
A response carries records and, when more exist, a cursor. Pass it back
as ?cursor=… for the next page. Cursors are stable under inserts, so paging does not
skip or repeat rows the way an offset does.
let cursor = null;
do {
const url = new URL(base + '/collections/tasks/records');
url.searchParams.set('limit', '100');
if (cursor) { url.searchParams.set('cursor', cursor); }
const page = await fetch(url, { headers }).then(r => r.json());
handle(page.records);
cursor = page.cursor ?? null;
} while (cursor);
Rules still apply
A query returns only records the caller may read. Filtering happens after the rule, not instead of it — an unauthorised record is absent, never merely hidden client-side. Security rules →