# Filter

Keep records whose JSONPath value matches a predicate.

## When to use it

Keep records matching the selected predicate at a JSONPath. Check how the predicate handles missing fields and mixed value types. A filter that returns no rows can be functioning correctly; inspect representative input before loosening it.

## Add and configure

1. Add **Filter** from the workflow step picker.
2. Give the step a recognisable name and connect its required inputs.
3. Set the options below. Nested names identify fields within an object or a list item.
4. Validate the recipe, inspect the test result, then run it on the intended data.

The step identifier used in the editor’s code view is `filter`.

## Settings

| Setting | Accepted value | Required | Default | What it controls |
| --- | --- | --- | --- | --- |
| Op (`op`) | "eq" / "ne" / "contains" / "exists" / "in" | No | "exists" | Comparison operation. |
| Path (`path`) | string | Yes | Not specified | JSONPath into each record (e.g. `$.status`). |
| Value (`value`) | value or null | No | null | Comparison value (ignored for 'exists'). |

## Inputs and outputs

| Direction | Port | Content | Required | Multiple records |
| --- | --- | --- | --- | --- |
| Inputs | `in` | records | Yes | Yes |
| Outputs | `out` | records | Yes | Yes |

## Effects, testing, and recovery

Transforms or passes records without a declared external side effect.

The declared preview behaviour is to execute this step. Reads, processing, or model usage can therefore be real. Read [dry runs](/docs/workflows/dry-runs) before using a preview with live connections.

No duplicate-prevention key is declared for this step. The step declares safe replay for its supported recovery path.

## Example: Keep open tickets

Step settings:

```json
{
  "op": "eq",
  "path": "$.status",
  "value": "open"
}
```

Input records:

```json
[
  {
    "id": 1,
    "status": "open"
  },
  {
    "id": 2,
    "status": "closed"
  }
]
```

Expected output for this example:

```json
[
  {
    "id": 1,
    "status": "open"
  }
]
```

## Example: Keep records that carry an email

Step settings:

```json
{
  "op": "exists",
  "path": "$.email"
}
```

Input records:

```json
[
  {
    "email": "ada@example.com"
  },
  {
    "name": "no email"
  }
]
```

Expected output for this example:

```json
[
  {
    "email": "ada@example.com"
  }
]
```

## Example: Keep records whose region is in a set

Step settings:

```json
{
  "op": "in",
  "path": "$.region",
  "value": [
    "eu",
    "uk"
  ]
}
```

Input records:

```json
[
  {
    "region": "eu"
  },
  {
    "region": "us"
  },
  {
    "region": "uk"
  }
]
```

Expected output for this example:

```json
[
  {
    "region": "eu"
  },
  {
    "region": "uk"
  }
]
```

## Check the result

Inspect the selected run’s status, counts, errors, and output records. An empty collection can be a valid result, and a completed step can contain per-record failures where the step defines that behaviour. Check the next step’s expected record shape before publishing or delivering the result.
