Product · Generate

Clean JSON in. Bank-accepted ISO 20022 out.

The outbound side of the engine builds pain.001 (SEPA credit transfer), pain.008 (SEPA direct debit), and the Swiss QR-bill (SPC v0200). Deterministic, byte-identical XML — no LLM in the request path — with structured-address enforcement for the Nov 14, 2026 mandate, deterministic-MsgId idempotency, and XSD subset validation that hard-fails on a content-model violation.

Outbound builders

Three document families. One emission contract.

Every builder takes a structured payload and returns the finished document — same shape, same guarantees across all three. No envelope template hunting, no per-schema glue code.

pain.001 — SEPA credit transfer

pain.001.001.09

JSON payment payload in, XSD-valid credit-transfer initiation out. Structured debtor/creditor addresses enforced for the Nov 14, 2026 mandate. CH (?profile=ch.03) and CGI-MP variants supported.

SEPA SCTCGI-MP v3ch.03 profile

pain.008 — SEPA direct debit

pain.008.001.02

CORE and B2B direct debit with mandate metadata enforcement and FRST / RCUR / OOFF / FNAL sequence-type grouping. Same deterministic emission contract as pain.001.

COREB2Bmandate

Swiss QR-bill

SPC v0200

The full 31-line SPC v0200 payload, capped at 997 bytes, with mod-97 IBAN, mod-10 QRR (Lührmann) and QR-IBAN range checks. Renders to PDF / SVG / PNG bytes or the raw payload string.

SPC 0200QRRSCOR

What the engine guarantees

Deterministic, idempotent, and hard-failing by design.

Byte-identical, deterministic XML

No LLM in the request path. The same payload renders the same bytes every time — element order, namespace prefixes, and whitespace are fixed. Diff two emissions and the only delta is the data you changed. That is what makes the output auditable and CI-stable.

Structured-address enforcement

Every debtor and creditor party is linted for the five structured fields — <StrtNm>, <BldgNb>, <PstCd>, <TwnNm>, <Ctry> — required when the SWIFT MX/CBPR+ mandate enforces on Nov 14, 2026. A fully-unstructured <AdrLine> is rejected at build; a hybrid (town + country) survives the post-deadline cutover.

Idempotency via deterministic MsgId

The MsgId is derived deterministically from the payload, so re-POSTing the same payment never produces a second wire. The same request is the same document — safe to retry on a timeout without a duplicate-payment risk.

XSD subset content-model validation

Output is validated against the XSD subset content model before it leaves the engine. A content-model violation hard-fails the build with the offending XPath — you never receive a structurally-invalid file that the bank would silently reject downstream.

Request → response

POST a payment. Receive an XSD-valid pain.001.

A structured payload in, a structured-address-compliant pain.001.001.09 back. The MsgId is deterministic, so the same request is idempotent — retry-safe on a timeout, with no duplicate wire.

RequestPOST /v1/iso20022/pain.001
Authorization: Bearer iso_live_9f3c…
Content-Type: application/json

{
  "debtor": {
    "name": "ACME Payroll AG",
    "iban": "CH4431999123000889012",
    "postal_address": {
      "street_name": "Bahnhofstrasse",
      "building_number": "12",
      "post_code": "8001",
      "town_name": "Zurich",
      "country": "CH"
    }
  },
  "creditor": {
    "name": "Anna Müller",
    "iban": "CH5604835012345678009",
    "postal_address": {
      "street_name": "Rue du Marché",
      "building_number": "7",
      "post_code": "1204",
      "town_name": "Geneve",
      "country": "CH"
    }
  },
  "amount": "4250.00",
  "currency": "CHF",
  "end_to_end_id": "INV-2026-06-001"
}
HTTP 200 · ACCEPTEDXSD subset ✓
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09">
  <CstmrCdtTrfInitn>
    <GrpHdr>
      <MsgId>MID-20260603-9f2c1a0db48e</MsgId>
      <CreDtTm>2026-06-03T08:15:00</CreDtTm>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>4250.00</CtrlSum>
      <InitgPty><Nm>ACME Payroll AG</Nm></InitgPty>
    </GrpHdr>
    <PmtInf>
      <Cdtr>
        <Nm>Anna Müller</Nm>
        <PstlAdr>
          <StrtNm>Rue du Marché</StrtNm>
          <BldgNb>7</BldgNb>
          <PstCd>1204</PstCd>
          <TwnNm>Geneve</TwnNm>
          <Ctry>CH</Ctry>
        </PstlAdr>
      </Cdtr>
      <!-- … -->
    </PmtInf>
  </CstmrCdtTrfInitn>
</Document>

The MsgId is derived deterministically from the payload — re-POST the identical body and you get the identical document, never a second payment. Full field-level reference, the same call in curl / TypeScript / Python, and the pain.008 + QR-bill shapes live on the REST API page.

Pricing

Priced per document. Never a transaction percentage.

You pay for the file we generate, not a slice of the money that moves through it. A €2,000,000 pain.001 and a €20 pain.001 cost the same to build — because the work is the same. The engine never touches the rail, the settlement, or the money itself; you keep your existing corporate bank relationships (EBICS / SFTP / API) and use iso-compliant purely to produce the file.

The unit of value

Not the API call. The demonstrable probability that the file is accepted at the customer's bank on the first attempt — backed by the XSD subset content model and the structured-address linter that run before the document ever leaves the engine.

Ship the mandate, this quarter

Five minutes to your first byte-identical pain.001.

Point your existing SDK at api.iso-compliant.com and emit a mandate-compliant pain.001, pain.008, or QR-bill today. Sandbox iso_test_ keys for CI, live iso_live_ keys for production.