How to read a pain.002#
When your bank answers a pain.001 or pain.008, the pain.002 Customer Payment Status Report carries a status at up to three levels: group (GrpSts), payment information block (PmtInfSts), and individual transaction (TxSts). It also carries zero or more status reason codes explaining any non-acceptance. The codes come from the ISO 20022 External Code Sets (ExternalStatusReason1Code), which is the canonical registry; this page covers the codes payment-operations teams actually meet, with the usual cause and the practical fix.
01. Status codes: how bad is it?#
| Status | Meaning | What to do |
|---|---|---|
RCVD | Received: arrived, not yet checked | Nothing yet. |
ACTC | Accepted, technical validation passed | Nothing. Syntax and schema are fine. |
ACCP | Accepted, customer profile checks passed | Nothing. |
ACSP | Accepted, settlement in process | Nothing. |
ACSC | Accepted, settlement completed | Done. Reconcile against camt.053. |
ACWC | Accepted with change (the bank altered something) | Read the changes; fix your source data so the bank stops "helping". |
PART | Partially accepted: some transactions rejected | Check per-transaction TxSts; resubmit only the rejected ones. |
PDNG | Pending, with further checks ongoing | Wait; investigate only if it persists past the bank's stated window. |
RJCT | Rejected | Read the reason codes below; repair; resubmit. |
02. Format and schema failures#
The rejections Pain001 exists to make impossible. Every one of these is caught by the validation gate before submission:
| Code | Name | Typical cause | Fix |
|---|---|---|---|
FF01 | Invalid file format | Wrong schema version, malformed XML, wrong namespace | Validate against the exact XSD your bank profiles (pain001 --dry-run). |
AM10 | Invalid control sum | CtrlSum doesn't match the sum of amounts | Never hand-compute totals: Pain001 recomputes NbOfTxs/CtrlSum from the records. |
AM01 | Zero amount | An amount of 0 slipped through | Filter zero rows at source. |
AM02 | Amount not allowed | Above a scheme or account limit | Check scheme ceilings and account mandates. |
AM03 | Currency not allowed | Currency not supported on the account/scheme | SEPA schemes are EUR-only; use the cross-border rulebook otherwise. |
AM09 | Wrong amount | Amount disagrees with a referenced mandate/agreement | Reconcile against the mandate. |
DT01 | Invalid date | Execution date malformed, in the past, or a non-banking day | ISO 8601, forward-dated, banking-day adjusted. |
CH03 | Execution date too far in future | Beyond the bank's forward window (often 1 year) | Shorten the horizon. |
TM01 | Cut-off time | File arrived after the bank's processing cut-off | Automate submission earlier; know each bank's cut-offs. |
DU01–DU03 | Duplicate message / payment info / transaction ID | Re-used MsgId, PmtInfId, or EndToEndId | Generate unique IDs per submission; never resubmit a file unchanged. |
03. Account and identifier failures#
| Code | Name | Typical cause | Fix |
|---|---|---|---|
AC01 | Incorrect account number | IBAN fails validation or doesn't exist | Mod-97 check before submission. The demo shows this live. |
AC03 | Invalid creditor account | Creditor IBAN wrong or closed | Verify against the invoice/master data. |
AC04 | Closed account | Account has been closed | Contact the counterparty for current details. |
AC06 | Blocked account | Account blocked for this transaction type | Counterparty must resolve with their bank. |
RC01 | Bank identifier incorrect | Malformed or unknown BIC | ISO 9362 structure check + directory lookup. |
AG01 | Transaction forbidden | Payment type not allowed on this account | Wrong account or missing product agreement. |
AG02 | Invalid bank operation code | Wrong local instrument / service level combination | Match your bank's implementation guide. |
04. Party, mandate, and regulatory failures#
| Code | Name | Typical cause | Fix |
|---|---|---|---|
BE01 | Inconsistent with end customer | Name doesn't match the account | Fix creditor master data; this is what Verification of Payee checks pre-submission. |
BE04 | Missing creditor address | Address absent where required | CBPR+ will require structured or hybrid addresses; the date is due by December 2026 (see the roadmap). |
BE05 | Unrecognised initiating party | Initiating party not authorised on the account | Check the bank mandate for the submitting entity. |
MD01 | No mandate | Direct debit without a valid mandate | Collect/register the mandate before collecting funds. |
MD02 | Missing mandate information | Mandate data incomplete in the pain.008 | Populate all mandate-related fields. |
MD07 | End customer deceased | n/a | Close the mandate. |
RR01–RR04 | Regulatory reasons | Missing debtor/creditor identification, name, address, or other regulatory data | Populate the party data your corridor requires; structured addresses solve most of these. |
AM04 | Insufficient funds | Not a format problem | Treasury, not toolchain. |
MS02 / MS03 | Reason not specified (customer / bank generated) | The bank chose not to say | Call the bank; often accompanies sanctions or internal-policy holds. |
NARR | Narrative | Free-text explanation in AddtlInf | Read the narrative field. |
05. Close the loop automatically#
Pain001 parses pain.002 responses into structured data, so your pipeline can route rejections without a human reading XML:
=
Validating the response before you trust it
The parser reads whichever pain.002 version your bank sends. It detects the namespace rather than assuming one. If you want the response checked against the official ISO schema first, pass validate=True:
=
Pain001 bundles the ISO schemas for pain.002.001.03 (what SEPA banks commonly reply with), pain.002.001.12, pain.002.001.14 and pain.002.001.15; bundled_schema_versions() returns the current list. If your bank replies in a version that is not bundled, validate=True raises rather than parsing unvalidated. That is deliberate: silently skipping the check would report a validation that never happened. Either supply the schema yourself with xsd_file_path=, or omit validate and parse without schema validation.
The MCP server exposes the same parser to AI agents as parse_pain002, and the payment-lifecycle guide shows where status handling sits in the full pipeline.
Canonical source. Code definitions live in the ISO 20022 External Code Sets, maintained at iso20022.org/catalogue-messages/additional-content-messages/external-code-sets and revised quarterly. Bank implementation guides may narrow, but not contradict, these meanings. Spot an inaccuracy? Report it.
