Product · Validate

Catch the malformed field before the bank does.

The validation layer of the engine has three jobs: XSD subset content-model validation that hard-fails on any violation, the structured-address linter for the SWIFT Nov 14, 2026 five-field mandate, and pain.002 reason-code classification. Every rejection carries the offending XPath, the bank-IG section it broke, and the corrected payload — no generic parser exceptions.

What validation covers

Three checks. Every one actionable.

XSD subset content-model validation

Every document is checked against the XSD subset content model. A violation hard-fails with the offending XPath, the IG section it breached, and the corrected payload — never a generic parser exception. A structurally-invalid file never leaves the engine.

A content-model violation is a hard fail, not a warning.

Structured-address linter

The Nov 14, 2026 mandate makes the five structured fields — <StrtNm>, <BldgNb>, <PstCd>, <TwnNm>, <Ctry> — required on cross-border MX. The linter flags a fully-unstructured <AdrLine> as a future reject; a hybrid (town + country) survives the cutover. Run it on every debtor and creditor party.

Five fields. Every party block. Linted before emission.

pain.002 reason-code classification

A rejected payment’s pain.002 status report is parsed and each RJCT reason code is classified — auto-retry-safe, HITL, or final. Never blind-retry on a non-RJCT response; a mechanical AC01 is a corrected retry, an AC04 is a human decision.

Retry-safe vs human-decision vs terminal — classified, not guessed.

Validator

Demo · sample payloads

Catch the malformed field before the bank does.

The same kinds of checks the engine enforces behind POST /v1/iso20022/*, run client-side on these example payloads. Every error carries the offending XPath, the bank-IG section it violated, and the corrected payload. No generic parser exceptions — every rejection is actionable.

Request bodylegacy payload — broken
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09">
  <CstmrCdtTrfInitn>
    <GrpHdr>
      <MsgId>PAY-2026-06-001</MsgId>
      <CreDtTm>2026-06-03T08:15:00</CreDtTm>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>4250.00</CtrlSum>
      <InitgPty>
        <Nm>ACME Payroll AG</Nm>
        <PstlAdr>
          <AdrLine>Bahnhofstrasse 12, 8001 Zürich CH</AdrLine>
        </PstlAdr>
      </InitgPty>
    </GrpHdr>
    <PmtInf>…</PmtInf>
  </CstmrCdtTrfInitn>
</Document>
Validator responseruleset ubs@2026.06
HTTP 400 · STRUCTURED_ADDRESS_REQUIRED

AdrLine is not permitted under InitgPty.PstlAdr per the SWIFT MX/CBPR+ structured-address mandate effective 2026-11-14. Replace with the structured fields below.

xpath/Document/CstmrCdtTrfInitn/GrpHdr/InitgPty/PstlAdr/AdrLine
ig_sectionUBS-CH-PAIN001 §4.2.7 (p.84)
rule_idubs-ch-pain001-structadr-001
severityERROR
POST /v1/iso20022/pain.001

What you just saw

Every error is a fix, not a stack trace.

The validator above runs the same checks that back POST /v1/iso20022/*. The pain.001 tab shows the structured-address linter catching a freeform <AdrLine> that the Nov 14 mandate will reject; the camt.053 tab shows an unmatched entry routed to HITL; every tab carries the XPath, the IG citation, and a one-click corrected payload.

Validate before you submit

Lint a payload now. Ship a clean file.

Point your SDK at api.iso-compliant.com and validate every pain.001, pain.008, camt.053, and QR-bill before it reaches the bank. Per-document pricing — never a transaction percentage.