Skip to main content
Rules are the workhorse of any Breadbox setup. A well-tuned set of rules can categorize the overwhelming majority of your transactions during sync, leaving only the genuinely ambiguous ones for a human or agent to look at. This guide walks through the DSL by example — four rules you can adapt and drop into your instance today. If you haven’t yet, skim Breadbox in a nutshell first for the vocabulary. The full specification lives in Auto-categorize transactions with rules and the rules API reference.

The DSL, in one screen

A rule is a JSON document with three important pieces:
  1. A condition — a recursive tree of leaves (field/op/value) and combinators (and / or / not).
  2. One or more actionsset_category, add_tag, remove_tag, add_comment, or assign_series (link the charge to a recurring series).
  3. A trigger and stage — when the rule runs (, always, on_change) and where in the pipeline (baseline, standard, refinement, override).
Amounts use Plaid convention: positive = money out (purchases, payments), negative = money in (refunds, paychecks). Every example below respects that.

Example 1 — Amazon purchases → Shopping

The canonical “merchant name contains a substring” rule. Two conditions combined with and: the description must contain AMAZON, and the amount must be positive (so we don’t catch Amazon refunds).
Create it via the API:
Before saving, dry-run against your history to sanity-check the match count:

Example 2 — Uber / Lyft / Waymo → Transportation

When a single condition isn’t enough, an or group handles the “any of these merchants” case. Here we use the in operator on merchant_name to check against a list in one shot.
merchant_name is only populated for providers that enrich the raw description (Plaid does this; Teller and CSV imports often don’t). If your data comes primarily from Teller, prefer name with contains and match on a substring of the raw description.

Example 3 — Threshold tag: flag anything over $500

Not every rule has to change the category. This one only tags — anything over $500 gets the high-amount tag so you can scan the queue for big-ticket items before the rest.
You’d pair this with a tag you’ve pre-created in the dashboard (TagsNew tag, slug high-amount). Then filter to /transactions?tags=high-amount in the UI, or query_transactions(tags=["high-amount"]) from an agent.

Example 4 — A not rule: auto-categorize groceries, but not Whole Foods prepared food

Sometimes the cleanest way to express a rule is “match this except for these cases.” The not combinator wraps a sub-condition and inverts it.
You can freely nest and, or, and not up to 10 levels deep. For most workflows you’ll keep it under three.
If a transaction gets the wrong category anyway, set it manually from the dashboard. That sets , which the rule engine honors forever — your deliberate choice won’t be undone by a later rule.

Applying rules retroactively

Rules only fire at sync time by default. To run a newly created rule against your full history:
Retroactive apply follows the same pipeline order and the same category_override protection as live sync. One caveat: add_comment actions are skipped during retroactive apply (they’re designed to narrate a specific sync event).

Where to go next

Last modified on June 13, 2026