Skip to main content
Every row from every source, whatever the file format, becomes the same eight-field transaction. Matching, tolerances, and duplicate detection all operate on this normalized shape, not on the original file.

From a row to a transaction

A bank CSV row like this:
becomes this transaction:

Amounts are integers

amount is 150000, not 1500.00. Reconify stores every amount as a minor-unit integer so comparisons are exact integer arithmetic: no float rounding ever enters a match decision. The parser’s multiplier controls the conversion, and getting it wrong puts every amount off by the same factor:
  • multiplier: 100 when the source file holds major units like 1,234.56 (most bank exports). 1,234.56 becomes 123456.
  • multiplier: 1 when the source file already holds minor units, like a Stripe amount field. 123456 stays 123456.
Pairing multiplier: 100 with a source that is already in minor units, the classic Stripe trap, makes every amount 100 times too large and turns every row into an amount_diff. If a run comes back with almost nothing matching and the amounts look absurd, check multiplier first.

Reference vs group key

ref_col is the matching key: reference matching compares it directly, and name-token matching only runs on rows without a usable reference. group_col is a separate key used only for duplicate detection, and it falls back to ref_col when you don’t set it. They diverge when several rows legitimately share one identifier but need to match independently. An invoice paid in three installments shares an invoice number in ref_col, but each installment has its own payment_id. Leave group_col unset and the duplicate detector groups all three installments together and flags them. Set group_col: payment_id and each row gets its own duplicate-detection key, so the detector stops flagging legitimate installments while ref_col still ties them to the same invoice for matching.

Optional fields and what omitting them costs

currency_col, name_col, and ref_col are all optional, and the file still parses without them, but matching behavior changes:
  • An empty reference never participates in reference matching, and an empty group_key is never grouped as a duplicate.
  • An empty name weakens token matching for that row when name_mode: tokens is set.
  • An empty currency is allowed on its own, but mixing empty and non-empty currencies for the same base currency fails the run.

Raw fields

By default, every transaction carries raw: the original row or object, unparsed. It’s useful for debugging a bad mapping, but it costs memory on large sources. Set skip_raw: true on a source when you don’t need the original fields in output.