ISO 20022 · the instruction
A pain.001 asks. The control sum is what a bank checks first.
A pain.001 is the file your treasury sends when it wants money to move: one message header, one payment block per ordering account, and one transaction per beneficiary. Everything under that header has to foot to the control sum stated in it, and a file that does not is refused whole, before anybody reads the payments inside it.
The account every page here reads
EUR- Published by
- ISO 20022
- What it carries
- One instruction: who pays, who is paid, how much, and the day it is asked for.
- Account
- ES21 0049 0001 5323 4567 8901
Closing balance · Aug 14, 2026EUR 2,990,901.67
The definition
What a pain.001 actually is
The ISO 20022 message a customer sends its bank to initiate credit transfers — the opposite direction from the statement that reports them the next morning.
A pain.001 is the ISO 20022 CustomerCreditTransferInitiation message. GrpHdr identifies the file and states how many transactions it holds and what they add up to. One PmtInf block carries everything the payments under it share: the ordering account, the bank that services it, the requested execution date and who pays the charges. Inside it, one CdtTrfTxInf per payment names the beneficiary, its account, the amount and the reference the payer wants back. Amounts use a period for the decimal and carry their currency as an attribute of the amount rather than in a field of its own.
- Who sends it
- You do. A pain.001 goes from your side to your bank, which is the opposite direction from every statement page in this library. It leaves on whatever channel that bank already runs — EBICS, host-to-host, SWIFT, the bank’s own API — and the channel is a separate decision from the message traveling inside it.
- When it arrives
- Once your approvals are in. The file is built when a run is released, and its requested execution date says which day you are asking for, not which day the bank books it. That is the bank’s decision, and it comes back on the statement.
- What it looks like
- Nested XML, and every value sits in a named element rather than at a position. Nothing has to be counted or read by offset, which is why a validator can refuse a file over one wrong element before a person ever opens it.
What its parts are called
- pain.001 CtrlSum
- pain.001 NbOfTxs
- pain.001 EndToEndId
- pain.001 ChrgBr SLEV
- pain.001 vs MT101
The file
One payment, as the file leaves
The instruction this library sends on the same day its statement closes: one credit transfer out of the account every other page here describes, for execution on the next business day.
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>MSG26081700041</MsgId>
<CreDtTm>2026-08-14T00:00:00</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>28450.00</CtrlSum>
<InitgPty><Nm>SOCIEDAD MATRIZ SA</Nm></InitgPty>
</GrpHdr>
<PmtInf>
<PmtInfId>MSG26081700041-01</PmtInfId>
<PmtMtd>TRF</PmtMtd>
<PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf>
<ReqdExctnDt><Dt>2026-08-17</Dt></ReqdExctnDt>
<Dbtr><Nm>SOCIEDAD MATRIZ SA</Nm></Dbtr>
<DbtrAcct><Id><IBAN>ES2100490001532345678901</IBAN></Id></DbtrAcct>
<DbtrAgt><FinInstnId><BICFI>BSCHESMMXXX</BICFI></FinInstnId></DbtrAgt>
<ChrgBr>SLEV</ChrgBr>
<CdtTrfTxInf>
<PmtId><EndToEndId>PO-2026-8841</EndToEndId></PmtId>
<Amt><InstdAmt Ccy="EUR">28450.00</InstdAmt></Amt>
<CdtrAgt><FinInstnId><BICFI>CAIXESBBXXX</BICFI></FinInstnId></CdtrAgt>
<Cdtr><Nm>NORTE SUMINISTROS SL</Nm></Cdtr>
<CdtrAcct><Id><IBAN>ES6621000418401234567891</IBAN></Id></CdtrAcct>
<RmtInf><Ustrd>SUMINISTRO AGOSTO</Ustrd></RmtInf>
</CdtTrfTxInf>
</PmtInf>
</CstmrCdtTrfInitn>Where each fact lives in this file
- What identifies the file itself
- <GrpHdr><MsgId>
- What the file says it adds up to
- <GrpHdr><NbOfTxs> · <GrpHdr><CtrlSum>
- Which account it leaves, and in whose name
- <Dbtr><Nm> · <DbtrAcct><Id><IBAN>
- Who is being paid, and into which account
- <Cdtr><Nm> · <CdtrAcct><Id><IBAN>
- Which bank sends it, and which one receives it
- <DbtrAgt><FinInstnId><BICFI> · <CdtrAgt><FinInstnId><BICFI>
- How much, and in which currency
- <Amt><InstdAmt Ccy="EUR">
- The day execution is asked for
- <PmtInf><ReqdExctnDt><Dt>
- The reference that ties it to a payment
- <PmtId><EndToEndId>
- Who pays the bank charges
- <PmtInf><ChrgBr>
- What the payment says it is for
- <RmtInf><Ustrd>
What gets checked
What a bank checks before it reads the payments
A pain.001 is accepted whole or refused whole. What decides that is a handful of elements which have to agree with each other.
The header states a count and a total, and both are claims about the transactions underneath. NbOfTxs has to be how many CdtTrfTxInf blocks the file really carries, and CtrlSum has to be what their InstdAmt values come to, down to the cent. We build both from the payments in the run instead of carrying them alongside, so a file cannot leave with a header that disagrees with its own contents. Every amount travels as exact minor units: nothing is rounded on the way in or on the way out.
The rest is the bank’s own boundary. A pain.001 that validates can still be rejected for a beneficiary account the bank will not take, a currency the ordering account does not hold, or a requested date that is not a business day where the money is going. That answer comes back on a pain.002, and it lands on the same instruction rather than in somebody’s inbox: the reference you set in EndToEndId is the one that comes back, and the debit turns up again on the next morning’s statement under it.
That is the whole trade with an instruction file. It is refused on arithmetic before it is judged on anything else, so the arithmetic is the part that has to be built rather than checked.
Next
Where this file came from and where it goes
MT101 is the same instruction in the older spelling, and the two are built here from one run. SEPA is not another file: it is the set of rules this one has to satisfy before a euro-area bank executes it. CAMT.053 is where the debit turns up the next morning.
Formats to read beside it
The same day written in four formats, side by side, is on Format library
Asked about pain.001
The questions a payments team actually types
- 01What is CtrlSum in a pain.001?
- The total of every InstdAmt in the file, stated once in the group header. It is a claim about the transactions underneath it, so it is checked before anything else: a control sum one cent away from the payments it covers gets the whole file refused, and nothing in it goes anywhere. NbOfTxs is the same claim about the count. Both are built from the run rather than carried beside it.
- 02What is the difference between pain.001 and pain.002?
- One asks and one answers. pain.001 is the credit transfer initiation your side sends; pain.002 is the payment status report the bank sends back, carrying a status per transaction and a reason code wherever something was rejected. The two are tied together by the references in the file you sent — the message identification and the end-to-end reference — which is why those two fields are worth setting to something real.
- 03Where does the end-to-end reference go in a pain.001?
- Under PmtId, on each transaction, as EndToEndId. The bank passes it through untouched: it comes back on the status report, it appears on the statement entry for the debit, and where the beneficiary’s bank supports it, it reaches the beneficiary too. It is the one field in the file that reliably ties an instruction to the entry that settles it, so it is worth setting to something your own ledger recognizes.
- 04What does ChrgBr SLEV mean?
- Charges follow the service level named on the payment. On a SEPA credit transfer that means each side pays its own bank, and it is the only value the scheme allows. The other codes live outside SEPA: DEBT puts every charge on the payer, CRED on the beneficiary, and SHAR splits them.
- 05Which pain.001 version should we send?
- Whichever your bank publishes in its own implementation guide, and across a group those are rarely the same. The message has several versions in circulation, and banks differ on which elements they require, which they ignore and how much text they accept in each. We pin a format profile to the version each bank really takes, so a group sending three versions does not have to standardize its banks before it can pay them.
Send us a file one of your banks takes.
One account, one run. You get back the same file built out of your own ledger, footed against the payments that produced it, carrying the references your systems already use.
No channel has to be opened for this: the file is enough.