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.
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
camt.053 / camt.054 XML in. Each <Ntry> / <TxDtls> is projected to amount, currency, CRDT/DBIT, and the raw entry for the dashboard.
Walk all six carrier fields, emit one candidate per non-empty carrier, each tagged high / medium / low confidence.
The per-bank dialect handler re-orders the candidates to match how that specific bank actually echoes the key on that rail.
The matching engine walks the ranked list against your expected payments. A confident hit reconciles; anything ambiguous routes to HITL.
The six carrier fields
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.
| Carrier | XML path | Confidence | Note |
|---|---|---|---|
| EndToEndId | TxDtls/Refs/EndToEndId | high | Primary ISO 20022 key. Placeholder values (NOTPROVIDED, UNSTRUCTURED, NULL) are treated as absent. |
| InstrId | TxDtls/Refs/InstrId | medium | Instruction id — sometimes a bank counter, sometimes a duplicate of EndToEndId. |
| StrdCdtrRef | TxDtls/RmtInf/Strd/CdtrRefInf/Ref | high | Structured creditor reference — where Swiss QR-bill QRR and SCOR ISO-11649 references land. |
| Ustrd | TxDtls/RmtInf/Ustrd | high / medium | Free-text remittance. A regex extracts INV-2026-001234 / ORD20260603_42 style keys; embedded matches drop to medium and keep the raw context. |
| AcctSvcrRef | TxDtls/Refs/AcctSvcrRef | low | Primarily the bank's own booking reference; only occasionally correlated to the originator. |
| SplmtryData | TxDtls/…/SplmtryData | medium | Bank-specific extension envelopes. When a bank populates this, it is usually meaningful. |
Per-bank dialect handlers
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.
SEPA SCT · Swiss QR-billCHF QR-bill bookings boost StrdCdtrRef (QRR / SCOR); EUR SEPA SCT boosts EndToEndId.
UBS camt.053 Customer IG + Swiss Payment Standards (public).
All inbound CRDTStrdCdtrRef is the canonical key for every inbound credit booking; EndToEndId is secondary.
PostFinance ISO 20022 message catalog (public).
SEPA SCT · SDD-returnEUR PMNT/RCDT bookings boost EndToEndId; StrdCdtrRef stays secondary (no DE QR-bill equivalent).
DB camt.053 Customer IG + EBA STEP2 / EPC rulebooks (public).
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).
SEPA SCT · SDD-returnEUR inbound boosts EndToEndId; AcctSvcrRef is explicitly demoted — the IG flags it as bank-internal.
ING camt.053 IG + Betaalvereniging Nederland guidelines (public).
Rejections + safety
When a payment is rejected, the pain.002 status report is parsed and each RJCT reason code is classified into one of three dispositions:
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
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
Reconcile inbound, keyed to your books
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.