Every list endpoint takes the same shape of query string: a page window, a sort, and filters. This page covers the parameters they share. The examples use the Public API; the same parameters work on the Admin API’s list operations.
Pagination
curl "https://api.minima.ltd/api/v1/public/sites/site_abc123/entities?limit=50&offset=100" \
-H "x-api-key: pub_your_key_here"| Parameter | Default | Notes |
|---|---|---|
limit |
20 |
How many records to return |
offset |
0 |
How many to skip |
List responses carry the window back to you alongside the data:
{
"data": [...],
"pagination": {
"total": 412,
"limit": 50,
"offset": 100,
"page": 3,
"totalPages": 9
}
}total is the count before the window is applied, so it is what you page against. page and totalPages are derived from it for convenience.
Sorting
?orderBy=publishedAt&order=descorder is asc or desc.
orderBy needs more care, because entities have both fixed fields and your own attributes, and the two share a namespace.
A bare key resolves an entity field first — id, name, publishedAt, slug — and only falls through to an attribute of the same name if no entity field matches. So if your entity type defines an attribute called publishedAt, orderBy=publishedAt sorts by the built-in field, not yours.
To name an attribute explicitly, prefix it:
?orderBy=attributes.publishedAt&type=ProductThe prefix does not fall back. attributes.name names the attribute name and nothing else — if the type declares no such attribute the request errors, even though name is a real entity field.
Filtering
filters takes a JSON-encoded array. Each filter names a field, an operator, and a value.
[{ "field": "price", "op": "lte", "value": 500 }]URL-encoded onto a request:
curl -G "https://api.minima.ltd/api/v1/public/sites/site_abc123/entities" \
--data-urlencode 'type=Product' \
--data-urlencode 'filters=[{"field":"price","op":"lte","value":500}]' \
-H "x-api-key: pub_your_key_here"| Operator | Value shape | Matches |
|---|---|---|
eq |
string, number, boolean | Exact match |
contains |
string | Substring match |
in |
array of strings or numbers | Any of the listed values |
gte |
string or number | Greater than or equal |
lte |
string or number | Less than or equal |
between |
two-element array | Inclusive range |
Filters combine with AND. Pass several and a record must satisfy all of them.
The parameter is named filters, and it carries the whole array as one JSON value. It is not a repeated parameter.
Which field a filter names
A bare key resolves a first-class entity field or one of your attributes, whichever matches — slug, category and price all work as written:
[{ "field": "slug", "op": "eq", "value": "letta" }]Prefix with attributes. to insist on the attribute:
[{ "field": "attributes.openSource", "op": "eq", "value": true }]Use the prefix when an attribute shares a name with a built-in field, which is the same shadowing rule orderBy follows above.
Filters fail loudly
A filter the API cannot honour returns 400. It is never dropped silently, so a filtered list is either filtered the way you asked or an error:
filtersthat is not valid JSONfiltersthat is a bare object rather than an array- an operator paired with a value it cannot use, such as
betweenwith a one-element array
Simple filters
Several common filters have their own parameters rather than needing filters:
| Parameter | Endpoint | Effect |
|---|---|---|
type |
Entities | Restrict to one entity type |
query |
Entities | Case-insensitive search on name, including partial matches |
slug |
Entities, Articles | Fetch by slug |
category |
Entities, Articles | Restrict to a category |
hasPermalink |
Entities | Require a canonical permalink on this site |
tag |
Articles | Restrict to a tag. Prefix with - to exclude, e.g. tag=-sponsored |
author |
Articles | Restrict to an author slug |
hasHeroImage |
Articles | true or false |
Facets
Facets count how many records fall under each value of an attribute. They are what you build a directory’s filter sidebar from — “Brand (12), Category (8)” — without fetching every record to count them yourself.
curl "https://api.minima.ltd/api/v1/public/sites/site_abc123/entity-types/ret_abc123/facets?keys=brand,material" \
-H "x-api-key: pub_your_key_here"keys is a comma-separated list of attribute keys. Omit it to get every facetable attribute on the type. The id in the path is the registry entity type ID, not the type’s name.
The response is an array, one entry per facet, each carrying its options already counted:
[
{
"type": "options",
"key": "architecture",
"label": "Architecture",
"source": "attribute",
"options": [
{ "label": "Microservice", "value": "microservice", "count": 1 },
{ "label": "Monolith", "value": "monolith", "count": 2 }
]
},
{
"type": "options",
"key": "openSource",
"label": "Open source",
"source": "attribute",
"options": [
{ "label": "Yes", "value": "true", "count": 1 },
{ "label": "No", "value": "false", "count": 1 }
]
}
]label is what you render, value is what you send back. Booleans come through as the strings "true" and "false", with Yes/No labels.
Take the option a reader picks and feed its value back through filters under the facet’s key:
[{ "field": "architecture", "op": "in", "value": ["microservice"] }]