Query syntax
The data plane parses exactly four query parameters. Knowing which ones do not exist saves more time than knowing which do, so start there.
What exists
Section titled “What exists”| Param | Value | Meaning |
|---|---|---|
filter |
URL-encoded JSON object | A Mongo-style filter, $and-ed with the policy filter. |
limit |
non-negative integer | Page size. |
skip |
non-negative integer | Offset. |
expand |
comma-separated field names | Inline related documents for x-ref fields. |
What does not exist
Section titled “What does not exist”There is no sort, no select or fields, no q, and no cursor on the REST list
endpoint. If you need sorting or projection today, reach for
GraphQL — or, for similarity ranking, the
vector search endpoint, whose body does take a fields projection.
filter
Section titled “filter”A raw Mongo-style filter object, URL-encoded:
curl -G "$URL/api/v1/posts" \ -H "authorization: Bearer $TOKEN" \ --data-urlencode 'filter={"published":true,"views":{"$gt":100}}'The engine $and-s your filter with the policy filter for the caller, so a filter can only
ever narrow what you are already allowed to see — never widen it.
Anything that is not a JSON object — an array, a scalar, malformed JSON — returns
400 INVALID_FILTER.
limit and skip
Section titled “limit and skip”curl -G "$URL/api/v1/posts" -H "authorization: Bearer $TOKEN" \ --data-urlencode 'limit=20' --data-urlencode 'skip=40'A negative or non-integer value returns 400 INVALID_PARAM.
Pagination is offset-based only. The public list endpoint returns a bare
{documents: [...]} with no total and no cursor — you paginate by incrementing skip.
The one listing that does return a count is the admin document browser:
{ "documents": [ … ], "total": 128 }Other admin listings (users, audit, function logs and versions, webhook deliveries, storage
files) accept limit/skip (or just limit) and return a plain array under a named key.
expand
Section titled “expand”For fields declared as relations (x-ref in the schema), expand inlines the referenced
document instead of leaving the bare id:
curl -G "$URL/api/v1/posts" -H "authorization: Bearer $TOKEN" \ --data-urlencode 'expand=author,category'Names that are unknown, or that point at a field which is not a relation, are silently
ignored. expand works on both list and single-document reads, and on both the data plane
and the admin document browser.
Expansion still goes through the policy engine for the target collection — you do not get to read a document by expanding into it.
Vector search
Section titled “Vector search”Similarity search is a POST (so that GET /:collection/search still resolves a document
whose id happens to be search), and takes its arguments in the body:
curl -X POST "$URL/api/v1/articles/search" \ -H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \ -d '{"text":"how do policies work","limit":5,"fields":["title","url"]}'| Field | Meaning |
|---|---|
text |
Embedded server-side with the field’s configured provider. Auto-embed backends require this and reject a precomputed vector. |
vector |
A precomputed embedding, when the backend allows it. |
limit |
Number of results. |
filter |
A Mongo-style pre-filter, on top of the policy filter. |
fields |
Inclusion projection. id and _score are always returned. |
field |
Which vector field to search when the collection has several. Defaults to the first configured. |
The endpoint is scoped as read, not write. See the vector search guide.
Writes
Section titled “Writes”PATCH treats a body whose keys begin with $ as raw Mongo update operators and passes it
through; any other body is wrapped in $set for you:
# these two are equivalentcurl -X PATCH "$URL/api/v1/posts/$ID" -H "authorization: Bearer $TOKEN" \ -H 'content-type: application/json' -d '{"title":"New"}'
curl -X PATCH "$URL/api/v1/posts/$ID" -H "authorization: Bearer $TOKEN" \ -H 'content-type: application/json' -d '{"$set":{"title":"New"}}'Operators are validated against the policy: an update that touches a field listed in
immutableFields is rejected, whether it arrived as $set, $inc or $push.
PUT is a full replace and rejects a body containing $ keys with
400 INVALID_BODY.
Both return 204 No Content on success.