> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Match rules

> Author exact, tolerance, date-lag, and fuzzy rules in Matcher. Set priorities, tolerances, and reference matching to control how transactions pair up.

Match rules are where you set your reconciliation policy. The policy sets how strict or forgiving Matcher is when it decides two transactions are the same. Tight rules mean more manual review but fewer false matches. Looser rules automate more but need careful oversight. You can enforce exact matches, allow controlled variance, tolerate timing differences, or compare free-text references by similarity.

## How rules work

***

When a matching run starts, Matcher evaluates rules in priority order.

* Rules are evaluated from the lowest priority number to the highest.
* Each rule creates all matches it can from transactions not already used by higher-priority rules.
* After every rule runs, transactions that remain unmatched become exceptions.

This approach stops any rule from reusing a higher-priority match. Progressively looser rules process the transactions that remain.

## Rule types

***

### Exact

Requires a strict match on configured fields.

* **Best for**: Deterministic matches where values should align 1:1.

### Tolerance

Allows controlled variance in amount matching.

* **Best for**: Known variance patterns such as fees, rounding, or FX differences.

### Date lag

Allows date differences between transactions.

* **Best for**: Posting delays between systems.

### Fuzzy

Replaces exact reference equality with normalized string-similarity scoring. Amount, currency, and date gates require exact equality by default, but `matchAmount`, `matchCurrency`, and `matchDate` independently control whether each gate applies. FUZZY always proposes a match for review and never auto-confirms.

* **Best for**: Free-text memos or truncated references where the reference varies but the enabled financial gates still align.

## Creating match rules

***

### Exact rule

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/contexts/{contextId}/rules" \
 -H "Authorization: Bearer $TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
   "type": "EXACT",
   "priority": 1,
   "config": {
     "matchAmount": true,
     "matchCurrency": true,
     "matchDate": true,
     "matchReference": true,
     "datePrecision": "DAY",
     "caseInsensitive": true,
     "referenceMustSet": false,
     "matchBaseAmount": false,
     "matchBaseCurrency": false,
     "matchScore": 100,
     "matchBaseScore": 90
   }
 }'
```

#### Config reference

<ParamField path="matchAmount" type="Boolean" default="true">
  Require exact amount match
</ParamField>

<ParamField path="matchCurrency" type="Boolean" default="true">
  Require exact currency match
</ParamField>

<ParamField path="matchDate" type="Boolean" default="true">
  Require exact date match
</ParamField>

<ParamField path="matchReference" type="Boolean" default="true">
  Require exact reference match
</ParamField>

<ParamField path="datePrecision" type="String" default="DAY">
  Date comparison precision: `DAY` or `TIMESTAMP`
</ParamField>

<ParamField path="caseInsensitive" type="Boolean" default="true">
  Case-insensitive reference comparison
</ParamField>

<ParamField path="referenceMustSet" type="Boolean" default="false">
  Require reference to be present on both sides
</ParamField>

<ParamField path="matchBaseAmount" type="Boolean" default="false">
  Match on base (converted) amount instead of original
</ParamField>

<ParamField path="matchBaseCurrency" type="Boolean" default="false">
  Match on base currency instead of original
</ParamField>

<ParamField path="matchScore" type="Integer" default="100">
  Accepted and validated, but **reserved/inert**. It does not change the calculated confidence score (see note below)
</ParamField>

<ParamField path="matchBaseScore" type="Integer" default="90">
  Accepted and validated, but **reserved/inert**. It does not change the calculated confidence score (see note below)
</ParamField>

<Note>
  **`matchScore` and `matchBaseScore` are currently inert.** They are accepted and validated in the rule config, but the scoring engine ignores them: confidence is always computed from the fixed internal component weights (amount 40, currency 30, date 20, reference 10). These fields are reserved for future use and setting them does **not** alter the confidence score or auto-confirm behavior. See [Confidence scoring](/en/products/matcher/reference/matcher-confidence-scoring).
</Note>

The response echoes the persisted rule with its assigned `id` and timestamps.

<Tip>
  API Reference: [Create match rule](/en/reference/products/matcher/create-match-rule)
</Tip>

### Tolerance rule

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/contexts/{contextId}/rules" \
 -H "Authorization: Bearer $TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
   "type": "TOLERANCE",
   "priority": 2,
   "config": {
     "percentTolerance": 0.005,
     "absTolerance": 0.50,
     "dateWindowDays": 3,
     "roundingScale": 2,
     "roundingMode": "HALF_UP",
     "percentageBase": "MAX",
     "matchCurrency": true,
     "matchReference": true,
     "caseInsensitive": true,
     "referenceMustSet": false,
     "matchBaseAmount": false,
     "matchBaseCurrency": false,
     "matchScore": 85,
     "matchBaseScore": 80
   }
 }'
```

#### Config reference

<ParamField path="percentTolerance" type="Decimal">
  Percentage threshold applied to `percentageBase` (0.005 = 0.5%). Defaults to `0`. Matcher compares this threshold with `absTolerance` and uses the larger one
</ParamField>

<ParamField path="absTolerance" type="Decimal">
  Absolute amount threshold. Defaults to `0`. Matcher compares it with the percentage threshold and uses the larger one
</ParamField>

Both thresholds default to zero, so you must configure any permitted amount variance explicitly.

<ParamField path="dateWindowDays" type="Integer">
  Number of days allowed between transaction dates
</ParamField>

<ParamField path="roundingScale" type="Integer">
  Decimal places for rounding
</ParamField>

<ParamField path="roundingMode" type="String">
  Rounding strategy: `HALF_UP`, `BANKERS`, `FLOOR`, `CEIL`, or `TRUNCATE`
</ParamField>

<ParamField path="percentageBase" type="String" default="MAX">
  Base for percentage calculation: `MAX`, `MIN`, `AVERAGE`, `LEFT`, or `RIGHT`
</ParamField>

<ParamField path="matchCurrency" type="Boolean" default="true">
  Require currency match
</ParamField>

<ParamField path="matchReference" type="Boolean" default="true">
  Require reference match
</ParamField>

<ParamField path="caseInsensitive" type="Boolean" default="true">
  Case-insensitive reference comparison
</ParamField>

<ParamField path="referenceMustSet" type="Boolean" default="false">
  Require reference to be present on both sides
</ParamField>

<ParamField path="matchBaseAmount" type="Boolean" default="false">
  Match on base (converted) amount
</ParamField>

<ParamField path="matchBaseCurrency" type="Boolean" default="false">
  Match on base currency
</ParamField>

<ParamField path="matchScore" type="Integer" default="85">
  Accepted and validated, but **reserved/inert**. It does not change the calculated confidence score
</ParamField>

<ParamField path="matchBaseScore" type="Integer" default="80">
  Accepted and validated, but **reserved/inert**. It does not change the calculated confidence score
</ParamField>

**Example:**

* Transaction A: \$1,000.00
* Transaction B: \$1,005.00
* Amount difference: \$5.00
* Percentage threshold: $1,005.00 × 0.5% = $5.025 (`percentageBase: MAX`)
* Absolute threshold: \$0.50
* Effective threshold: `MAX($5.025, $0.50)` = \$5.025 → **Matches**

### Fuzzy rule

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/contexts/{contextId}/rules" \
 -H "Authorization: Bearer $TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
   "type": "FUZZY",
   "priority": 4,
   "config": {
     "minSimilarity": 0.85,
     "matchAmount": true,
     "matchCurrency": true,
     "matchDate": true,
     "datePrecision": "DAY",
     "referenceMustSet": true,
     "matchScore": 70
   }
 }'
```

#### Config reference

<ParamField path="minSimilarity" type="Decimal" default="0.80">
  Minimum normalized reference similarity (0–1) required to gate as a match
</ParamField>

<ParamField path="matchAmount" type="Boolean" default="true">
  When `true`, require an exact amount match
</ParamField>

<ParamField path="matchCurrency" type="Boolean" default="true">
  When `true`, require an exact currency match
</ParamField>

<ParamField path="matchDate" type="Boolean" default="true">
  When `true`, require an exact date match
</ParamField>

<ParamField path="datePrecision" type="String" default="DAY">
  Date comparison precision: `DAY` or `TIMESTAMP`
</ParamField>

<ParamField path="referenceMustSet" type="Boolean" default="true">
  Require a non-empty reference on both sides
</ParamField>

<ParamField path="matchScore" type="Integer" default="70">
  Accepted and defaulted to `70`, but **reserved/inert**. It does not cap or change calculated confidence or auto-confirm behavior
</ParamField>

<Note>
  FUZZY replaces reference equality with similarity. By default, it also requires exact amount, currency, and date matches. Disable each gate independently with `matchAmount`, `matchCurrency`, or `matchDate`. FUZZY always proposes matches for human review and never auto-confirms them.
</Note>

### Date lag rule

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/contexts/{contextId}/rules" \
 -H "Authorization: Bearer $TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
   "type": "DATE_LAG",
   "priority": 3,
   "config": {
     "maxDays": 3,
     "minDays": 0,
     "inclusive": true,
     "direction": "ABS",
     "feeTolerance": 0,
     "matchScore": 80,
     "matchCurrency": true
   }
 }'
```

#### Config reference

<ParamField path="maxDays" type="Integer">
  Maximum number of days difference allowed
</ParamField>

<ParamField path="minDays" type="Integer" default="0">
  Minimum number of days difference required
</ParamField>

<ParamField path="inclusive" type="Boolean" default="true">
  Whether the boundary days are inclusive
</ParamField>

<ParamField path="direction" type="String" default="ABS">
  How to measure the lag: `ABS` (absolute), `LEFT_BEFORE_RIGHT`, or `RIGHT_BEFORE_LEFT`
</ParamField>

<ParamField path="feeTolerance" type="Decimal" default="0">
  Allowed amount difference to account for fees
</ParamField>

<ParamField path="matchScore" type="Integer" default="80">
  Accepted and validated, but **reserved/inert**. It does not change the calculated confidence score. Note that DATE\_LAG rules always score the reference component as 0, capping the maximum score at 90
</ParamField>

<ParamField path="matchCurrency" type="Boolean" default="true">
  Require currency match
</ParamField>

### Allocation settings (all rule types)

All rule types accept additional allocation settings for split and aggregate matching:

| Field                      | Type    | Description                                              |
| -------------------------- | ------- | -------------------------------------------------------- |
| `allowPartial`             | Boolean | Allow partial allocation of transaction amounts          |
| `allocationDirection`      | String  | Allocation order: `LEFT_TO_RIGHT` or `RIGHT_TO_LEFT`     |
| `allocationToleranceMode`  | String  | How tolerance is measured: `ABS` (absolute) or `PERCENT` |
| `allocationToleranceValue` | Decimal | Tolerance threshold for allocation                       |
| `allocationUseBaseAmount`  | Boolean | Use base (converted) amount for allocation               |

## Rule priority

***

Rules are evaluated by priority. Lower numbers run first.

### Priority strategy

| Priority | Rule type | Use case                         |
| -------- | --------- | -------------------------------- |
| 1–10     | EXACT     | Deterministic matches            |
| 11–50    | TOLERANCE | Small, expected variance         |
| 51–100   | DATE\_LAG | Date differences between systems |

### Reorder rules

You can reorder rules by providing the rule IDs in the desired order:

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/contexts/{contextId}/rules/reorder" \
 -H "Authorization: Bearer $TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
   "ruleIds": [
     "550e8400-e29b-41d4-a716-446655440001",
     "550e8400-e29b-41d4-a716-446655440002",
     "550e8400-e29b-41d4-a716-446655440000"
   ]
 }'
```

<Tip>
  API Reference: [Reorder match rules](/en/reference/products/matcher/reorder-match-rules)
</Tip>

## Testing rules

***

Test rules in dry-run mode before committing matches.

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/matching/contexts/{contextId}/run" \
 -H "Authorization: Bearer $TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
   "mode": "DRY_RUN"
 }'
```

Dry run mode evaluates all rules and returns potential matches. It does not create exceptions, but Matcher completes and persists the `MatchRun` with statistics and emits its completion event.

## Managing rules

***

### List rules

```bash cURL theme={null}
curl -X GET "https://api.matcher.example.com/v1/contexts/{contextId}/rules" \
 -H "Authorization: Bearer $TOKEN"
```

#### Response

The list endpoint returns a summary view of rules. To see the full configuration details for a specific rule, use the individual rule endpoint or the create response which includes the complete `config` object.

```json theme={null}
{
  "items": [
    {
      "id": "019c96a0-2b20-7123-9a1b-2c3d4e5f6a7b",
      "contextId": "019c96a0-2a10-7dfe-b5c1-8a1b2c3d4e5f",
      "type": "EXACT",
      "priority": 1,
      "config": {
        "matchAmount": true,
        "matchCurrency": true,
        "matchDate": true,
        "matchReference": true,
        "datePrecision": "DAY",
        "matchScore": 100,
        "matchBaseScore": 90
      },
      "createdAt": "2026-02-02T16:40:00Z",
      "updatedAt": "2026-02-02T16:40:00Z"
    }
  ],
  "limit": 20,
  "hasMore": false
}
```

<Tip>
  API Reference: [List match rules](/en/reference/products/matcher/list-match-rules)
</Tip>

### Update a rule

```bash cURL theme={null}
curl -X PATCH "https://api.matcher.example.com/v1/contexts/{contextId}/rules/{ruleId}" \
 -H "Authorization: Bearer $TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
   "priority": 5,
   "type": "TOLERANCE",
   "config": {
     "percentTolerance": 0.02,
     "absTolerance": 10.0
   }
 }'
```

<Tip>
  API Reference: [Update match rule](/en/reference/products/matcher/update-match-rule)
</Tip>

### Delete a rule

```bash cURL theme={null}
curl -X DELETE "https://api.matcher.example.com/v1/contexts/{contextId}/rules/{ruleId}" \
 -H "Authorization: Bearer $TOKEN"
```

<Tip>
  API Reference: [Delete match rule](/en/reference/products/matcher/delete-match-rule)
</Tip>

## Best practices

***

<AccordionGroup>
  <Accordion title="Start strict, then loosen">
    Lead with exact rules. Add tolerance rules only for the variance you can justify and explain.
  </Accordion>

  <Accordion title="Leave room in priorities">
    Use gaps (1, 10, 20, 50) so you can insert rules without renumbering your entire set.
  </Accordion>

  <Accordion title="Dry-run every change">
    Treat rule updates as production changes. Validate match rates and exception volume before committing.
  </Accordion>

  <Accordion title="Write descriptions that explain intent">
    A rule should document the variance it covers and the risk it introduces.
  </Accordion>

  <Accordion title="Review rule output over time">
    If a rule never matches, it may be unnecessary. If it matches too often, it may be too broad.
  </Accordion>

  <Accordion title="Keep loose rules at low priority">
    High tolerance increases false positives. Use it as a fallback and review results carefully.
  </Accordion>
</AccordionGroup>

## Next steps

***

<Card title="Exception routing" icon="route" href="/en/products/matcher/configuration/matcher-exception-routing" horizontal>
  Configure classification, assignment, and escalation for unmatched transactions.
</Card>

<Card title="Confidence scoring" icon="chart-simple" href="/en/products/matcher/reference/matcher-confidence-scoring" horizontal>
  Understand how scores are calculated and how thresholds impact automation.
</Card>
