Skip to main content
Rules automatically categorize transactions during sync by matching conditions on transaction fields. Each rule contains a condition tree that Breadbox evaluates against every new or modified transaction. When the condition matches, the rule applies its configured action — typically setting the transaction’s category. Rules run in priority order (lower number = runs first) according to a four-stage pipeline.

List rules

GET /api/v1/rules
Returns all transaction rules. Accepts optional filters for active/inactive status and creator type. Auth: Read

Response

{
  "data": [
    {
      "id": "r1a2b3c4-d5e6-f789-0abc-def123456789",
      "short_id": "Pq7rSt8u",
      "name": "Amazon purchases",
      "enabled": true,
      "stage": "standard",
      "priority": 10,
      "condition": {
        "type": "and",
        "conditions": [
          { "field": "name", "operator": "contains", "value": "AMAZON" }
        ]
      },
      "action_field": "category_slug",
      "action_value": "shopping-online",
      "creator_type": "user",
      "created_at": "2025-12-01T10:00:00Z",
      "updated_at": "2025-12-01T10:00:00Z"
    }
  ]
}
curl -H "X-API-Key: bb_your_key" \
  "http://localhost:8080/api/v1/rules"

Get a single rule

GET /api/v1/rules/{id}
Returns a single rule by its UUID or short ID. Auth: Read

Path parameters

id
string
required
The rule’s Breadbox UUID or short ID.
curl -H "X-API-Key: bb_your_key" \
  "http://localhost:8080/api/v1/rules/r1a2b3c4-d5e6-f789-0abc-def123456789"

Create a rule

POST /api/v1/rules
Creates a new categorization rule. The rule runs automatically on every future sync. To apply it to existing transactions immediately, use POST /api/v1/rules/{id}/apply after creation. Auth: Write

Request body

{
  "name": "Netflix subscription",
  "enabled": true,
  "stage": "standard",
  "condition": {
    "type": "and",
    "conditions": [
      { "field": "name", "operator": "contains", "value": "NETFLIX" },
      { "field": "amount", "operator": "gt", "value": 0 }
    ]
  },
  "action_field": "category_slug",
  "action_value": "entertainment-streaming-services"
}
name
string
required
Human-readable name for the rule (e.g., "Netflix subscription").
enabled
boolean
default:"true"
Whether the rule is active. Disabled rules are skipped during sync.
stage
string
default:"standard"
Pipeline stage. One of: baseline, standard, refinement, override. Resolves to priority 0, 10, 50, or 100 respectively. Stage names are case-insensitive. If both stage and priority are provided, priority wins.
priority
integer
Raw pipeline priority integer from 0 to 1000. Lower numbers run first. Overrides stage when both are provided.
condition
object
required
The condition tree to evaluate. See Condition structure below.
action_field
string
required
The field to set when the condition matches. Typically "category_slug".
action_value
string
required
The value to assign to action_field. For category rules, this is the category slug.

Response

Returns the created rule with 201 Created.
curl -X POST \
  -H "X-API-Key: bb_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Netflix subscription",
    "stage": "standard",
    "condition": {
      "type": "and",
      "conditions": [
        { "field": "name", "operator": "contains", "value": "NETFLIX" }
      ]
    },
    "action_field": "category_slug",
    "action_value": "entertainment-streaming-services"
  }' \
  "http://localhost:8080/api/v1/rules"

Update a rule

PUT /api/v1/rules/{id}
Updates an existing rule. All fields in the request body replace their current values. Omitted fields retain their existing values. Auth: Write

Path parameters

id
string
required
The rule’s Breadbox UUID or short ID.
curl -X PUT \
  -H "X-API-Key: bb_your_key" \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}' \
  "http://localhost:8080/api/v1/rules/r1a2b3c4-d5e6-f789-0abc-def123456789"

Delete a rule

DELETE /api/v1/rules/{id}
Permanently deletes a rule. Already-categorized transactions are not affected. System-seeded rules cannot be deleted — disable them instead. Auth: Write

Path parameters

id
string
required
The rule’s Breadbox UUID or short ID.
curl -X DELETE \
  -H "X-API-Key: bb_your_key" \
  "http://localhost:8080/api/v1/rules/r1a2b3c4-d5e6-f789-0abc-def123456789"

Apply a rule retroactively

POST /api/v1/rules/{id}/apply
Runs a single rule against all existing transactions in the database. Transactions that already have a manual category_override are skipped. Returns the number of transactions updated. Auth: Write

Path parameters

id
string
required
The rule’s Breadbox UUID or short ID.

Response

{
  "updated_count": 23
}
curl -X POST \
  -H "X-API-Key: bb_your_key" \
  "http://localhost:8080/api/v1/rules/r1a2b3c4-d5e6-f789-0abc-def123456789/apply"

Apply all rules retroactively

POST /api/v1/rules/apply-all
Runs all active rules against all existing transactions, in priority order. Transactions with a category_override are skipped. This is equivalent to re-running the full categorization pipeline on historical data. Auth: Write

Response

{
  "rules_applied": 8,
  "transactions_updated": 142
}
curl -X POST \
  -H "X-API-Key: bb_your_key" \
  "http://localhost:8080/api/v1/rules/apply-all"

Preview a condition (dry run)

POST /api/v1/rules/preview
Runs a condition tree against existing transactions without making any changes. Returns the matching transactions so you can verify a condition before saving it as a rule. Auth: Write

Request body

{
  "condition": {
    "type": "and",
    "conditions": [
      { "field": "name", "operator": "contains", "value": "AMAZON" },
      { "field": "amount", "operator": "gt", "value": 50 }
    ]
  },
  "limit": 20
}
condition
object
required
The condition tree to evaluate. Uses the same structure as rule conditions.
limit
integer
default:"50"
Maximum number of matching transactions to return for preview.

Response

{
  "match_count": 34,
  "sample": [
    {
      "id": "t1a2b3c4-d5e6-f789-0abc-def123456789",
      "name": "AMAZON.COM*AB1CD2EF3",
      "amount": 89.99,
      "date": "2026-01-15"
    }
  ]
}
curl -X POST \
  -H "X-API-Key: bb_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "condition": {
      "type": "and",
      "conditions": [
        { "field": "name", "operator": "contains", "value": "AMAZON" }
      ]
    }
  }' \
  "http://localhost:8080/api/v1/rules/preview"

Condition structure

Rules use a recursive JSON condition tree. A condition node is either a leaf (field comparison) or a composite (logical combination of other nodes).

Composite nodes

TypeDescription
andAll child conditions must match.
orAt least one child condition must match.
notThe single child condition must not match.
{
  "type": "and",
  "conditions": [
    { "field": "name", "operator": "contains", "value": "AMAZON" },
    {
      "type": "or",
      "conditions": [
        { "field": "amount", "operator": "gt", "value": 50 },
        { "field": "merchant_name", "operator": "eq", "value": "Amazon" }
      ]
    }
  ]
}

Leaf nodes

FieldDescription
fieldTransaction field to evaluate (see available fields below).
operatorComparison operator (see operators below).
valueThe value to compare against.

Available fields

FieldTypeDescription
namestringRaw transaction name from the institution.
merchant_namestringCleaned merchant name from the provider.
amountnumericTransaction amount (Plaid convention: positive = debit).
category_primarystringCurrent primary category.
category_detailedstringCurrent detailed subcategory.
pendingbooleanWhether the transaction is pending.
providerstringData provider (plaid, teller, csv).
account_idstringBreadbox account UUID.
user_idstringBreadbox user UUID.
user_namestringFamily member display name.

Operators by field type

String operators
OperatorDescription
eqExact match (case-sensitive).
neqNot equal.
containsCase-insensitive substring match.
not_containsDoes not contain the substring.
matchesRegular expression match.
inValue is one of a list (pass value as an array).
Numeric operators
OperatorDescription
eqEqual.
neqNot equal.
gtGreater than.
gteGreater than or equal.
ltLess than.
lteLess than or equal.
Boolean operators
OperatorDescription
eqEqual to true or false.
neqNot equal.

Pipeline stages

Rules run in priority order during sync. Lower priority numbers run first, so earlier stages can set a baseline that later stages can refine or override.
StagePriorityDescription
baseline0Broad catch-all rules that categorize the most common transactions.
standard10Default stage. Regular categorization rules.
refinement50Rules that correct or narrow categories set by earlier stages.
override100High-confidence rules that should always win, regardless of earlier results.
Transactions with a manual category_override are skipped by all pipeline stages.

Error codes

ConditionStatusCode
Missing or invalid API key401MISSING_API_KEY / INVALID_API_KEY
Rule not found404NOT_FOUND
Unknown stage value400VALIDATION_ERROR
Invalid condition structure422VALIDATION_ERROR
Attempting to delete a system rule422VALIDATION_ERROR