> ## 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 — how strict or forgiving Matcher should be when deciding 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.
* The first rule that produces a match determines the outcome.
* If no rule matches, the transaction becomes an exception.

This approach ensures deterministic matching while allowing progressively looser rules as fallbacks.

## 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, while keeping the financial gate (amount, currency, date) exact. 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 amount, currency, and date 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** — does not change the calculated confidence score (see note below)
</ParamField>

<ParamField path="matchBaseScore" type="Integer" default="90">
  Accepted and validated, but **reserved/inert** — 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/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/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" default="0.005">
  Maximum percentage variance allowed (0.005 = 0.5%)
</ParamField>

<ParamField path="absTolerance" type="Decimal" default="0.50">
  Maximum absolute amount variance allowed
</ParamField>

<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">
  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** — does not change the calculated confidence score
</ParamField>

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

**Example:**

* Transaction A: \$1,000.00
* Transaction B: \$1,005.00
* Variance: 0.5% → **Matches** (within 0.5% tolerance and \$0.50 absolute tolerance)

### 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">
  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="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">
  Nominal score ceiling (the graded similarity scorer drives the actual confidence)
</ParamField>

<Note>
  FUZZY relaxes only the reference comparison (equality becomes similarity); the amount, currency, and date gate exactly as in an EXACT rule. Because it proposes rather than auto-confirms, its matches always land below the auto-confirm threshold for human review.
</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** — 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/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 shows potential matches without persisting results.

## 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/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/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/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/matcher/configuration/matcher-exception-routing" horizontal>
  Configure classification, assignment, and escalation for unmatched transactions.
</Card>

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