ISO 20022 message
pain.001 format: customer credit transfer initiation
pain.001 is the ISO 20022 payment file a company sends its bank: a batch of credit transfers such as supplier payments, payroll or urgent wires. One file holds a group header, one or more payment information blocks (one per debit account, execution date and payment type) and the transactions inside them. It replaces bank-specific and national formats and the SWIFT MT101.
| Message | pain.001, root element <CstmrCdtTrfInitn> |
|---|---|
| Name | Customer credit transfer initiation |
| Sent | Account owner → bank |
| SWIFT MT counterpart | MT101 |
| Read by | Payment File Viewer |
Who sends it, and when
The company (the debtor, or a service centre initiating for it) uploads it to its bank through online banking, host-to-host, EBICS or SWIFT. The bank checks it and answers with one or more pain.002 status reports; the payments then show up on the camt.053 statement.
The structure of a pain.001
Document
└─ CstmrCdtTrfInitn
├─ GrpHdr MsgId, CreDtTm, NbOfTxs, CtrlSum, InitgPty
└─ PmtInf a block: one debtor account, date and payment type
├─ PmtInfId, PmtMtd (TRF), BtchBookg, NbOfTxs, CtrlSum
├─ PmtTpInf SvcLvl (SEPA, URGP …), LclInstrm, CtgyPurp (SALA …)
├─ ReqdExctnDt, Dbtr, DbtrAcct, DbtrAgt, ChrgBr
└─ CdtTrfTxInf one per payment
├─ PmtId InstrId, EndToEndId
├─ Amt/InstdAmt
├─ CdtrAgt, Cdtr, CdtrAcct
└─ RmtInf Ustrd (text) or Strd (structured reference)Versions in use
Version .001.03, from 2009, is still the most widely used. Version .001.09, from 2019, is the one the EPC’s SEPA guidelines have been based on since March 2024 (customers could keep their existing files) and the one SWIFT’s CBPR+ uses; many banks accept both. In .001.09 the execution date is a choice of a date or a date and time (ReqdExctnDt/Dt or DtTm), and a BIC is <BICFI>. The viewer reads .001.02 to .001.13.
An annotated pain.001
An excerpt of the sample the viewer opens (fictitious companies, published test account numbers):
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>NWT-PAY-20261030-01</MsgId>
<CreDtTm>2026-10-29T09:12:00</CreDtTm>
<NbOfTxs>3</NbOfTxs>
<CtrlSum>6370.45</CtrlSum>
…
</GrpHdr>
<PmtInf>
<PmtInfId>PMT-20261030-01</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<BtchBookg>true</BtchBookg>
…
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
</PmtTpInf>
…
<CdtTrfTxInf>
<PmtId>
<InstrId>PMT-20261030-01-001</InstrId>
<EndToEndId>NW-2026-311</EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="EUR">2500.00</InstdAmt>
</Amt>
…
<CdtrAcct>
<Id>
<IBAN>FR1420041010050500013M02606</IBAN>
</Id>
</CdtrAcct>
<RmtInf>
<Ustrd>Invoice 2026-311</Ustrd>
</RmtInf>
</CdtTrfTxInf>
…“…” marks lines left out.
| In the file | What it says |
|---|---|
<NbOfTxs>3 / <CtrlSum>6370.45 | Control totals: how many payments and their sum. Banks reject a file whose totals do not add up. |
<BtchBookg>true | Book the block as one debit on the statement. |
<SvcLvl><Cd>SEPA | A SEPA credit transfer: euro, IBANs, the SEPA character set. |
<EndToEndId>NW-2026-311 | Your reference: it reaches the payee and comes back on status reports and statements. |
<Ustrd>Invoice 2026-311 | Remittance text for the payee, 140 characters at most in SEPA. |
Open this sample in the Payment File Viewer
To make one rather than read one, the SEPA XML Generator builds a SEPA pain.001 from a list of payments or a CSV, checked against the EPC rules, in your browser.
Common validation errors
What most often goes wrong in a pain.001, and the rule that reports it in the viewer and the API:
pain.sum.group(Group header control sum differs): The group header CtrlSum differs from the sum of the amounts.pain.count.payment(Payment information count differs): A block’s NbOfTxs differs from its transactions.iban.invalid(Invalid IBAN): A creditor IBAN that fails its check digits or country length.ccy.decimals(Too many decimals for the currency): Too many decimals for the currency.pain.duplicate.e2e(Duplicate end-to-end id): The same end-to-end id on two payments.pain.date.past(Requested date in the past): A requested execution date in the past.sepa.charset(Characters outside the SEPA set): Characters outside the SEPA set in a SEPA payment.
Check a pain.001 from a script or an AI agent
Scripts and AI agents can do the same without a browser: POST /api/v1/validate or the MCP tool validate_payment_file returns every issue with its rule id, severity, line and path, and whether the file is valid. No key is needed, and the file is processed in memory and never stored (API and MCP docs).
curl -s --data-binary @pain001-sepa.xml https://iso20022-navigator.com/api/v1/validate{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "validate_payment_file",
"arguments": {
"content": "<the file text>"
}
}
}