list_transaction_rules and preview_rule, and Categorization for apply_rules (retroactive application).
The full DSL lives in the Breadbox repo at docs/rule-dsl.md. Key concepts recapped below under Pipeline stages.
All tools on this page are Write scope and require session_id + reason.
create_transaction_rule
Create a transaction rule. Rules match condition trees against transactions during sync and fire in pipeline-stage order (priority ASC — lower runs first). Passstage (baseline | standard | refinement | override) instead of a raw priority when you can — stage resolves to priority 0/10/50/100 so rules from different agents compose predictably.
Parameters
Human-readable description. Convention:
"<pattern-type>: <match> → <category>".Condition tree. Omit or pass
{} to match every transaction. See Condition grammar.Array of typed actions. Shapes:
{"type": "set_category", "category_slug": "..."}{"type": "add_tag", "tag_slug": "..."}{"type": "remove_tag", "tag_slug": "..."}{"type": "add_comment", "content": "..."}
add_comment fires only at sync time (not on retroactive apply). If omitted, supply category_slug as a shorthand.Shorthand for
[{"type": "set_category", "category_slug": "<slug>"}]. Either actions or category_slug is required.When the rule fires:
on_create (default — first-synced transactions), on_change (existing transactions that change on re-sync), or always (both). on_update is accepted as a legacy alias for on_change. Retroactive apply ignores trigger.Semantic pipeline stage. Preferred over raw priority. One of
baseline (priority 0), standard (10, default), refinement (50), override (100). If both stage and priority are supplied, priority wins.Raw pipeline-stage integer, 0–1000. Lower runs first. Prefer
stage for shared vocabulary.Optional expiry duration:
24h, 30d, 1w. Rule auto-disables after this period.If
true, immediately apply this rule to existing transactions after creation. Materializes set_category, add_tag, remove_tag; skips add_comment (sync-only).Example input
Example output
apply_retroactively: true was passed, the response also includes retroactive_matches: <count> (or retroactive_error: "<msg>" on failure).
update_transaction_rule
Update one rule. Every field is optional — omit to leave unchanged.conditions={} explicitly clears conditions (match-all). actions=[...] replaces the entire action set. expires_at="" clears expiry.
Parameters
Rule UUID or short ID.
New condition tree. Pass
{} to explicitly change to match-all. Omit entirely to leave conditions unchanged.Replace the entire actions array. Pass an empty array to reject (rules must have at least one action).
Shorthand: replace only the
set_category action. Other action types on the rule are preserved.Disabled rules are excluded from sync and retroactive apply.
RFC3339 timestamp, or empty string to clear expiry.
Example input
Example output
delete_transaction_rule
Delete a rule by ID. System-seeded rules (theneeds-review auto-tagger) cannot be deleted — disable them via update_transaction_rule instead.
Parameters
Rule UUID or short ID.
Example input
Example output
batch_create_rules
Create up to 100 rules in one call. Ideal for composable pipelines — each item can set itsstage to order rules so earlier stages set up tags/categories that later stages react to.
Each item follows the same shape as create_transaction_rule. Returns created rules plus any per-item errors so partial success is recoverable.
Parameters
Array of rule definitions. Max 100. Each item has
name (required), conditions, actions or category_slug (one required), trigger, stage, priority, expires_in.Example input
Example output
Pipeline stages and priority
Rules fire in priority-ASC order during each sync pass, and within a single pass each rule observes mutations from earlier-stage rules. That makes rules composable — rule A can add a tag, rule B’s condition can react to that tag, rule C can set a category based on the combined state.| Stage | Priority | Typical use |
|---|---|---|
baseline | 0 | Broad defaults — tagging coffee shops, marking credit card payments |
standard | 10 (default) | Most categorization rules |
refinement | 50 | Rules that react to earlier-stage tags or categories |
override | 100 | Rules that forcibly win set_category regardless of what earlier stages did |
- Per-merchant rules (priority 20–30 or
refinement) > name-pattern rules (standard) >category_primaryrules (baseline). - Prefer
containsover exact match — bank feeds format merchant names inconsistently. - Always use
category_slug, notcategory_id, when authoring actions or filters.
Condition grammar
Same grammar used bypreview_rule.
- Fields —
name,merchant_name,amount,category_primary,category_detailed,category(assigned slug, live-updated by earlier-stage rules),pending,provider,account_id,account_name,user_id,user_name,tags. - Operators —
- String/category:
eq,neq,contains,not_contains,matches(RE2),in. - Numeric:
eq,neq,gt,gte,lt,lte. - Bool:
eq,neq. - Tags:
contains,not_contains,in.
- String/category:
- Combinators —
and,or,not(nest freely, max depth 10).