Product · Reconcile · The durable moat

Every bank statement, keyed back to your invoice ID.

Parse a camt.053 / camt.054 statement and the engine keys each booking back to the customer's invoice or order ID. The catch: which field a bank echoes that key in never standardises. It hides in any one of six carrier fields, and which carrier wins varies per bank, per rail, sometimes per channel. Re-ranking those carriers per documented bank behaviour is the part only field experience builds — and it is the durable layer of this product.

The reconciliation path

Four steps from statement to matched invoice.

01

Parse the statement

camt.053 / camt.054 XML in. Each <Ntry> / <TxDtls> is projected to amount, currency, CRDT/DBIT, and the raw entry for the dashboard.

02

Extract candidate keys

Walk all six carrier fields, emit one candidate per non-empty carrier, each tagged high / medium / low confidence.

03

Re-rank per bank

The per-bank dialect handler re-orders the candidates to match how that specific bank actually echoes the key on that rail.

04

Match to your payment

The matching engine walks the ranked list against your expected payments. A confident hit reconciles; anything ambiguous routes to HITL.

The six carrier fields

Where the key hides — and how confident each one is.

A reconciliation key (your internal invoice / order id) is echoed back in any one of these six carriers inside a camt.053 <TxDtls> block. There is no standard for which one — so the extractor reads all six.

CarrierXML pathConfidenceNote
EndToEndIdTxDtls/Refs/EndToEndIdhighPrimary ISO 20022 key. Placeholder values (NOTPROVIDED, UNSTRUCTURED, NULL) are treated as absent.
InstrIdTxDtls/Refs/InstrIdmediumInstruction id — sometimes a bank counter, sometimes a duplicate of EndToEndId.
StrdCdtrRefTxDtls/RmtInf/Strd/CdtrRefInf/RefhighStructured creditor reference — where Swiss QR-bill QRR and SCOR ISO-11649 references land.
UstrdTxDtls/RmtInf/Ustrdhigh / mediumFree-text remittance. A regex extracts INV-2026-001234 / ORD20260603_42 style keys; embedded matches drop to medium and keep the raw context.
AcctSvcrRefTxDtls/Refs/AcctSvcrReflowPrimarily the bank's own booking reference; only occasionally correlated to the originator.
SplmtryDataTxDtls/…/SplmtryDatamediumBank-specific extension envelopes. When a bank populates this, it is usually meaningful.

Per-bank dialect handlers

Five banks, five re-ranking rules.

Each handler consumes the candidate list and re-orders it to match how that specific bank populates the carrier on a given rail — the part that never appears in a generic ISO 20022 parser.

UBS Switzerland AG

SEPA SCT · Swiss QR-bill

CHF QR-bill bookings boost StrdCdtrRef (QRR / SCOR); EUR SEPA SCT boosts EndToEndId.

UBS camt.053 Customer IG + Swiss Payment Standards (public).

PostFinance AG

All inbound CRDT

StrdCdtrRef is the canonical key for every inbound credit booking; EndToEndId is secondary.

PostFinance ISO 20022 message catalog (public).

Deutsche Bank AG

SEPA SCT · SDD-return

EUR PMNT/RCDT bookings boost EndToEndId; StrdCdtrRef stays secondary (no DE QR-bill equivalent).

DB camt.053 Customer IG + EBA STEP2 / EPC rulebooks (public).

BNP Paribas

SEPA SCT (French CSM)

EUR SEPA SCT inbound boosts EndToEndId; CFONB overlay does not prescribe a different carrier.

BNP Connexis Cash docs + CFONB ISO 20022 guides (public).

ING Bank N.V.

SEPA SCT · SDD-return

EUR inbound boosts EndToEndId; AcctSvcrRef is explicitly demoted — the IG flags it as bank-internal.

ING camt.053 IG + Betaalvereniging Nederland guidelines (public).

Rejections + safety

Classify the reject. Never blind-retry a wire.

pain.002 rejection classification

When a payment is rejected, the pain.002 status report is parsed and each RJCT reason code is classified into one of three dispositions:

  • Auto-retry. Mechanical, correctable faults (e.g. AC01 / AC03 / BE05) become a corrected retry payload.
  • HITL. Ambiguous or account-state codes (AC04 / AM05 / XT* extended / timeouts) route to a human-approval queue.
  • Final. Terminal rejections are surfaced as such — no retry is attempted.
Full pain.002 reason-code reference →

HITL safety — no duplicate wires

The engine never blind-retries on a non-RJCT response. An unmatched inbound entry, or a rejection that isn't provably safe to retry, is routed to a human-in-the-loop queue rather than re-fired automatically. The default bias is to stop and ask — a missed match is an inconvenience, a duplicate wire is a real loss.

Unmatched entry — routed to HITL

{
  "code": "UNMATCHED_ENTRY",
  "disposition": "hitl",
  "reason": "EndToEndId not matched in 90d window"
}

The honest version of the moat

A real-code edge that compounds — but only with field experience.

The per-bank quirk catalog is real, shipped code today — five handlers re-ranking six carriers on documented behaviour. That is the durable layer: as more statements flow through and as fixtures get UAT-attested against each bank, the catalog deepens in a way a generic parser can't copy.

We will not overstate it. The handlers are derived from public implementation guides, re-rank only, and carry zero bank attestation. The UAT-attested fixtures that turn this from “public-IG heuristic” into a measured, bank-confirmed catalog are prospective — they accrue with field experience. We publish where we stand on /trust and the evidence on /proofs.

What is real today vs prospective

  • REALFive per-bank handlers re-ranking six carriers; the candidate-key extractor; pain.002 classification; HITL routing.
  • SOONUAT-attested, bank-confirmed fixtures that upgrade each handler from public-IG heuristic to measured behaviour — accrued with field experience.
camt.053 field reference →

Reconcile inbound, keyed to your books

Parse a camt.053 today. See the matches.

POST a statement to /v1/iso20022/camt.053/parse and get reconciled line items with the carrier key preserved. Per-document pricing — never a transaction percentage.