Skip to main content
This section provides a deep dive into every mechanism available for constructing conditions.

2.1 Accessing Transaction Data

Transaction data is represented as a flat or nested JSON object. You access fields using dot notation. Top-level fields: These are the standard fields on the transactions table: Accessing nested metadata: The metadata field is a JSON object that can contain any custom data your system sends. You access its properties with dot notation:
How it works internally: The interpreter uses a dig() function that splits the path by . and traverses the JSON tree. If any part of the path does not exist, the condition evaluates to false (it does not throw an error). Pitfall: If a field is missing from the transaction data, the condition silently fails. This is by design — it prevents rules from crashing on incomplete data. But it means a typo in a field name (e.g., ammount instead of amount) will cause a rule to never trigger without any error message.

2.2 Comparison Operators

These operators form the backbone of simple conditions. Each compares a field’s value against a target value. Type Coercion Rules: The interpreter attempts to compare values numerically first. If both sides can be parsed as float64, a numeric comparison is performed. If not, both sides are converted to strings and compared lexicographically. This means:
  • amount > 1000 -> Numeric comparison (correct).
  • currency == "USD" -> String comparison (correct).
  • "100" > "99" -> String comparison ("1" < "9", so this is false). Be careful with stringified numbers.
Important: For string comparisons, only eq and ne are supported. Using >, <, >=, or <= on non-numeric strings will return false. Examples:

2.3 Logical Operators: and / or

Logical operators combine multiple conditions into a single boolean result. Syntax:
Operator Precedence: Currently, and and or have equal precedence and are evaluated left-to-right. There is no implicit grouping that makes and bind tighter than or. For the rule:
This is parsed as (A or B) and C, not A or (B and C). This is a critical detail. If you need specific grouping, structure your rule conditions carefully or split into multiple rules. Multi-line conditions: The parser supports conditions that span multiple lines. You can place and/or at the beginning of a new line for readability:
Short-circuit evaluation: The interpreter uses short-circuit logic:
  • For and: If the left side is false, the right side is not evaluated.
  • For or: If the left side is true, the right side is not evaluated.
This is important for performance — expensive aggregate checks placed on the right side of an and will be skipped if a cheap check on the left already fails.

2.4 Set Operators: in

The in operator checks whether a field’s value exists within a given list. This is essential for checking against blacklists, whitelists, or known-bad values. Syntax:
How it works: The interpreter converts the field value to a string and iterates through the list, comparing each element as a string. This means in is a string membership check. Example: Sanctioned Country Check
Example: Suspicious MCC Check

2.5 Pattern Operators: regex and not_regex

The regex operator performs regular expression matching on string fields. This is powerful for detecting suspicious patterns in free-text fields like transaction descriptions. Syntax:
Key Facts:
  • The pattern is a standard Go regular expression (RE2 syntax).
  • regex returns true if the pattern matches anywhere in the field value.
  • not_regex returns true if the pattern does not match.
  • The pattern must be a double-quoted string.
  • Use (?i) at the start for case-insensitive matching.
Example: Detecting Suspicious Descriptions
Pitfall: Complex regex patterns can be expensive. Avoid catastrophic backtracking patterns like (.+)+ on large strings. Keep patterns as simple and specific as possible.