> ## 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.

# Split and aggregate matches

> Reconcile 1:N, N:1, and N:M transaction patterns using context types and rule allocation flags to control how amounts are distributed.

Real-world reconciliation often involves transactions that don't match 1:1. A single payment may cover multiple invoices, or several deposits may consolidate into one bank entry. Matcher handles these complex scenarios through split and aggregate matching.

## Overview

***

Matcher supports four matching patterns:

| Pattern | Description                  | Example                        |
| ------- | ---------------------------- | ------------------------------ |
| **1:1** | One source to one target     | Single invoice payment         |
| **1:N** | One source to many targets   | Bulk payment covering invoices |
| **N:1** | Many sources to one target   | Deposits consolidated at bank  |
| **N:M** | Many sources to many targets | Complex netting                |

## How it works

***

Split and aggregate behavior is controlled by two mechanisms:

1. **Context type** — determines the matching cardinality (`1:1`, `1:N`, or `N:M`).
2. **Rule allocation flags** — control how amounts are distributed within a match group.

There is no separate "split" or "aggregate" setting on the context. The context type defines what patterns are allowed, and the rule config controls allocation behavior.

### Context type mapping

| Context type | Allowed patterns                                                              |
| ------------ | ----------------------------------------------------------------------------- |
| `1:1`        | One source to one target only                                                 |
| `1:N`        | One source to many targets (split), or many sources to one target (aggregate) |
| `N:M`        | Any combination of sources and targets                                        |

### Rule allocation settings

All rule types accept allocation flags in their `config`:

| 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 residuals             |
| `allocationUseBaseAmount`  | Boolean | Use base (converted) amount for allocation               |

### Example: tolerance rule with allocation

```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.01,
     "absTolerance": 5.0,
     "matchCurrency": true,
     "allowPartial": true,
     "allocationDirection": "LEFT_TO_RIGHT",
     "allocationToleranceMode": "ABS",
     "allocationToleranceValue": 10.0,
     "matchScore": 85,
     "matchBaseScore": 80
   }
 }'
```

## Creating a 1:N context

***

To enable split or aggregate matching, create a context with type `1:N`:

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/contexts" \
 -H "Authorization: Bearer $TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
   "name": "Payment Reconciliation",
   "type": "1:N",
   "interval": "daily"
 }'
```

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

## 1:N split matching

***

One source transaction matches multiple target transactions.

### Common use cases

* **Bulk payment**: Single wire covering multiple invoices
* **Payroll**: One bank debit for multiple salary payments
* **Settlement**: One gateway payout for multiple orders

### Example: bulk invoice payment

**Source (Bank Statement):**

| ID        | Amount      | Reference         |
| --------- | ----------- | ----------------- |
| bank\_001 | \$15,000.00 | BULK-PAY-2024-001 |

**Targets (Ledger Entries):**

| ID       | Amount     | Invoice      |
| -------- | ---------- | ------------ |
| inv\_001 | \$5,000.00 | INV-2024-001 |
| inv\_002 | \$7,500.00 | INV-2024-002 |
| inv\_003 | \$2,500.00 | INV-2024-003 |

**Result:** 1:3 match with full allocation

## N:1 aggregate matching

***

Multiple source transactions match one target transaction.

### Common use cases

* **Bank deposits**: Multiple checks deposited as one credit
* **Card settlements**: Daily batch of transactions as one deposit
* **Cash consolidation**: Multiple register receipts to one deposit

### Example: consolidated deposit

**Sources (Point of Sale):**

| ID       | Amount     | Register |
| -------- | ---------- | -------- |
| pos\_001 | \$1,250.00 | REG-01   |
| pos\_002 | \$980.00   | REG-02   |
| pos\_003 | \$1,770.00 | REG-03   |

**Target (Bank Statement):**

| ID        | Amount     | Reference        |
| --------- | ---------- | ---------------- |
| bank\_002 | \$4,000.00 | DEPOSIT-20240120 |

**Result:** 3:1 match with full allocation

## N:M many-to-many matching

***

Multiple source transactions match multiple target transactions. This is the most complex pattern.

### Common use cases

* **Intercompany netting**: Multiple invoices netted against multiple payments
* **Trade settlements**: Complex clearing with partial fills
* **Revenue recognition**: Multiple deliveries against multiple advances

### Example: intercompany netting

**Sources (Company A Payables):**

| ID       | Amount      | Reference  |
| -------- | ----------- | ---------- |
| pay\_001 | \$10,000.00 | IC-PAY-001 |
| pay\_002 | \$8,000.00  | IC-PAY-002 |

**Targets (Company A Receivables):**

| ID       | Amount      | Reference  |
| -------- | ----------- | ---------- |
| rec\_001 | \$12,000.00 | IC-REC-001 |
| rec\_002 | \$6,000.00  | IC-REC-002 |

**Result:** 2:2 match, \$18,000 total matched

To enable N:M matching, create a context with type `N:M`:

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/contexts" \
 -H "Authorization: Bearer $TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
   "name": "Intercompany Netting",
   "type": "N:M",
   "interval": "weekly"
 }'
```

## Running and reviewing matches

***

After configuring the context and rules, trigger a matching run and review the resulting groups.

### Run matching

```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"
 }'
```

### View match run history

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

### View match groups

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

### View group details

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

### Confirm a match group

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/matching/groups/{groupId}/confirm" \
 -H "Authorization: Bearer $TOKEN"
```

### Reject a match group

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/matching/groups/{groupId}/reject" \
 -H "Authorization: Bearer $TOKEN"
```

### Revoke a confirmed match group

```bash cURL theme={null}
curl -X POST "https://api.matcher.example.com/v1/matching/groups/{groupId}/revoke" \
 -H "Authorization: Bearer $TOKEN"
```

## Matching algorithm

***

For N:M scenarios, Matcher uses deterministic sequential allocation to pair transactions.

### How it works

1. **Sort**: Transactions are sorted deterministically to ensure reproducible results across runs.
2. **Iterate**: The engine walks through candidates in priority order.
3. **Allocate**: Amounts are distributed according to the `allocationDirection` setting (`LEFT_TO_RIGHT` or `RIGHT_TO_LEFT`).
4. **Track residuals**: Any remaining unallocated amounts are tracked. If `allowPartial` is `true`, partial matches are created; otherwise, unallocated transactions become exceptions.

## Best practices

***

<AccordionGroup>
  <Accordion title="Start with 1:N before N:M">
    Many-to-many matching is complex. Start with simpler patterns and enable N:M only when necessary.
  </Accordion>

  <Accordion title="Use allocation tolerance for rounding">
    Small rounding differences are common in split payments. Set allocationToleranceValue to a few cents to avoid false exceptions.
  </Accordion>

  <Accordion title="Enable partial allocation deliberately">
    Only set allowPartial to true when partial matches are expected. This prevents false matches from incomplete data.
  </Accordion>

  <Accordion title="Dry-run before committing">
    Always test split and aggregate matching in DRY\_RUN mode first to verify allocation results.
  </Accordion>

  <Accordion title="Monitor residuals">
    Track residual amounts over time. Growing residuals may indicate systematic matching issues.
  </Accordion>
</AccordionGroup>

## Next steps

***

<CardGroup cols={2}>
  <Card title="Match Rules" icon="scale-balanced" href="/en/matcher/configuration/matcher-match-rules">
    Configure rules and allocation settings.
  </Card>

  <Card title="Security" icon="shield-halved" href="/en/matcher/reference/matcher-security">
    Security and access control.
  </Card>
</CardGroup>
