Author a matcher
Describe which records from two sources should be compared, what counts as evidence, and what happens when a pair is confirmed.
A matcher tells Twin Matching which records to compare, how to score a pair, and what a confirmed pair means. Matchers are authored as definitions and activated through the API; every change is a new version, and the previous version retires with its open queue. This page is for the person writing one.
The two sides
A matcher compares a left side with a right side. Each side is either an object type in a workspace channel, or a relation in the connected warehouse (a Xero contacts view, a SUN accounts view, the rows of a synced spreadsheet).
A warehouse side can be shaped before anything is compared:
- Filter narrows it to the rows the matcher is about, for example SUN accounts of one type, or the rows of one spreadsheet tab. Filters are simple predicates on columns: equals, not equals, in a list, not in a list, is null, is not null. Every filter must hold.
- Parent fields read a column from the row's parent through a relationship
the connection schema already declares, such as an invoice's contact name
through
invoice_contact. The value appears on the row under the name you give it, so a comparator can check that a record's counterparty agrees with the invoice's own contact. - Composed fields join several of the row's own columns into one, such as a person's full name from first name and surname, so a split name can block and compare like a single one.
When both sides read the same rows, the matcher looks for duplicates within one source. A row never pairs with itself and each pair appears once.
Blocking: which pairs are even considered
Comparing every row with every other row is never done. Blocking rules pick the pairs worth scoring by deriving a key from one field on each side and pairing rows whose keys are equal. Rules are combined, so a pair reached by any rule is considered.
identifier_equalfor shared ids and references.normalised_text_equalfor exact names after case and punctuation are removed.name_key_equalfor organisation names with legal suffixes stripped (Ltd, Limited, GmbH and so on), a fuzzy but bounded key.prefix_equalfor the first few characters of the normalised text: a coarse block that reaches spelling variants at the cost of more pairs to score.
A matcher declares a pair budget; a run that blocks more pairs than that fails rather than scoring them.
Comparators: how a pair is scored
Each comparator compares one field on each side with one operator, returns an
agreement between 0 and 1, and carries a weight. The score is the weighted
average of the comparators that had a value on both sides; a missing value is
never evidence of disagreement. Operators are identifier_equal,
normalised_text_equal, trigram_similarity (with a minimum similarity),
numeric_tolerance (absolute or relative, with a sign convention when one
source stores spend as negatives) and date_window.
Contradictions name the comparators whose disagreement means the pair can never be applied automatically, whatever its score. A comparator may carry a weight of zero: it then records agreement and can raise a contradiction without moving the score at all. Use that when a check is a flag rather than evidence, otherwise a disagreeing check can pull a pair below the review band before its flag is seen. At least one comparator must carry weight.
Bands and outcomes
Two thresholds turn a score into a band. At or above the automatic band a pair is decided by the matcher itself with the outcome you name, unless it carries a contradiction, in which case it goes to review. At or above the review band a pair waits for a person. Below that it is abstained and not kept. Leaving the automatic band unset makes a matcher review-only, which is where every new matcher on a customer's data should start.
Outcomes are what a reviewer can choose: at least one equivalence outcome and one negative outcome, usually with an abstain. An equivalence outcome can materialise: record an identity link between the two systems, stamp a channel record with the warehouse row it came from (so later runs know the pair is already linked and the record knows its source), or write a reference field. Nothing changes a record until a pair is confirmed, and every decision can be undone.
Scheduling and freshness
A matcher runs again on its own when either side has newer data, no more often than the interval you set. A run you start by hand is queued and lands in the Inbox as a batch shortly after; the scoring happens beside the connectors, not in the request. A matcher can also declare how stale a side may be before automatic decisions are held for a person, and the organisation's link policy can raise or hold the automatic band above whatever the matcher says.
Evaluating a change
Do not judge a matcher by eye. Before changing one, capture its current candidates; after, run the new version and compare: which pairs appeared or disappeared, which changed band, whether any automatic pair was lost. Write down what you expect the counts to be before you look. The run header reports how many pairs each comparator contradicted and how many pairs were already linked, which is usually enough to see whether a change did what you meant.