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

# Rules

> Rulesets and rules: skip, recategorise or rename transactions before they reach a destination

A **ruleset** is a named, reusable list of up to 20 **rules**; a sync has at most one ruleset attached. Each rule has `conditions` (groups of conditions: OR across groups, AND within a group) and one `action`.

```json theme={null}
{
  "id": "rule_2Ab4Cd6eFg8hJk0lMn2oPq",
  "object": "rule",
  "ruleset": "rset_6Kp8Lm1nQr3sTu5vWx7yZa",
  "name": "Skip internal transfers",
  "position": 0,
  "enabled": true,
  "conditions": { "groups": [ { "conditions": [ { "field": "description", "operator": "contains", "value": "transfer to savings" } ] } ] },
  "action": { "type": "skip" },
  "metadata": null,
  "livemode": true,
  "created": "2026-08-21T02:00:00.000Z",
  "updated": "2026-08-21T02:00:00.000Z"
}
```

Fields: `merchantName`, `description`, `amount`, `direction`, `category`, `class`, `accountId`, `reference`. Operators: `contains`, `does_not_contain`, `equals`/`is`, `is_not`, `starts_with`, `is_in`, `is_not_in`, and for `amount` `gt`, `lt`, `eq`, `between`. Actions: `{ "type": "skip" }`, `{ "type": "email" }` (notify by email, still written), `{ "type": "set_category", "value": "…" }`, `{ "type": "set_merchant", "value": "…" }`. Rules evaluate in `position` order; the first `skip` wins.

`value` is always a string, or an array of strings for `between`, `is_in` and `is_not_in`. A number is rejected with `400 parameter_invalid`.

<Warning>
  Rule amounts are the **only** place in v2 where money is not minor units. An `amount` value is a decimal string in major units — `"100"` means one hundred dollars, not one hundred cents — and it is compared against the **absolute** value of the transaction, so `gt "100"` matches a −$104.96 debit and a +$104.96 credit alike. Use a `direction` condition in the same group to restrict to one side. `between` takes two values and orders them for you.
</Warning>

Dry-run a ruleset before attaching it: `POST /v2/rulesets/{id}/preview` returns the actions each recent transaction would receive, and writes nothing.

| Method and path                         | Scope              | Notes                                                                                                                                   |
| --------------------------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /v2/rulesets`, `POST /v2/rulesets` | rules:read / write | `{ name, enabled?, metadata? }`                                                                                                         |
| `GET`/`POST`/`DELETE /v2/rulesets/{id}` | rules:read / write |                                                                                                                                         |
| `POST /v2/rulesets/{id}/duplicate`      | rules:write        | Copies the ruleset and its rules                                                                                                        |
| `GET`/`POST /v2/rulesets/{id}/rules`    | rules:read / write | Create appends; 409 `rule_limit_reached` at 20                                                                                          |
| `POST /v2/rulesets/{id}/rules/reorder`  | rules:write        | `{ rules: [every rule id, in order] }`                                                                                                  |
| `GET`/`POST`/`DELETE /v2/rules/{id}`    | rules:read / write |                                                                                                                                         |
| `POST /v2/rulesets/{id}/preview`        | rules:read (heavy) | `{ account, limit?, from?, to? }` dry run over recent transactions; returns `{ transaction, actions, skipped }` per row, writes nothing |
| `POST /v2/syncs/{id}/rulesets`          | syncs:write        | Attach (`["rset_…"]`) or detach (`[]`)                                                                                                  |
