ISO 20022 explained

What Is pain.001? ISO 20022 Credit Transfer Initiation

The ISO 20022 message a company sends its bank to order credit transfers: what it is, how it is built, which version to use, and a complete example that validates against the official schema.

pain.001 is the ISO 20022 message a company sends its bank to order one or more credit transfers. Its full name is Customer Credit Transfer Initiation: "pain" is the payment initiation message family, .001 is the message number, and the suffix, such as pain.001.001.09, is the version. It is XML, it is validated against an official schema (XSD), and it replaces bank-specific CSV formats and the SWIFT MT101 text message.

pain.001 in one minute#

  • Who sends it: a company (the debtor, or an agent acting for it) sends it to its own bank (the debtor agent).
  • What it carries: one or more batches of credit transfers, each with a debtor account, a requested execution date and any number of payments to creditors.
  • What comes back: the bank answers with pain.002, the Customer Payment Status Report, accepting or rejecting the file or individual transactions with ISO reason codes.
  • What happens next: once accepted, the bank turns each instruction into interbank messages such as pacs.008, which the company never sees.
  • Where it is used: SEPA credit transfers under the EPC rulebooks, cross-border payments on Swift under CBPR+ (pain.001.001.09), and many domestic schemes. Pain001's example corpus covers 42 scenarios across 17 markets.

How a pain.001 message is structured#

Every version shares the same three-level skeleton inside a <CstmrCdtTrfInitn> element.

Level Element What it holds
1 <GrpHdr> Group Header Message ID, creation timestamp, number of transactions (NbOfTxs), control sum (CtrlSum), initiating party
2 <PmtInf> Payment Information One batch: payment method, requested execution date, debtor, debtor account and agent, charge bearer
3 <CdtTrfTxInf> Credit Transfer Transaction One payment: end-to-end reference, amount and currency, creditor, creditor account and agent, remittance information

A file can hold several <PmtInf> batches, and each batch many <CdtTrfTxInf> payments. NbOfTxs and CtrlSum appear at both the file and the batch level and must match the payments they count, which is one of the most common reasons a bank rejects a file.

A complete pain.001 example#

This is a single SEPA credit transfer in pain.001.001.09, taken unchanged from Pain001's example corpus. It validates against the official ISO 20022 XSD. The parties, IBANs and BICs are fictitious.

<?xml version='1.0' encoding='UTF-8'?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09">
  <CstmrCdtTrfInitn>
    <GrpHdr>
      <MsgId>OML-SCT-20260921</MsgId>
      <CreDtTm>2026-09-21T12:00:00</CreDtTm>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>2200.00</CtrlSum>
      <InitgPty>
        <Nm>Officine Meccaniche Lombarde SpA</Nm>
        <PstlAdr>
          <PstCd>20123</PstCd>
          <TwnNm>Milano</TwnNm>
          <Ctry>IT</Ctry>
          <AdrLine>Via Torino 15</AdrLine>
        </PstlAdr>
      </InitgPty>
    </GrpHdr>
    <PmtInf>
      <PmtInfId>SCT-20260921-IT-01</PmtInfId>
      <PmtMtd>TRF</PmtMtd>
      <BtchBookg>false</BtchBookg>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>2200.00</CtrlSum>
      <PmtTpInf>
        <SvcLvl>
          <Cd>SEPA</Cd>
        </SvcLvl>
      </PmtTpInf>
      <ReqdExctnDt>
        <Dt>2026-09-22</Dt>
      </ReqdExctnDt>
      <Dbtr>
        <Nm>Officine Meccaniche Lombarde SpA</Nm>
        <PstlAdr>
          <PstCd>20123</PstCd>
          <TwnNm>Milano</TwnNm>
          <Ctry>IT</Ctry>
          <AdrLine>Via Torino 15</AdrLine>
        </PstlAdr>
      </Dbtr>
      <DbtrAcct>
        <Id>
          <IBAN>IT48T78971134594OGDKY5VXE41</IBAN>
        </Id>
      </DbtrAcct>
      <DbtrAgt>
        <FinInstnId>
          <BICFI>TLAOIT60</BICFI>
        </FinInstnId>
      </DbtrAgt>
      <ChrgBr>SLEV</ChrgBr>
      <CdtTrfTxInf>
        <PmtId>
          <EndToEndId>OML-2026-0921-01</EndToEndId>
        </PmtId>
        <Amt>
          <InstdAmt Ccy="EUR">2200.00</InstdAmt>
        </Amt>
        <CdtrAgt>
          <FinInstnId>
            <BICFI>MHXHITI0</BICFI>
          </FinInstnId>
        </CdtrAgt>
        <Cdtr>
          <Nm>Fonderia Bresciana Srl</Nm>
          <PstlAdr>
            <PstCd>25121</PstCd>
            <TwnNm>Brescia</TwnNm>
            <Ctry>IT</Ctry>
          </PstlAdr>
        </Cdtr>
        <CdtrAcct>
          <Id>
            <IBAN>IT23J14887404856NF3794IGWXN</IBAN>
          </Id>
        </CdtrAcct>
        <RmtInf>
          <Ustrd>Fattura 117/2026</Ustrd>
        </RmtInf>
      </CdtTrfTxInf>
    </PmtInf>
  </CstmrCdtTrfInitn>
</Document>

Try your own data in the browser demo: it builds a pain.001 file from a CSV and validates it against the official schema without the data leaving your machine.

pain.001 versions#

ISO publishes a new version when the message model changes. Banks and schemes each accept particular versions, so the version you send is the one your bank's channel documentation names.

Version Notes
pain.001.001.03 The long-standing SEPA and CGI workhorse; identifies banks with <BIC>
.04, .05, .06, .07, .08 Maintenance versions used by particular channels
pain.001.001.09 The 2019 version CBPR+ selected for Swift; identifies banks with <BICFI>, adds LEI and UETR carriage
.10, .11, .12 Post-2019 refinements
pain.001.001.13 Published by ISO on 19 March 2026; adds an optional unique transaction identifier (UnqTxIdr)

The compatibility matrix shows which versions Pain001 generates, validates and migrates between.

Message Direction Purpose
pain.001 Company to its bank Orders credit transfers (pushes money out)
pain.002 Bank to company Reports the status of a pain.001 or pain.008: accepted, partially accepted or rejected, with reason codes
pain.008 Company to its bank Orders direct debits (collects money under a mandate)
pacs.008 Bank to bank The interbank credit transfer a pain.001 instruction becomes
MT101 Company or bank, over Swift The legacy text "Request for Transfer" that pain.001 replaces. Swift deferred the retirement of the interbank MT101 relay in August 2026 (Swift); see MT101 to pain.001

The glossary defines the rest of the ISO 20022 vocabulary in plain English.

Why banks reject pain.001 files#

A file can be well-formed XML and still be rejected. The checks stack up in layers:

  1. Schema: the file must validate against the official XSD for its version.
  2. Data quality: IBANs pass their check digits, BICs are well formed, dates and amounts are valid, and NbOfTxs and CtrlSum match the payments.
  3. Scheme rules: SEPA, CBPR+ and domestic schemes add their own constraints, such as the allowed character set or a structured postal address.
  4. Your bank's profile and channel: each bank publishes its own usage guidelines on top of the scheme.

Pain001 checks the first three layers before the file reaches the bank and states plainly that the fourth is the bank's to confirm.

How to create a pain.001 file#

  • From a spreadsheet: Excel to pain.001 turns an Excel or CSV payment list into a validated file.
  • In the browser: the demo generates and validates a file locally, with no upload.
  • From code or the command line: install the open-source pain001 library and run:
pain001 -t pain.001.001.09 -d payments.csv -o out/

The technical reference covers every option, and the FAQs answer the questions treasury, operations and engineering teams ask most.

Sources#