Skip to content

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.

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.

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.

A raw Mongo-style filter object, URL-encoded:

Terminal window
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.

Terminal window
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.

For fields declared as relations (x-ref in the schema), expand inlines the referenced document instead of leaving the bare id:

Terminal window
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.

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:

Terminal window
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.

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:

Terminal window
# these two are equivalent
curl -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.