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

# Filtering and pagination

> Query syntax for list endpoints — filters, operators, OR groups, custom fields, sorting

### Discovering what you can filter

Every resource exposes a `/help` endpoint that returns its filterable attributes, the
operators each one accepts, and any enum values. Start there rather than guessing.

```bash theme={null}
curl https://api.zivio.net/api/v4/projects/help \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

### Filters

Filters use `filter[attribute]` syntax. Multiple filters are combined with AND.

```bash theme={null}
# Equality
GET /api/v4/projects?filter[state]=draft

# Multiple values — implicit IN
GET /api/v4/projects?filter[state]=draft,new

# Explicit operator
GET /api/v4/projects?filter[created_at][gte]=2024-01-01

# Range
GET /api/v4/projects?filter[budget][between]=1000000,5000000

# Combined — state AND budget
GET /api/v4/projects?filter[state]=draft&filter[budget][gte]=1000000
```

#### Operators

| Operator            | Meaning                                      | Applies to                              |
| ------------------- | -------------------------------------------- | --------------------------------------- |
| `eq`                | Equals (the default)                         | all types                               |
| `not_eq`            | Not equal                                    | all types                               |
| `in` / `not_in`     | Matches any / none of a comma-separated list | integer, string, money, decimal         |
| `gt` / `gte`        | Greater than / or equal                      | integer, datetime, date, money, decimal |
| `lt` / `lte`        | Less than / or equal                         | integer, datetime, date, money, decimal |
| `between`           | Inclusive range, comma-separated             | integer, datetime, date, money, decimal |
| `like` / `not_like` | Case-insensitive substring                   | string                                  |

<Warning>
  **Money values are in minor currency units.** Use `1000000` for £10,000.00.
</Warning>

<Tip>
  `like` is a case-insensitive substring match — pass the bare term
  (`filter[title][like]=redesign`). Do not add `%` wildcards; they are not needed.
</Tip>

### OR groups

Use `or[group]` to combine conditions with OR. Filters inside a group are ANDed; the groups
themselves are ORed. Group keys are arbitrary as long as they are unique.

```bash theme={null}
# state is draft OR pending
GET /api/v4/projects?or[1][state]=draft&or[2][state]=pending

# (state=pending AND budget>=50000) OR state=closed
GET /api/v4/projects?or[1][state]=pending&or[1][budget][gte]=50000&or[2][state]=closed
```

### Custom fields

Custom fields are filtered with `cf[key]`, and support existence checks alongside the usual
operators.

```bash theme={null}
cf[priority]=high                 # exact match
cf[department][in]=eng,design     # matches any
cf[priority][not_eq]=low          # not equal
cf[notes][contains]=urgent        # contains text
cf[legacy_field][exists]=         # field is present (value ignored)
cf[deprecated][not_exists]=       # field is absent
```

Custom fields work inside OR groups too: `or[1][cf][priority]=high&or[2][state]=pending`.

### Sorting

```bash theme={null}
GET /api/v4/projects?sort[created_at]=desc   # descending
GET /api/v4/projects?sort[title]=            # ascending (empty value)
```

The sortable attributes for each resource are listed by its `/help` endpoint.

### Pagination

<ParamField query="page" type="integer" default="1">
  Page number, 1-indexed.
</ParamField>

<ParamField query="limit" type="integer" default="20">
  Results per page. Maximum 100.
</ParamField>

```bash theme={null}
GET /api/v4/projects?page=2&limit=50
```

### A worked example

Draft or pending projects over £10,000, newest first:

```bash theme={null}
curl -G https://api.zivio.net/api/v4/projects \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  --data-urlencode "or[1][state]=draft" \
  --data-urlencode "or[2][state]=pending" \
  --data-urlencode "filter[budget][gte]=1000000" \
  --data-urlencode "sort[created_at]=desc" \
  --data-urlencode "limit=50"
```
