Get Matcher running in minutes. This guide walks you through the complete journey, from creating your first reconciliation context to reviewing matched transactions.
Before you begin
You need:
- A running Matcher instance
- A valid JWT token for authentication
- Two transaction files to reconcile (CSV, JSON, or XML)
All examples use cURL. Replace $TOKEN with your JWT token and https://api.matcher.example.com with your Matcher URL.
Step 1: Create a reconciliation context
A context defines the scope of your reconciliation: what you are comparing and how.
curl -X POST "https://api.matcher.example.com/v1/config/contexts" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Daily Bank Reconciliation",
"type": "1:1",
"interval": "daily"
}'
The type field defines how transactions are paired:
| Type | Description |
|---|
1:1 | Each transaction matches exactly one counterpart |
1:N | One transaction can match multiple counterparts |
N:M | Multiple transactions can match across both sides |
Save the id from the response. You will use it in every subsequent step.
{
"id": "019c96a0-2a10-7dfe-b5c1-8a1b2c3d4e5f",
"name": "Daily Bank Reconciliation",
"type": "1:1",
"interval": "daily",
"status": "DRAFT",
"createdAt": "2026-03-04T12:00:00Z",
"updatedAt": "2026-03-04T12:00:00Z"
}
The context starts in DRAFT status. It moves to ACTIVE when you are ready to run reconciliation.
Step 2: Add data sources
Every context needs at least two sources: the systems whose transactions you want to compare.
Create a bank source
curl -X POST "https://api.matcher.example.com/v1/config/contexts/{contextId}/sources" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Chase Bank - Account 1234",
"type": "BANK"
}'
Create a ledger source
curl -X POST "https://api.matcher.example.com/v1/config/contexts/{contextId}/sources" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "General Ledger - GL 1000",
"type": "LEDGER"
}'
Save both source id values.
Source types
| Type | Use case |
|---|
BANK | Bank statements |
LEDGER | General ledger / ERP exports |
GATEWAY | Payment processor data |
CUSTOM | Any other data source |
Step 3: Map source fields
Your source files probably use different column names than Matcher expects. Field maps translate them into Matcher’s standard schema.
Map the bank source
curl -X POST "https://api.matcher.example.com/v1/config/contexts/{contextId}/sources/{bankSourceId}/field-maps" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mapping": {
"Transaction ID": "transaction_id",
"Amount": "amount",
"Currency": "currency",
"Post Date": "date",
"Description": "reference"
}
}'
Map the ledger source
curl -X POST "https://api.matcher.example.com/v1/config/contexts/{contextId}/sources/{ledgerSourceId}/field-maps" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mapping": {
"entry_id": "transaction_id",
"debit_credit_amount": "amount",
"currency_code": "currency",
"posting_date": "date",
"memo": "reference"
}
}'
Required fields
Every transaction must have these fields after mapping:
| Field | Type | Description |
|---|
transaction_id | String | Unique identifier within the source |
amount | Decimal | Transaction amount |
currency | String | ISO 4217 currency code (e.g. USD) |
date | Date | Transaction date (YYYY-MM-DD) |
Optional but recommended: reference (external reference or description).
Step 4: Create match rules
Rules define how Matcher compares transactions. Start with an exact rule, which is the most precise.
Create an exact rule
curl -X POST "https://api.matcher.example.com/v1/config/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,
"caseInsensitive": true,
"datePrecision": "DAY"
}
}'
Add a tolerance rule as fallback
Catch small differences like bank fees or rounding:
curl -X POST "https://api.matcher.example.com/v1/config/contexts/{contextId}/rules" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "TOLERANCE",
"priority": 10,
"config": {
"percentTolerance": 0.01,
"absTolerance": 5.0,
"dateWindowDays": 2,
"matchCurrency": true,
"matchReference": true,
"caseInsensitive": true
}
}'
Matcher evaluates rules by priority (lowest number first). The exact rule runs first. Only unmatched transactions fall through to the tolerance rule.
Rule types
| Type | When to use | Priority range |
|---|
EXACT | Values should match exactly | 1-10 |
TOLERANCE | Small, expected differences | 11-50 |
DATE_LAG | Date delays between systems | 51-100 |
Step 5: Activate the context
Move the context from DRAFT to ACTIVE:
curl -X PATCH "https://api.matcher.example.com/v1/config/contexts/{contextId}" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "ACTIVE"
}'
Step 6: Upload transaction files
Upload one file per source. Matcher accepts CSV, JSON, and XML formats via multipart form upload.
Upload bank transactions
curl -X POST "https://api.matcher.example.com/v1/imports/contexts/{contextId}/sources/{bankSourceId}/upload" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@bank_transactions.csv" \
-F "format=csv"
Upload ledger transactions
curl -X POST "https://api.matcher.example.com/v1/imports/contexts/{contextId}/sources/{ledgerSourceId}/upload" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@ledger_entries.csv" \
-F "format=csv"
Each upload creates an ingestion job. Check the job status:
curl -X GET "https://api.matcher.example.com/v1/imports/contexts/{contextId}/jobs" \
-H "Authorization: Bearer $TOKEN"
Wait for both jobs to reach COMPLETED status before running the match.
Step 7: Run matching
Start with a dry run to preview results without persisting:
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"
}'
Both responses include a runId. Save it for Step 8.
Review the dry run results. When satisfied, run with COMMIT to persist matches:
curl -X POST "https://api.matcher.example.com/v1/matching/contexts/{contextId}/run" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mode": "COMMIT"
}'
Step 8: Review results
View match groups
curl -X GET "https://api.matcher.example.com/v1/matching/runs/{runId}/groups?contextId={contextId}" \
-H "Authorization: Bearer $TOKEN"
Each match group contains paired transactions and a confidence score (0-100):
| Score | What happens |
|---|
| 90-100 | Auto-confirmed, no action needed |
| 60-89 | Needs manual review |
| Below 60 | No match created, becomes an exception |
Undo an incorrect match
Use the unmatch endpoint to reject a match group and return transactions to the unmatched pool:
curl -X DELETE "https://api.matcher.example.com/v1/matching/groups/{matchGroupId}?contextId={contextId}" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reason": "Transactions belong to different records"
}'
Rejected transactions return to the unmatched pool for the next run.
Step 9: Handle exceptions
Exceptions are transactions that could not be matched automatically. Matcher classifies each exception by severity:
| Severity | Criteria | SLA |
|---|
CRITICAL | Amount >= 100,000 or age >= 120h | 24 hours |
HIGH | Amount >= 10,000 or age >= 72h | 72 hours |
MEDIUM | Amount >= 1,000 or age >= 24h | 5 days |
LOW | All others | 7 days |
List exceptions
curl -X GET "https://api.matcher.example.com/v1/exceptions" \
-H "Authorization: Bearer $TOKEN"
Resolve exceptions by force matching, creating adjustments, or dispatching to external systems like JIRA.
Next steps