Skip to main content
Matcher exposes two read-only simulation endpoints so you can answer “what would happen?” before you commit configuration: match simulation (will this rule actually match?) and fee simulation (what fees would this schedule charge?). Neither persists anything.

Match simulation


Preview how a single rule — an existing configured rule (ruleId) or an inline candidate rule (rule) — would match a context’s unmatched transactions, without committing anything.
curl -X POST "https://api.matcher.example.com/v1/matching/simulate" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "contextId": "550e8400-e29b-41d4-a716-446655440000",
    "rule": {
      "type": "TOLERANCE",
      "config": { "matchAmount": true, "matchCurrency": true, "tolerance": 0.01 }
    },
    "sampleLimit": 25
  }'
Supply exactly one of:
  • ruleId — preview an existing configured rule of the context.
  • rule — preview an un-persisted candidate definition (type is one of EXACT, TOLERANCE, DATE_LAG, FUZZY, plus its config).
Supplying both, or neither, returns 400. sampleLimit (1–200, default 25) caps the returned would-match pairs. The response reports how many 1:1 groups the rule would form, a bounded sample of would-match pairs (each with a confidence score and per-component rationale), and the per-side unmatched counts:
{
  "ruleType": "TOLERANCE",
  "matchedGroups": 12,
  "unmatchedLeft": 3,
  "unmatchedRight": 5,
  "sampleTruncated": false,
  "sample": [
    {
      "left":  { "id": "...", "amount": "100.00", "currency": "BRL", "date": "2025-06-01T00:00:00Z" },
      "right": { "id": "...", "amount": "100.00", "currency": "BRL", "date": "2025-06-01T00:00:00Z" },
      "score": 90,
      "why": { "amountMatch": true, "currencyMatch": true, "dateMatch": true, "referenceScore": 0 },
      "amountDelta": "0.00",
      "dateDeltaDays": 0
    }
  ]
}
Scope: the simulation scores by the deterministic rule engine over the raw transaction amounts. It does not apply run-time fee normalization or the FX-variance band, and it previews only 1:1 pairwise grouping (no 1:N/N:M allocation). A pair that only matches after fee normalization, inside the FX band, or via allocation is not counted here.

Fee simulation


Calculate fees for a given gross amount using a specific fee schedule. Use it to validate a schedule’s rules before you attach it to a context.
curl -X POST "https://api.matcher.example.com/v1/fee-schedules/{scheduleId}/simulate" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "grossAmount": "100.00", "currency": "USD" }'
The response returns the net amount, the total fee, and a per-item breakdown:
{
  "grossAmount": "100.00",
  "netAmount": "97.70",
  "totalFee": "2.30",
  "currency": "USD",
  "items": [
    { "name": "interchange", "fee": "1.50", "baseUsed": "100.00" }
  ]
}
Fee simulation has no transaction metadata, so expression-fee items that require a transaction identifier surface their missing-identifier error as a 4xx. A missing schedule returns 404.

When to use each


UseWhen
Match simulation (/matching/simulate)You are authoring or reviewing a match rule and want to see how many transactions it would group, and which pairs, before committing it.
Fee simulation (/fee-schedules/{scheduleId}/simulate)You are configuring a fee schedule and want to verify the net/fee breakdown it would produce for a representative gross amount.
Both are strictly read-only: they never persist a run, group, item, rule, or transaction, and the tenant is always taken from the JWT.

Response codes


StatusMeaning
200Simulation returned
400Invalid input (ambiguous/missing rule, invalid ids, invalid gross amount)
404Context, rule, or fee schedule not found
503Match simulation not available