Home/Blog/pain.002: reading payment status reports from your bank

pain.002: reading payment status reports from your bank

How to interpret a pain.002 status report — accepted, rejected, and pending payments — returned by your bank.

After you submit a pain.001 payment file to your bank, the bank does not just process it silently. It sends back a pain.002 message — the Customer Payment Status Report. This message tells you whether your file was accepted, whether individual transactions were rejected, and why.

Most ERP and treasury systems handle this automatically, but when something goes wrong — a file is rejected, a payment does not land, or reconciliation does not balance — you often need to read the pain.002 directly to understand what happened. This post explains the structure and the most important codes.

What pain.002 is

pain.002.001.10 (or pain.002 for short) is the ISO 20022 message type for Customer Payment Status Report. Swiss banks return it after processing a payment initiation file (pain.001). A single pain.002 can report on the entire file, on individual payment batches within the file, or on individual transactions — sometimes all three levels in the same document.

The pain.002 is not a payment confirmation. It is a processing status update. A status of ACSC (Accepted Settlement Completed) does not mean the money is in the recipient's account — it means your bank has processed the transaction and sent it into the clearing system. The final confirmation comes from the account statement (camt.054 or camt.053).

The three-level structure

Pain.002 mirrors the three-level hierarchy of pain.001:

GrpHdr (Group Header)
  └─ OrgnlGrpInfAndSts (Original Group Information and Status)
       └─ TxInfAndSts (Transaction Information and Status) — one per transaction

Not every pain.002 uses all three levels. A file-level rejection (for example, if the file failed schema validation) will have a status only in OrgnlGrpInfAndSts. A transaction-level rejection (for example, an invalid IBAN on one payment) will have a status in TxInfAndSts for that transaction.

Group-level status

<OrgnlGrpInfAndSts>
  <OrgnlMsgId>PAYMENT-2024-001</OrgnlMsgId>
  <OrgnlMsgNmId>pain.001.001.09</OrgnlMsgNmId>
  <GrpSts>ACTC</GrpSts>
</OrgnlGrpInfAndSts>

OrgnlMsgId matches the MsgId from your pain.001 file. This is how you link the status report back to the payment file you submitted. The GrpSts code tells you the overall result:

CodeMeaning
ACTCAccepted — technical validation passed, processing is underway
ACCPAccepted — customer profile validation passed
ACSCAccepted Settlement Completed — all transactions processed
ACWCAccepted With Change — accepted but with modifications (rare)
RJCTRejected — the entire file was rejected
PARTPartially accepted — some transactions accepted, some rejected

PART is the most operationally important status because it means you need to find out which transactions failed and resubmit only those, while the accepted ones are already in the clearing system (do not resubmit them).

Transaction-level status

For each rejected transaction, the TxInfAndSts block identifies it and explains why:

<TxInfAndSts>
  <OrgnlEndToEndId>INV-2024-0047</OrgnlEndToEndId>
  <OrgnlInstrId>PMT-001</OrgnlInstrId>
  <TxSts>RJCT</TxSts>
  <StsRsnInf>
    <Rsn>
      <Cd>AC01</Cd>
    </Rsn>
    <AddtlInf>Account number does not exist</AddtlInf>
  </StsRsnInf>
</TxInfAndSts>

OrgnlEndToEndId matches the EndToEndId from your pain.001. If you used the supplier's invoice number as the end-to-end ID (as recommended), you can immediately see which invoice payment failed. OrgnlInstrId matches the InstrId.

Rejection reason codes

The Cd element in StsRsnInf/Rsn carries a code from the ISO 20022 ExternalStatusReason1Code list. The most common ones in Swiss processing:

CodeReasonTypical cause
AC01Incorrect account numberIBAN check digit failed or account closed
AC04Closed account numberThe account exists but is closed
AC06Blocked accountAccount is frozen or has restrictions
AG01Transaction forbiddenPayment type not allowed for this account
AM04Insufficient fundsDebit account does not have enough balance
AM05Duplicate paymentSame EndToEndId already processed
BE01Inconsistent with end customerCreditor details do not match bank records
DT01Invalid dateExecution date in the past or a non-banking day
FF01Invalid file formatStructural error in the pain.001 file
MS02Reason not specifiedBank rejects but does not give a specific code
RC01Bank identifier incorrectInvalid BIC or clearing number
RR01Missing debtor informationRequired fields in the debtor block are empty

AC01 and AM05 are the most common in practice. AC01 usually means the IBAN you have on file for the supplier is wrong or outdated — the bank's validation caught a check digit error, or the account no longer exists. AM05 (duplicate) triggers when you submit the same EndToEndId twice — which can happen if a file is resubmitted after a connectivity issue and both attempts reached the bank.

Pending status

Not all pain.002 messages are final. A bank may send an intermediate status of PDNG (pending) for transactions that have been received but not yet processed — for example, a payment scheduled for a future date. You will receive a subsequent pain.002 with a final status when the payment is actually executed or rejected.

<TxSts>PDNG</TxSts>

Systems that process pain.002 automatically need to handle this case: a pending status means keep waiting, not that the payment is done.

Matching pain.002 back to your records

The matching logic in your system should work as follows:

  1. Read OrgnlMsgId from the group header — this identifies the pain.001 file the report refers to
  2. For each TxInfAndSts, read OrgnlEndToEndId — this identifies the individual payment
  3. Look up the transaction in your payment register using the end-to-end ID
  4. Update the transaction status based on TxSts
  5. For rejections, store the reason code and log it for the operator

This is why using meaningful, unique values for EndToEndId in pain.001 matters so much. If you used an invoice number, the pain.002 rejection immediately tells you which supplier invoice needs attention. If you used a generated sequence number with no connection to the original invoice, finding it again requires a lookup table.

What to do with rejections

For file-level rejections (GrpSts = RJCT): fix the structural issue and resubmit the entire file with a new MsgId.

For transaction-level rejections (TxSts = RJCT) within a partially accepted file: correct only the rejected transactions and submit a new pain.001 file containing only those — not the whole original batch. Resubmitting already-accepted transactions will trigger AM05 (duplicate) errors.

For AC01 (wrong IBAN): contact the supplier, get the correct bank details, update your vendor master, and resubmit the payment.

For AM04 (insufficient funds): the debit account did not have enough balance at execution time. Top up the account and resubmit — this is typically a timing issue with a treasury transfer.

The camt.054 post covers how to reconcile completed payments against your invoices once the transactions are settled.