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

# Filtering (SFS-1)

> Filter list results with SFS-1 expressions — the mental model and common patterns.

Every list endpoint accepts a `filter` query parameter using **SFS-1 (Soluts Filter Syntax v1)** — a lightweight, predictable filter language. This page covers the mental model and common patterns; the [Filtering reference](/api-reference/conventions/filtering) is the full normative contract.

## The mental model

A filter is a list of **comparisons** joined by `AND` (or `;` as shorthand):

```
status=SUCCESS AND createdAt>=2026-01-01
```

Each comparison has three parts: a `field`, an `operator`, and a `literal`. The server validates everything against the endpoint's schema before executing the query.

That is the whole language. There is no `OR`, no parentheses, no functions, no wildcards — and that is deliberate. SFS-1 prioritizes **predictability** over expressiveness.

## Operators

| Operator          | Allowed on                  |
| ----------------- | --------------------------- |
| `=` `!=`          | All types                   |
| `<` `<=` `>` `>=` | Numbers and timestamps only |

For strings, booleans, and enums, you can only check equality. This keeps query performance bounded and prevents accidental full-text scans.

## Common patterns

### Equality

```
status=SUCCESS
```

Most filters are equality checks. They are also the fastest — these always hit an index.

### Range

```
createdAt>=2026-01-01 AND createdAt<2026-02-01
```

Date and amount ranges are the second-most-common filter. The half-open form (`>=` start, `<` end) is the canonical way to express "all items in January" without overlap.

### Multiple criteria

```
status=SUCCESS;direction=IN;createdAt>=2026-01-01
```

`;` is shorthand for `AND` — both are equivalent. Whitespace is optional but improves readability.

### Enum filtering

```
direction=IN
network=br.gov.bcb.pix
status=AWAITING_APPROVAL
```

Enum values are **case-sensitive**. `direction=in` will fail with `INVALID_FILTER`.

## What you cannot do (and why)

| You might want                    | Why SFS-1 rejects it     | What to do instead                                                     |
| --------------------------------- | ------------------------ | ---------------------------------------------------------------------- |
| `status=SUCCESS OR status=FAILED` | No `OR` in v1.           | Issue two filtered queries and merge client-side.                      |
| `name LIKE 'prod-*'`              | No wildcards.            | Use exact `name=` if you know the value; design for known identifiers. |
| `NOT status=SUCCESS`              | No negation.             | Use `status!=SUCCESS` (yes, that one works — it is `!=`, not `NOT`).   |
| `(a=1 AND b=2) OR (c=3)`          | No parentheses, no `OR`. | Two queries client-side.                                               |
| `tags has "vip"`                  | No collection operators. | Filter the field that exists on the resource.                          |

The design rationale: filters should be **cheap to plan, fast to execute, predictable to non-technical users**. Complex boolean algebra defeats those goals.

## Which fields can you filter on?

Filterable fields are **explicitly allowlisted by each endpoint**. Each endpoint's reference page lists its filterable fields.

| Endpoint                              | Common filterable fields                            |
| ------------------------------------- | --------------------------------------------------- |
| `GET /wallets`                        | `id`, `status`, `name`, `createdAt`                 |
| `GET /wallets/{wallet}/paymentOrders` | `id`, `direction`, `status`, `network`, `createdAt` |

Trying to filter on a field not in the allowlist returns `INVALID_FILTER`.

## Literal forms

| Form                 | Example                               |
| -------------------- | ------------------------------------- |
| Unquoted identifier  | `ACTIVE`, `SUCCESS`, `br.gov.bcb.pix` |
| Double-quoted string | `"John Doe"`, `"ACME \"Corp\""`       |
| Single-quoted string | `'John Doe'`                          |
| Integer              | `42`                                  |
| Float                | `3.14`, `2.997e9`                     |
| Boolean              | `true`, `false`                       |
| Null                 | `null`                                |
| Timestamp (RFC 3339) | `"2026-01-15T00:00:00Z"`              |

For values that contain spaces, dots, dashes that look like operators, or any non-identifier characters, quote them.

## URL encoding

The `filter` value lives in the URL. Spaces, `>`, `<`, `=` must be encoded per RFC 3986:

```
filter=status%20%3D%20SUCCESS%20AND%20amount%20%3E%3D%2010000
```

Most HTTP clients encode automatically. Hand-built URLs must encode explicitly — see the [Filtering reference](/api-reference/conventions/filtering) for the full table.

## Filtering and pagination interact

When you paginate (`page_token`), the `filter` you used on the first call **must stay identical** for every subsequent page. Changing it returns `INVALID_PAGE_TOKEN`. This is intentional — pagination tokens are bound to the filter context.

## Reference

<Card title="Filtering (SFS-1) — full reference contract" icon="filter" href="/api-reference/conventions/filtering" horizontal>
  Operators, literals, validation, formal grammar.
</Card>
