ISO 20022 pain.001 validator
Twelve checks against the things that actually get a credit transfer file rejected. Runs in your browser; the file is never uploaded.
Validate a file
Read in this browser. Nothing is uploaded.
What gets checked
Twelve rules, applied in order. The first failure of a structural rule stops the ones that depend on it, so a file that is not well formed reports one finding rather than fifty.
- 01
Well-formed XML
The document parses. Reports the position of the first syntax error when it does not.
- 02
Namespace and version
Root is Document in urn:iso:std:iso:20022:tech:xsd:pain.001.001.NN, and the version is reported back.
- 03
Mandatory elements
GrpHdr, PmtInf and CdtTrfTxInf each carry the elements the message definition requires.
- 04
Present but empty
A required element that exists with no content. Passes a schema, fails at the bank.
- 05
Transaction counts
GrpHdr/NbOfTxs equals the number of transactions in the file, and each PmtInf/NbOfTxs equals its own.
- 06
Control sums
GrpHdr/CtrlSum equals the total of every InstdAmt, computed in minor units so no rounding error is introduced.
- 07
IBAN check digits
Length by country and the ISO 7064 mod-97 checksum, on both debtor and creditor accounts.
- 08
BIC format
Eight or eleven characters in the ISO 9362 pattern.
- 09
Amount format
Positive, at most five fraction digits, and a three-letter currency code.
- 10
Date and time formats
CreDtTm as an ISO 8601 datetime, ReqdExctnDt as a date, with a warning for an execution date in the past.
- 11
Text length limits
Max35Text on identifiers and Max140Text on names and remittance information.
- 12
Duplicate identifiers
Repeated EndToEndId values within one file, a common cause of partial rejection.
Why a file that matches the schema still gets rejected
The schema describes shape. Almost every rejection is about agreement between parts of the file that the schema has no way to compare.
An XSD can say that CtrlSum must be a decimal. It cannot say that the decimal must equal the sum of the amounts elsewhere in the document. It can say IBAN is a string matching a pattern. It cannot run the check digits. It can say EndToEndId is required and at most 35 characters. It cannot notice that you used the same one twice.
Every one of those passes schema validation and fails at the bank. That gap is what this tool covers.
A worked example
The sample file loads with three deliberate faults. It is well formed, correctly namespaced, and every mandatory element is present, so a schema validator reports nothing. Here it reports:
- Control sum mismatch
- GrpHdr/CtrlSum claims 1500.00 while the two transactions total 1750.00. The classic cause: an amount was edited and the header was not.
- Duplicate end-to-end id
- Both transactions carry E2E-0001. Copying a transaction block and forgetting to change the identifier is the single most common way this happens.
- Failed check digits
- One creditor IBAN does not survive the mod-97 test, which means a digit was mistyped somewhere in it. The arithmetic finds it without needing to know the real account.
Where this tool will mislead you
Passing is not acceptance. A clean report means the file is internally consistent, not that your bank will process it. Cut-off times, mandate and limit checks, sanctions screening and your bank's own addenda to the message are all invisible here.
A valid BIC is not a real BIC. The format is checked against ISO 9362; the SWIFT directory is licensed and cannot be redistributed, so an institution that does not exist will pass this check.
Local schemes add rules. SEPA, for instance, restricts the currency to EUR and constrains several fields the base message leaves open. A file valid as generic pain.001 can be invalid as a SEPA Credit Transfer.
Terminology
- pain.001
- CustomerCreditTransferInitiation: the instruction file a business sends to its bank.
- GrpHdr
- Group header. Identifies the file as a whole and carries the totals for it.
- PmtInf
- Payment information. One block per debtor account and execution date, each holding its own count and control sum as well as its transactions.
- CdtTrfTxInf
- Credit transfer transaction information. One individual payment.
- EndToEndId
- The reference that travels with the payment all the way to the creditor and back on any return. Must be unique within the file.
- Minor units
- The smallest denomination of a currency, such as cents. Summing in integers of these avoids the floating point error that produces most phantom control sum failures.
Common questions
Is this real XSD schema validation?
No, and no browser-based tool can honestly claim otherwise. Browsers have no XSD validator. DOMParser checks that a document is well-formed and nothing more, and doing it properly client-side means compiling libxml2 to WebAssembly, which is over a megabyte before the ISO 20022 schema files are counted.
What this does instead is check the twelve rules that actually cause rejections. A file that fails XSD is usually obviously broken. A file that passes XSD and still gets thrown out is the normal case, and it is thrown out for a control sum that disagrees with its own transactions, an IBAN whose check digits fail, or a mandatory element that is present but empty.
Does my payment file get uploaded anywhere?
No. The file is read with the browser File API straight into memory on your machine, validated there, and never sent to any server. There is no backend to send it to: this site is static files.
That is the practical reason to use this rather than an enterprise portal. A pain.001 carries account numbers, creditor names and payment amounts, and uploading one to a third party to check its syntax is a poor trade.
What is a pain.001?
The ISO 20022 CustomerCreditTransferInitiation message. It is the file a business sends its bank to say "make these payments", and it is what replaced most proprietary bank upload formats.
The name is structural rather than descriptive: pain is the payments-initiation business area, 001 the message, and the trailing numbers the variant and version. So pain.001.001.09 is version 9 of variant 1.
Why does my control sum keep failing?
Almost always because it was computed in floating point. Summing 1000.00 and 750.00 as decimals in most languages will not reliably give exactly 1750.00, and the bank compares strings, not approximations.
Add amounts as integers in minor units and format once at the end. This tool does the same, using integer arithmetic at five decimal places, so it will never report a mismatch that is really a rounding artefact.
The other frequent cause is a per-block PmtInf/CtrlSum that is correct while the GrpHdr/CtrlSum still holds the total from an earlier draft. Both are checked separately here.
Which pain.001 versions are supported?
Any pain.001.001.NN namespace is accepted and the detected version is reported back to you. The structural checks target the elements that are mandatory across versions, so 03 through 12 all validate sensibly.
Version-specific differences are handled where they matter. ReqdExctnDt, for example, is a bare date in older versions and wraps a <Dt> element in newer ones; both are accepted.
Why does it check IBANs but not BIC directories?
Because an IBAN is self-checking and a BIC is not. An IBAN carries two check digits validated by the ISO 7064 mod-97 algorithm, so a typo can be caught with arithmetic alone, offline, with no lookup.
A BIC can only be confirmed against the SWIFT directory, which is licensed and not redistributable. So the BIC is checked for correct format under ISO 9362 and nothing further. A well-formed BIC that does not belong to a real institution will pass here and fail at your bank.
It passes here. Will my bank accept it?
Not necessarily, and it would be dishonest to imply otherwise. Passing means the file is structurally sound and internally consistent, which removes the common causes of rejection.
Your bank additionally applies scheme rules this tool cannot know: whether your debtor account is permitted to send this payment type, the cut-off time for the requested execution date, agreed limits, sanctions screening, and any local addenda to the ISO 20022 message. Those are in your bank's implementation guide.
Why is a duplicate EndToEndId a problem?
Because it is the identifier that follows the payment from your ledger to the creditor's bank and back onto the return message. If two transactions share one, you cannot tell which of them a status report or a return is about.
Many banks reject the whole file for this. Some accept it and give you two indistinguishable payments, which is worse.
Where these rules come from
Message structure and element names follow the ISO 20022 payments initiation message definition published at iso20022.org. IBAN validation implements ISO 13616 with the ISO 7064 mod-97-10 check, and BIC format follows ISO 9362.
No schema files are bundled and no schema validation is performed. The reasoning for that is in the first FAQ answer above, and it is a deliberate limitation rather than an oversight.
Your bank's implementation guide outranks this page. If a rule here disagrees with it, or with the published message definition, tell me and it gets fixed.