---
title: "Querying"
description: "Pagination, sorting, filtering and facets across the Minima list endpoints"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.minima.ltd/llms.txt
> Use this file to discover all available pages before exploring further.

# Querying

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

```bash
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:

```json
{
  "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

```bash
?orderBy=publishedAt&order=desc
```

`order` 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:

```bash
?orderBy=attributes.publishedAt&type=Product
```

> **Caution**
>
> Sorting by an attribute requires `type`. Attributes are defined per entity type, so without one there is no schema to resolve the attribute against, and the request errors rather than falling back to a default sort.

The 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.

```json
[{ "field": "price", "op": "lte", "value": 500 }]
```

URL-encoded onto a request:

```bash
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:

```json
[{ "field": "slug", "op": "eq", "value": "letta" }]
```

Prefix with `attributes.` to insist on the attribute:

```json
[{ "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:

- `filters` that is not valid JSON
- `filters` that is a bare object rather than an array
- an operator paired with a value it cannot use, such as `between` with 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.

```bash
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:

```json
[
  {
"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`:

```json
[{ "field": "architecture", "op": "in", "value": ["microservice"] }]
```

Source: https://docs.minima.ltd/developers/querying/index.mdx
