Kolos Hetyéssy Software developer

Free tools / SEPA & NACHA Payment File API

Convert a free-text address to an ISO 20022 structured address

Type one postal address below. You get the ISO 20022 structured address (street, building number, postal code, town, country) as SEPA and Swift payments expect it, or a hybrid address when only the town and country are certain.

  • Free, no sign-up
  • Your file is never stored
  • Deterministic: no AI guesswork

Try it now

The demo uses the same rules as the API. Your text is read in memory and discarded right after. Please use a company or test address, not a private person's.

The live demo needs JavaScript, which seems to be switched off. The sample tabs show the engine's real output without it.

A pain.001.001.09 credit transfer generated by the API: structured addresses, one invoice reference and one RF creditor reference. Every check passes.

pain001-v09-valid.xml 1469 bytes · pain.001.001.09

Input file

<?xml version="1.0" ?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09">
  <CstmrCdtTrfInitn>
    <GrpHdr>
      <MsgId>PAYRUN-2026-10-23</MsgId>
      <CreDtTm>2026-10-21T09:00:00</CreDtTm>
      <NbOfTxs>2</NbOfTxs>
      <CtrlSum>1284.06</CtrlSum>
      <InitgPty>
        <Nm>Acme GmbH</Nm>
      </InitgPty>
    </GrpHdr>
    <PmtInf>
      <PmtInfId>PAYRUN-2026-10-23-1</PmtInfId>
      <PmtMtd>TRF</PmtMtd>
      <NbOfTxs>2</NbOfTxs>
      <CtrlSum>1284.06</CtrlSum>
      <PmtTpInf>
        <SvcLvl>
          <Cd>SEPA</Cd>
        </SvcLvl>
      </PmtTpInf>
      <ReqdExctnDt>
        <Dt>2026-10-23</Dt>
      </ReqdExctnDt>
      <Dbtr>
        <Nm>Acme GmbH</Nm>
        <PstlAdr>
          <TwnNm>Berlin</TwnNm>
          <Ctry>DE</Ctry>
        </PstlAdr>
      </Dbtr>
      <DbtrAcct>
        <Id>
          <IBAN>DE89370400440532013000</IBAN>
        </Id>
      </DbtrAcct>
      <DbtrAgt>
        <FinInstnId>
          <BICFI>COBADEFFXXX</BICFI>
        </FinInstnId>
      </DbtrAgt>
      <ChrgBr>SLEV</ChrgBr>
      <CdtTrfTxInf>
        <PmtId>
          <EndToEndId>INV-2026-17</EndToEndId>
        </PmtId>
        <Amt>
          <InstdAmt Ccy="EUR">1234.56</InstdAmt>
        </Amt>
        <Cdtr>
          <Nm>Supplier BV</Nm>
          <PstlAdr>
            <TwnNm>Amsterdam</TwnNm>
            <Ctry>NL</Ctry>
          </PstlAdr>
        </Cdtr>
        <CdtrAcct>
          <Id>
            <IBAN>NL91ABNA0417164300</IBAN>
          </Id>
        </CdtrAcct>
        <RmtInf>
          <Ustrd>Invoice 2026-17</Ustrd>
        </RmtInf>
      </CdtTrfTxInf>
      <CdtTrfTxInf>
        <PmtId>
          <EndToEndId>NOTPROVIDED</EndToEndId>
        </PmtId>
        <Amt>
          <InstdAmt Ccy="EUR">49.50</InstdAmt>
        </Amt>
        <Cdtr>
          <Nm>Office Supplies KG</Nm>
        </Cdtr>
        <CdtrAcct>
          <Id>
            <IBAN>DE02120300000000202051</IBAN>
          </Id>
        </CdtrAcct>
        <RmtInf>
          <Strd>
            <CdtrRefInf>
              <Tp>
                <CdOrPrtry>
                  <Cd>SCOR</Cd>
                </CdOrPrtry>
              </Tp>
              <Ref>RF18539007547034</Ref>
            </CdtrRefInf>
          </Strd>
        </RmtInf>
      </CdtTrfTxInf>
    </PmtInf>
  </CstmrCdtTrfInitn>
</Document>

Validation result

VALID 0 errors · 0 warnings

PAYRUN-2026-10-23
pain.001.001.09
Payment blocks
1
Transactions
2
Total
1284.06 EUR

No problems found. Schema, SEPA character set, totals, IBANs, addresses and references all pass.

JSON response POST /v1/validate
{
  "message_type": "pain.001.001.09",
  "kind": "credit_transfer",
  "profile": "epc",
  "valid": true,
  "error_count": 0,
  "warning_count": 0,
  "summary": {
    "message_id": "PAYRUN-2026-10-23",
    "payment_blocks": 1,
    "transactions": 2,
    "total_amount": "1284.06",
    "currency": "EUR"
  },
  "issues": []
}

A 2009 pain.001.001.03 file whose header control sum has two digits swapped. A German bank may reject the whole file for this.

pain001-v03-wrong-total.xml 1815 bytes · pain.001.001.03

Input file

<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
  <CstmrCdtTrfInitn>
    <GrpHdr>
      <MsgId>OLD-2026-10-20-1</MsgId>
      <CreDtTm>2026-10-20T10:00:00</CreDtTm>
      <NbOfTxs>2</NbOfTxs>
      <CtrlSum>1248.06</CtrlSum>
      <InitgPty>
        <Nm>Acme GmbH</Nm>
        <Id><OrgId><BICOrBEI>COBADEFFXXX</BICOrBEI></OrgId></Id>
      </InitgPty>
    </GrpHdr>
    <PmtInf>
      <PmtInfId>OLD-2026-10-20-1-P1</PmtInfId>
      <PmtMtd>TRF</PmtMtd>
      <BtchBookg>true</BtchBookg>
      <NbOfTxs>2</NbOfTxs>
      <CtrlSum>1284.06</CtrlSum>
      <PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf>
      <ReqdExctnDt>2026-10-23</ReqdExctnDt>
      <Dbtr>
        <Nm>Acme GmbH</Nm>
        <PstlAdr><Ctry>DE</Ctry><AdrLine>Hauptstr. 1</AdrLine><AdrLine>10115 Berlin</AdrLine></PstlAdr>
      </Dbtr>
      <DbtrAcct><Id><IBAN>DE89370400440532013000</IBAN></Id></DbtrAcct>
      <DbtrAgt><FinInstnId><BIC>COBADEFFXXX</BIC></FinInstnId></DbtrAgt>
      <ChrgBr>SLEV</ChrgBr>
      <CdtTrfTxInf>
        <PmtId><EndToEndId>INV-2026-17</EndToEndId></PmtId>
        <Amt><InstdAmt Ccy="EUR">1234.56</InstdAmt></Amt>
        <CdtrAgt><FinInstnId><BIC>INGBNL2A</BIC></FinInstnId></CdtrAgt>
        <Cdtr><Nm>Supplier BV</Nm></Cdtr>
        <CdtrAcct><Id><IBAN>NL91ABNA0417164300</IBAN></Id></CdtrAcct>
        <RmtInf><Ustrd>Invoice 2026-17</Ustrd></RmtInf>
      </CdtTrfTxInf>
      <CdtTrfTxInf>
        <PmtId><EndToEndId>NOTPROVIDED</EndToEndId></PmtId>
        <Amt><InstdAmt Ccy="EUR">49.50</InstdAmt></Amt>
        <Cdtr><Nm>Office Supplies KG</Nm></Cdtr>
        <CdtrAcct><Id><IBAN>DE02120300000000202051</IBAN></Id></CdtrAcct>
        <RmtInf><Ustrd>Order 5521</Ustrd></RmtInf>
      </CdtTrfTxInf>
    </PmtInf>
  </CstmrCdtTrfInitn>
</Document>

Validation result

INVALID 1 error · 1 warning

OLD-2026-10-20-1
pain.001.001.03
Payment blocks
1
Transactions
2
Total
1284.06 EUR

ERROR · CONTROL_SUM GrpHdr/CtrlSum The message control sum is 1248.06; the amounts add up to 1284.06.

WARNING · OLD_VERSION pain.001.001.03 is the 2009 version. Banks are moving to the 2019 versions (pain.001.001.09 / pain.008.001.08); German banks' specification limited the old version to November 2025. Use /v1/convert to migrate the file.

JSON response POST /v1/validate
{
  "message_type": "pain.001.001.03",
  "kind": "credit_transfer",
  "profile": "epc",
  "valid": false,
  "error_count": 1,
  "warning_count": 1,
  "summary": {
    "message_id": "OLD-2026-10-20-1",
    "payment_blocks": 1,
    "transactions": 2,
    "total_amount": "1284.06",
    "currency": "EUR"
  },
  "issues": [
    {
      "severity": "error",
      "rule": "CONTROL_SUM",
      "path": "GrpHdr/CtrlSum",
      "message": "The message control sum is 1248.06; the amounts add up to 1284.06."
    },
    {
      "severity": "warning",
      "rule": "OLD_VERSION",
      "path": "",
      "message": "pain.001.001.03 is the 2009 version. Banks are moving to the 2019 versions (pain.001.001.09 / pain.008.001.08); German banks' specification limited the old version to November 2025. Use /v1/convert to migrate the file."
    }
  ]
}

A pain.008.001.02 direct debit with a mistyped creditor identifier and a mandate dated in the future.

pain008-v02-errors.xml 1663 bytes · pain.008.001.02

Input file

<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02">
  <CstmrDrctDbtInitn>
    <GrpHdr>
      <MsgId>DD-2026-10-20-1</MsgId>
      <CreDtTm>2026-10-20T10:00:00</CreDtTm>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>25.00</CtrlSum>
      <InitgPty><Nm>Sportverein Musterstadt e.V.</Nm></InitgPty>
    </GrpHdr>
    <PmtInf>
      <PmtInfId>DD-2026-10-20-1-RCUR</PmtInfId>
      <PmtMtd>DD</PmtMtd>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>25.00</CtrlSum>
      <PmtTpInf>
        <SvcLvl><Cd>SEPA</Cd></SvcLvl>
        <LclInstrm><Cd>CORE</Cd></LclInstrm>
        <SeqTp>RCUR</SeqTp>
      </PmtTpInf>
      <ReqdColltnDt>2026-11-02</ReqdColltnDt>
      <Cdtr><Nm>Sportverein Musterstadt e.V.</Nm></Cdtr>
      <CdtrAcct><Id><IBAN>DE89370400440532013000</IBAN></Id></CdtrAcct>
      <CdtrAgt><FinInstnId><BIC>COBADEFFXXX</BIC></FinInstnId></CdtrAgt>
      <ChrgBr>SLEV</ChrgBr>
      <CdtrSchmeId>
        <Id><PrvtId><Othr><Id>DE98ZZZ09999999990</Id><SchmeNm><Prtry>SEPA</Prtry></SchmeNm></Othr></PrvtId></Id>
      </CdtrSchmeId>
      <DrctDbtTxInf>
        <PmtId><EndToEndId>MEMBER-0001-2026-11</EndToEndId></PmtId>
        <InstdAmt Ccy="EUR">25.00</InstdAmt>
        <DrctDbtTx><MndtRltdInf><MndtId>M-001</MndtId><DtOfSgntr>2026-12-01</DtOfSgntr></MndtRltdInf></DrctDbtTx>
        <DbtrAgt><FinInstnId><Othr><Id>NOTPROVIDED</Id></Othr></FinInstnId></DbtrAgt>
        <Dbtr><Nm>Anna Schmidt</Nm></Dbtr>
        <DbtrAcct><Id><IBAN>DE02120300000000202051</IBAN></Id></DbtrAcct>
        <RmtInf><Ustrd>Membership November</Ustrd></RmtInf>
      </DrctDbtTxInf>
    </PmtInf>
  </CstmrDrctDbtInitn>
</Document>

Validation result

INVALID 2 errors · 1 warning

DD-2026-10-20-1
pain.008.001.02
Payment blocks
1
Transactions
1
Total
25.00 EUR

ERROR · CREDITOR_ID PmtInf[1]/CdtrSchmeId/Id/PrvtId/Othr/Id 'DE98ZZZ09999999990' is not a valid SEPA creditor identifier.

ERROR · MANDATE_DATE PmtInf[1]/DrctDbtTxInf[1]/DrctDbtTx/MndtRltdInf/DtOfSgntr The mandate signature date is in the future.

WARNING · OLD_VERSION pain.008.001.02 is the 2009 version. Banks are moving to the 2019 versions (pain.001.001.09 / pain.008.001.08); German banks' specification limited the old version to November 2025. Use /v1/convert to migrate the file.

JSON response POST /v1/validate
{
  "message_type": "pain.008.001.02",
  "kind": "direct_debit",
  "profile": "epc",
  "valid": false,
  "error_count": 2,
  "warning_count": 1,
  "summary": {
    "message_id": "DD-2026-10-20-1",
    "payment_blocks": 1,
    "transactions": 1,
    "total_amount": "25.00",
    "currency": "EUR"
  },
  "issues": [
    {
      "severity": "error",
      "rule": "CREDITOR_ID",
      "path": "PmtInf[1]/CdtrSchmeId/Id/PrvtId/Othr/Id",
      "message": "'DE98ZZZ09999999990' is not a valid SEPA creditor identifier."
    },
    {
      "severity": "error",
      "rule": "MANDATE_DATE",
      "path": "PmtInf[1]/DrctDbtTxInf[1]/DrctDbtTx/MndtRltdInf/DtOfSgntr",
      "message": "The mandate signature date is in the future."
    },
    {
      "severity": "warning",
      "rule": "OLD_VERSION",
      "path": "",
      "message": "pain.008.001.02 is the 2009 version. Banks are moving to the 2019 versions (pain.001.001.09 / pain.008.001.08); German banks' specification limited the old version to November 2025. Use /v1/convert to migrate the file."
    }
  ]
}

How it works

  1. Copy an address from your vendor or customer list, the way it is stored: one line, or several lines separated by commas.
  2. Add the two-letter country code, unless the address already ends with the country.
  3. Read the result: every ISO 20022 element with its value, the form (structured or hybrid) and the confidence. Unclear addresses are marked for review instead of guessed.

The rules

Form TwnNm + Ctry Other structured elements AdrLine
Structured required as many as available not allowed
Hybrid required allowed 1–2 lines, 70 characters each, not repeating the structured parts
Unstructured – only Ctry 1–2 lines; postponed end date, see above

Lengths from the ISO 20022 schema: TwnNm 35, StrtNm 70, BldgNb 16, PstCd 16, PstBx 16, AdrLine 70. Sources: EPC guidance document EPC153-22 v2.0, the EPC SEPA credit transfer customer-to-PSP implementation guidelines 2025 (address of the originator and of the beneficiary), and the EPC announcement of 10 September 2026.

Result Meaning In file mode
structured, high every part found its element, the postal code matches the country’s format applied
hybrid, medium town, country and postal code are certain; the rest (flat, floor, c/o …) stays in an address line applied
review, low no postal code, two possible towns, a field too long, or an unknown country left as it is, listed for manual review

Questions

When do SEPA payments need structured addresses?

The EPC planned to stop accepting unstructured addresses (address lines only) on 15 November 2026. On 9 September 2026 it postponed that date; the new one is not set yet. Swift postponed its November 2026 date for cross-border payments on 27 August 2026 and expects to announce more by December 2026. Structured and hybrid addresses are accepted today, and the hybrid form has no end date.

What is a hybrid address?

Town (TwnNm) and country (Ctry) in their own fields, plus one or two free-text address lines of up to 70 characters. Whatever is available in structured form must go into the structured elements and must not be repeated in the lines (EPC guidance EPC153-22).

Which countries are supported?

Austria, Belgium, Croatia, the Czech Republic, Denmark, Finland, France, Germany, Hungary, Ireland, Italy, Liechtenstein, Luxembourg, Monaco, the Netherlands, Norway, Poland, Portugal, Romania, Slovakia, Slovenia, Spain, Sweden, Switzerland, the United Kingdom and the United States. Other countries are always marked for review.

Does it check that the address exists?

No. It checks the format and the order (postal code pattern, street before or after the number, where the town stands). It has no postal database, so a postal code that does not belong to the town is not noticed.

Can it fix a whole payment file or vendor list?

Yes, through the API: fix-file rewrites the payer and payee addresses of a pain.001 or pain.008 and returns a change report, and parse-csv adds the structured columns and a status to every row of a CSV.

Need it in your own software?

The same engine is available as an API: whole files instead of a preview, every export format, automation.

SEPA & NACHA Payment File API →

Related tools

Free toolSEPA & NACHA Payment File API

pain.001 validator

Check a pain.001 or pain.008 file against the ISO 20022 schema and the EPC rules, with every problem explained.

Free toolSEPA & NACHA Payment File API

pain.001.001.03 to .09

Migrate 2009 SEPA files to the 2019 versions, checked against the new schema and the SEPA rules.

Free toolSEPA & NACHA Payment File API

NACHA file validator

Check a NACHA ACH file record by record, with each problem's line, column and a plain explanation.