API reference
Pagination, filtering and search
How list endpoints page, sort and filter, and how the search endpoints differ.
List responses
List endpoints return a data array and a page object.
{
"data": [{ "id": "01J...", "name": "Spring sale" }],
"page": { "page": 1, "page_size": 50, "total": 137 }
}
| Query parameter | Default | Notes |
|---|---|---|
page | 1 | Positive integer. |
page_size | 50 | 1 to 500; larger values are clamped to 500. |
sort | endpoint default | Comma list of field names; prefix - for descending, e.g. sort=-created_at,name. |
q | none | Free-text search over the entity's text fields. |
filter[field]=value | none | Equality. Shorthand for filter[field][eq]=value. |
filter[field][op]=value | none | See operators below. |
Reports, logs and some activity endpoints use a keyset next_cursor in page instead of page numbers, because they sit on top of ClickHouse: pass it back as cursor in the request body. Those endpoints are marked in the reports and logs references.
Filter operators
| Operator | Meaning |
|---|---|
eq, ne | Equal, not equal. |
gt, gte, lt, lte | Comparisons on numbers and timestamps. |
in, nin | Value is (not) in a comma-separated list: filter[status][in]=active,paused. |
contains, starts | Case-insensitive substring and prefix on text. |
empty | Field is null or blank. |
between | Two comma-separated values, inclusive. |
Filtering on an unknown field or operator returns 400 validation_failed with a details entry such as filter[foo]: unknown or unfilterable field. JSON columns (custom_fields) are not filterable through the query string.
Search endpoints
Most collections also expose POST /{resource}/search for filters that do not fit in a URL. The body is a SearchRequest:
{
"search": "spring",
"filters": [
{ "field": "status", "op": "in", "value": ["active", "paused"] },
{ "field": "created_at", "op": "gte", "value": "2026-01-01T00:00:00Z" }
],
"page": 1,
"page_size": 100
}
The response has the same data and page shape as a list.
Soft deletes and versions
Deleting an entity marks it deleted and hides it from lists; every change is recorded in the audit log and bumps the read-only version field. Updates use PATCH with only the fields you change.