Skip to main content
Rules

Rule configuration

Everything you need to know about rules, and how to configure them.

Written By Matias

Last updated 1 day ago

The Synci rule engine enables advanced financial automation. While our introductory guide covers the basics of creating rules, this article dives deep into the configuration options that allow you to transform, calculate, and precisely control how your data flows between your bank and your destinations.


Rule components & logic

Every rule consists of Conditions (the "if") and Actions (the "then"). If a rule has no conditions, its actions run on every transaction the rule processes.

Conditions

Conditions define when a rule should trigger. Each condition consists of:

  • Field: The transaction property to check (e.g., amount, creditor.name).

  • Operator: The comparison logic (e.g., Contains, Greater than, Matches regex).

  • Value: The value to compare against. You can use static text and/or dynamic Liquid expressions.

Text comparisons are case-sensitive: a condition that checks whether the payee Contains coffee won't match COFFEE SHOP. For a case-insensitive match, use Matches regex with the inline (?i) flag, for example /(?i)coffee/.

Actions

Actions define what happens when conditions are met. Multiple actions can be added to a single rule, and they are executed in the order you define them. Each action consists of:

  • Field: The transaction property to set. You pick it from one list, grouped by where the change applies (see Choosing what an action changes below).

  • Value: The value to set the field to. You can use static text and/or dynamic Liquid expressions.

Rule settings (trigger logic)

You'll find these on the rule's Settings tab, under Behavior:

  • Trigger on any condition: If enabled, the rule triggers if at least one condition matches (OR logic). If disabled, all conditions must match (AND logic). Once a rule has two or more conditions, the Match All / Any control above them in the builder changes the same setting.

  • Skip other rules when triggered: If enabled and this rule triggers, Synci will stop processing any subsequent rules for that specific transaction. Use this to prioritize specific rules or create "catch-all" logic at the bottom of your list.

  • Enabled: Disabled rules are not executed.


Liquid expressions

Synci uses the Liquid template language for dynamic values in rule conditions and actions. Liquid lets you reference transaction fields, apply filters to transform values, and chain multiple operations together.

Basic syntax

Use {{ }} to insert a dynamic value:

{{ transaction.creditor.name }}

This inserts the creditor name from the current transaction. All transaction fields are accessed through the transaction object.

Only what's inside {{ }} is evaluated. Plain text (without {{ }}) is treated as a literal value, so no special syntax is needed for static values like 100, EUR, or Groceries.

Inserting variables

In the rule editor, type { to open the variable picker. Select a field from the dropdown to insert it as a chip, with optional modifiers. You can also type the full variable path manually if free-text is enabled.

We also provide a “Insert variable” button below the input field. Clicking this will open the same window as if you had typed {.

Commonly used fields

Field Description

transaction.amount

Transaction amount (positive for income, negative for expenses)

transaction.currency

ISO currency code (e.g., EUR, USD, NOK)

transaction.creditor.name

The name of the party receiving the payment

transaction.debtor.name

The name of the party sending the payment

transaction.remittance_information.unstructured

The "memo" or "description" from your bank

transaction.booking_date

The date the transaction was recorded by the bank

transaction.value_date

The date the transaction was settled

transaction.balance_after_transaction

Account balance after the transaction

Mapped fields

Synci provides mapped fields: the date, payee and description Synci shows across the app, based on the Map fields section of each account's settings.

FieldDescription

transaction.mapped_fields.payee

The payee Synci shows for the transaction

transaction.mapped_fields.description

The description Synci shows for the transaction

transaction.mapped_fields.date

The most relevant date for the transaction

Older rules may use transaction.mapped.payee and the other transaction.mapped.* paths. These still work, but transaction.mapped_fields.* is the path to use going forward.

Other fields

For the full list of available fields, see the {{ }} variable picker in the rule editor. Additional fields include debtor/creditor details (IBAN, BIC, etc.), remittance information, currency exchange data, external identifiers, and enriched transaction data.


Modifiers / Filters

Modifiers transform a value. Add a modifier after a variable using the | (pipe) character:

{{ transaction.creditor.name | upcase }}

This takes the creditor name and converts it to uppercase.

Chaining filters

Filters can be chained left-to-right. Each filter receives the output of the previous one:

{{ transaction.remittance_information.unstructured | remove: "REF " | upcase | truncate: 50 }}

This removes "REF ", converts to uppercase, then truncates to 50 characters.

Limits: A value can use at most 10 filters in total, counted across all of its {{ }} tags combined, and can be at most 10,000 characters long.

Text filters

FilterExampleDescription

remove

{{ transaction.creditor.name | remove: "PURCHASE AT " }}

Remove all occurrences of a substring

replace

{{ transaction.mapped_fields.description | replace: "old", "new" }}

Replace all occurrences of a substring

upcase

{{ transaction.creditor.name | upcase }}

Convert to UPPERCASE

downcase

{{ transaction.creditor.name | downcase }}

Convert to lowercase

strip

{{ transaction.mapped_fields.description | strip }}

Remove leading and trailing whitespace

truncate

{{ transaction.mapped_fields.description | truncate: 50 }}

Truncate to a maximum number of characters

append

{{ transaction.mapped_fields.description | append: " (synced)" }}

Add text to the end

prepend

{{ transaction.mapped_fields.description | prepend: "Note: " }}

Add text to the beginning

Position-based text filters

These Synci-specific filters operate on character positions (1-based indexing):

FilterExampleDescription

remove_at

{{ transaction.mapped_fields.description | remove_at: 1, 5 }}

Remove characters from position 1 to 5

keep_at

{{ transaction.mapped_fields.description | keep_at: 6 }}

Keep everything from position 6 onward

remove_at details:

  • {{ value | remove_at: 5 }}: Removes everything from the 5th character to the end.

  • {{ value | remove_at: 1, 10 }}: Removes the first 10 characters.

  • {{ value | remove_at: 5, 5 }}: Removes only the 5th character.

keep_at details:

  • {{ value | keep_at: 5 }}: Keeps everything from the 5th character to the end (removes the first 4).

  • {{ value | keep_at: 1, 10 }}: Keeps only the first 10 characters.

  • {{ value | keep_at: 3, 8 }}: Keeps only characters 3 through 8.

Math filters

FilterExampleDescription

times

{{ transaction.amount | times: 1.21 }}

Multiply (e.g., add 21% tax)

plus

{{ transaction.amount | plus: 1.50 }}

Add a value

minus

{{ transaction.amount | minus: 5 }}

Subtract a value

divided_by

{{ transaction.amount | divided_by: 100 }}

Divide by a value

abs

{{ transaction.amount | abs }}

Absolute value

round

{{ transaction.amount | round: 2 }}

Round to N decimal places

Math filters can be chained:

{{ transaction.amount | times: 1.21 | plus: 1.50 }}

This adds 21% tax and then a flat processing fee.

Date filters

FilterExampleDescription

date_add

{{ transaction.booking_date | date_add: 7 }}

Add days to a date

date_add (negative)

{{ transaction.booking_date | date_add: -1 }}

Subtract days from a date

date

{{ now | date: "%Y-%m-%d" }}

Format a date

date_add accepts up to 3650 days in either direction.

The now variable represents the current date and time:

{{ now | date: "%Y-%m-%d" }}           → today's date
{{ now | date_add: -7, "%Y-%m-%d" }}   → 7 days ago

Regex filters

Synci supports two regex filters: one to extract a single value (regex_capture), and one to rewrite a string using one or more capture groups (regex_replace). Both accept any standard PCRE pattern wrapped in delimiters (e.g., /pattern/).

regex_capture

Returns a single capture group (the first one by default):

FilterExampleDescription

regex_capture

{{ transaction.mapped_fields.description | regex_capture: '/Ref: (\d+)/' }}

Extract a regex match

Example: If the description is "Invoice Ref: 9982", the result is "9982".

You can optionally specify which capture group to extract by passing a second argument:

{{ transaction.mapped_fields.description | regex_capture: '/(\w+): (\d+)/', 2 }}

If no match is found, the filter returns an empty string.

regex_replace

Returns the entire input with matches substituted by a replacement template. Use backreferences ($1, $2, ${name}) to reorder or recombine capture groups in a single filter call:

FilterExampleDescription

regex_replace

{{ transaction.mapped_fields.description | regex_replace: '/REF (\d+) (\w+)/', '$2-$1' }}

Rewrite using a replacement template

Example: If the description is "REF 123 ABC", the result is "ABC-123".

Use regex_replace whenever you need more than one capture group in the output, or when you want to substitute matches in place. If the pattern doesn't match, the input is returned unchanged.

Tips for both filters:

  • Wrap the pattern in delimiters: /pattern/. Both single-quoted and double-quoted strings are accepted in Liquid.

  • Pipes (|) inside the regex pattern are part of the pattern (alternations), not filter separators, so they don't count toward the 10-filter limit.

  • If you're unfamiliar with regular expressions, try a regex helper like RegExr or Olaf Neumann's Regex Generator.

Other useful filters

FilterExampleDescription

default

{{ transaction.mapped_fields.description | default: "No description" }}

Use a fallback if the value is empty

size

{{ transaction.mapped_fields.description | size }}

Get the length of a string

split

{{ transaction.mapped_fields.description | split: "," }}

Split a string into an array

first / last

{{ transaction.mapped_fields.description | split: " " | first }}

Get the first/last element of an array

For the full list of standard Liquid filters, see the Liquid documentation.


Choosing what an action changes

There is no action type to pick. When you add an action, you choose the field to change from a single list, grouped by where the change applies. The groups you see depend on the kind of rule.

Rules that change your data in Synci

These rules set fields on the stored transaction, so the change is permanent and shows up everywhere the transaction is shown, transferred or shared. The fields come in two groups:

  • Mapped fields: The date, payee and description Synci shows across the app.

  • Raw transaction fields: The underlying bank transaction fields, such as remittance_information.unstructured or creditor.name.

Rules that apply only on the way out

These rules change the outgoing copy of the transaction, never the stored one. The fields are grouped by which destinations they reach:

  • Works with all destinations: Payee, Description, Date and Amount. These reach every destination, plus the API, SimpleFIN apps and webhooks when the rule is used as an output rule.

  • YNAB only: cleared, approved, payee_name, payee_id, memo, flag_color, import_id, import_payee_name, import_payee_name_original, account_name.

  • Lunch Money only: payee, currency, recurring_id, notes, tags, external_id.

  • YNAB & Lunch Money: category_id. Instead of pasting an ID, you pick the category from a list loaded live from YNAB or Lunch Money.

  • Spreadsheet & API output: The raw transaction fields, such as remittance_information.unstructured or creditor.name. These reach Google Sheets and Notion, plus the API, SimpleFIN apps and webhooks when the rule is used as an output rule.

Google Sheets and Notion don't have fields of their own. They build each row or page from the transaction, so to change what lands there, set fields from Works with all destinations or Spreadsheet & API output. The change shows up in whichever columns or properties those fields are mapped to.

A rule's actions decide which destinations it fits, so you can only combine groups that at least one destination has in common. For example, a rule can set the payee and a YNAB memo, but it can't set both a YNAB field and a Lunch Money field, or a YNAB field and a raw transaction field: no destination could take all of them, so the rule can't be saved. Once a rule is attached, the list only offers fields that fit everything it's attached to. An output rule attached to a bank account only offers Works with all destinations, Spreadsheet & API output and Stop transfer.

Stop transfer

Only rules that apply on the way out have this action. Add it with the Stop transfer button in the Then section. When the conditions match, the transaction is not sent to the destination, and its transfer log shows Skipped Transfer. Used in an output rule on a bank account, it also hides the transaction from the API, SimpleFIN apps and webhooks. This action takes no value.

Use case: Filtering out internal transfers or specific types of automated transactions you don't wish to track.


Testing rules

Click Test at the top of a rule's page to dry-run it against real transactions. Choose up to 10 transactions, then click Run test. There is no sample data: tests always use your real transactions.

The results show you, for each transaction:

  • Whether the conditions matched (Matched, Not matched or Failed).

  • A before/after comparison of every field that was changed.

  • Any errors, for example in your Liquid expressions.

  • For rules that apply on the way out, whether the transfer would stop.

If you have unsaved changes in the builder, Test asks how to continue: Test without saving tries your draft and leaves the saved rule untouched, while Save and test saves your changes first.

Testing runs the exact same logic as production, so what you see is what you'll get. It never saves changes or transfers anything.


Attaching, detaching, and reordering rules

Attaching rules to bank accounts or linked accounts

A new rule is already attached to the account or linked account you created it for. To attach it somewhere else, click Attach at the top of the rule's page. Choose where to attach it (only accounts and linked accounts the rule fits are listed), set the Rule execution order by dragging the rules or using the arrows, and confirm with Attach rule.

Detaching rules

Click Detach at the top of the page, choose the attachment to remove, and confirm with Detach rule. The rule and its other attachments stay, and changes it already made to stored transactions are not undone.

Reordering rules

Click the More button at the top of the page, then Reorder. Choose the bank account or linked account, then drag the rules (or use the arrows) into your preferred execution order and click Save order. On a bank account, rules that change your data and output rules each have their own order.


Configuration example: Multi-step cleanup

You can combine multiple techniques in a single rule. This one applies only on the way out and is attached to a linked account that sends to YNAB:

  1. Condition: remittance_information.unstructured Starts with CHECKING_TRANSFER:

  2. Action 1: Payee (Works with all destinations) → Internal Transfer

  3. Action 2: Memo (YNAB only) → {{ transaction.remittance_information.unstructured | remove: "CHECKING_TRANSFER: " }}

  4. Action 3: Flag Color (YNAB only) → blue

What happens: When a transaction's bank description starts with "CHECKING_TRANSFER:", YNAB receives it with "Internal Transfer" as the payee, the description without that prefix as the memo, and a blue flag. The transaction stored in Synci is unchanged. Because the rule sets fields that only YNAB has, it can only be attached to links that send to YNAB.


Pro tips

  • 1-Based Indexing: Position-based filters (remove_at, keep_at) start counting at 1, not 0.

  • Regex Delimiters: Always wrap regex patterns in delimiters (e.g., /pattern/).

  • Order Matters: Rules run in their execution order, from top to bottom. Use More > Reorder on a rule's page to change it.

  • Chain Wisely: You can use up to 10 filters per value, counted across all of its {{ }} tags. Each filter receives the result of the previous one.

  • Test First: Use Test to check your rules against real transactions as soon as you've built them.

  • Unknown Filters: The engine uses strict mode, so only recognized filters are allowed. If you use an unknown filter name, you'll get a clear error message.

  • Plain Text is Fine: You don't need Liquid syntax for simple static values. Just type EUR or Groceries directly.