All entries
Chapter VIII
Journal · 13 Sept 2026 · 11 min read

ISO 20022 pain.001 vs pacs.008: Rules by Rail

pain.001 vs pacs.008 explained with the versions, field limits and status codes SEPA, CBPR+, Fedwire, FedNow and CHAPS actually enforce in 2026.

A pacs.008 sent over Swift CBPR+ must carry exactly one transaction, a mandatory UETR and a charge bearer of DEBT, CRED or SHAR. Send the same payment into SEPA and the only charge bearer allowed is SLEV, which CBPR+ rejects. Same message name, same version number (pacs.008.001.08), and the two rulebooks cannot accept one shared value for a field as basic as who pays the fees.

That is the part the ranking explainers for "pain.001 vs pacs.008" leave out. They describe the ISO catalogue. Your code talks to a market practice, and every rail has its own.

What Is the Difference Between pain.001 and pacs.008?

pain.001 is what a customer sends to its bank. pacs.008 is what banks send to each other. The rest of the differences follow from that.
pain.001 (Customer Credit Transfer Initiation)pacs.008 (FI to FI Customer Credit Transfer)
SenderCorporate, fintech, PSP clientDebtor agent, intermediary agent, clearing system
ReceiverDebtor's bankNext agent or clearing system
StructureGroup header → payment information blocks → transactionsGroup header → transactions
BatchingMany transactions per payment-information block, sharing a debtor account and execution dateCBPR+ fixes NbOfTxs at 1; clearing schemes such as SEPA batch
Settlement dataNone; you request an execution dateInterbank settlement amount and date
Status responsepain.002pacs.002
Typical SEPA versionpain.001.001.09pacs.008.001.08

If you are a fintech without direct scheme access, you almost certainly produce pain.001 (or a bank's JSON wrapper around it) and never see a pacs.008 until something goes wrong and a bank forwards you one during an investigation. If you are a direct participant in FedNow, CHAPS or a SEPA clearing house, pacs.008 is your payment order, and pain.001 is what your own corporate customers send you.

ISO 20022 Message Types Explained: pain, pacs and camt

The four-letter prefix is the business area. For payments work you need three.

  • pain (payments initiation): pain.001 initiation, pain.002 status report, pain.013/pain.014 request-to-pay and response.
  • pacs (payments clearing and settlement): pacs.008 customer transfer, pacs.009 bank-to-bank transfer, pacs.004 return, pacs.002 status, pacs.028 status request.
  • camt (cash management): camt.052 intraday report, camt.053 end-of-day statement, camt.054 debit/credit notification, camt.056 recall request, camt.029 resolution of investigation.
The suffix is the version. pacs.008.001.08 is variant 001, version 08. Version numbers matter more than the explainers suggest, because the big infrastructures did not all pick the same ones.

Which ISO 20022 Versions Do SEPA, Fedwire, FedNow and CHAPS Use in 2026?

RailCustomer transferReturnStatusNotes
SEPA SCT and SCT Instpacs.008.001.08pacs.004.001.09pacs.002.001.102025 implementation guides, effective 5 October 2025
Swift CBPR+pacs.008.001.08not checkednot checkedSingle-transaction profile, UETR mandatory
Fedwire Fundspacs.008.001.08pacs.004.001.10not checkedLive 14 July 2025; header head.001.001.03
FedNowpacs.008.001.08pacs.004.001.10pacs.002.001.10Per the Fed's readiness guide (v1.3, 2022)
CHAPSpacs.008.001.08pacs.004.001.09pacs.002.001.10Live 19 June 2023; header head.001.001.02

Look at the return column. The Federal Reserve built Fedwire on the 2019 message versions with one exception, pacs.004.001.10 from 2020. CHAPS and the EPC stayed on .09. So if you run a returns service that handles both GBP and USD, you are maintaining two schemas for the same business event, and your XSD validation needs to be selected by rail, not by message name. The business application header differs too: head.001.001.02 in CHAPS, .03 in Fedwire.

FedNow has its own quirks. It has no REST endpoint for sending a payment, and its pacs.009 is for liquidity transfers only.

CBPR+ vs SEPA: Field Rules That Break a Shared Payment Model

Most teams start with one internal payment object and serialise it to whichever rail a payment is routed over. This table shows where that breaks. Both columns describe pacs.008.001.08.

ElementSwift CBPR+SEPA Credit Transfer
ChrgBrDEBT, CRED, SHARSLEV only
UETRMandatory (1..1), UUID v4Optional (0..1), same UUID v4 pattern
EndToEndId1–35 chars; NOTPROVIDED if the originator gave none1–35 chars
Ustrd (unstructured remittance)Restricted to one occurrence, 140 chars140 chars
Character set, referencesa-z A-Z 0-9 / - ? : ( ) . , ' + and spaceSame Latin set; IDs cannot start or end with / or contain //
Character set, names and addressesExtended set adds ! # $ % & * = ^ _ ~ " ; < > @, braces, square brackets, backslash and the vertical barLatin set only
AdrLineISO allows 7, CBPR+ allows 3 at 70 chars; 35 chars per line if the address is unstructured onlyUnstructured-only addresses not allowed from 22 November 2026 per the 2025 guide
Hybrid address minimumTwnNm and Ctry mandatory, at most 2 AdrLineTwnNm and Ctry

The UETR regex is stricter than "any UUID". CBPR+ enforces version 4 with the variant nibble in [89ab]:

[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}

Lowercase only. A UUID v7 fails it, and so does any library that emits uppercase hex. Switching an ID generator to v7 for index locality is a sensible-looking database change that would break every cross-border payment, and it would sail through domestic testing on a rail where UETR is optional.

The character sets bite differently. A customer name like O'Brien & Sons is valid in CBPR+ (both ' and & are in the extended set) but the & fails SEPA validation. Mapping that ampersand to + or and has to happen per rail, at egress, and never in the stored customer record.

The 35-character line limit for unstructured CBPR+ addresses exists because the MT format it replaced used 35-character lines. When Swift's in-flow translation squeezes an MX into an MT for a receiver that still wants FIN, fields that do not fit are truncated and marked with a trailing +. If you reconcile against inbound MTs from a correspondent, a + at column 35 is not data. It is a flag telling you data was lost.

pacs.002 and pain.002 Status Codes: ACSP vs ACSC vs ACCC

The ISO external code set defines the transaction status ladder. These are the codes that show up in production:

CodeMeaningHas money moved?
RCVDReceivedNo
ACTCAuthentication and syntax/semantic validation passedNo
ACCPTechnical validation and customer profile check passedNo
ACSPAll checks passed, accepted for execution, settlement in processNo
ACSCSettlement completedInterbank leg, yes
ACCCSettlement on the creditor's account completedBeneficiary credited
ACWCAccepted with changeDepends on what changed
ACWPAccepted, not posted to the creditorNot to the beneficiary
PDNGPendingNo
BLCKBlocked, after ACWPFunds held
RJCTRejectedNo

The expensive mistake is mapping ACSP to "paid". It means the bank has accepted the instruction and settlement is in progress. ACSC means the interbank leg settled. Only ACCC tells you the beneficiary's account was credited, and plenty of banks never send it. If your product shows "Payment complete" to users, key it off ACSC at the earliest and document the gap.

SEPA's pain.002 is reject-only. The EPC customer-to-PSP guide allows just RJCT, at group, payment-information or transaction level. In the scheme-standard flow, silence is success. Build a state machine that waits for a positive pain.002 and your SEPA payments sit in PENDING forever. Individual banks can offer positive reports through their own bilateral profiles, so confirm the behaviour per bank, in writing, before go-live.

ISO 20022 Reason Codes for Rejects, Returns and Recalls

When a status is RJCT or a pacs.004 arrives, the StsRsnInf or return reason carries an external code. The ones worth mapping to specific user-facing messages:

  • AC01 account number invalid or missing
  • AC04 account closed
  • AC06 account blocked
  • AM04 insufficient funds
  • AM05 duplication
  • BE01 customer identification inconsistent with account
  • FF01 invalid file format
  • MS02 / MS03 not specified, by customer / by agent
  • RR01RR04 regulatory reasons
  • RC01 BIC incorrect
AM05 deserves special handling. It is a scheme telling you your own idempotency controls failed, and it should page someone rather than show a retry button.

SEPA narrows these further. A camt.056 recall may only give DUPL, TECH or FRAD as its reason. A negative camt.029 answer is restricted to AC04, AM04, ARDT, CUST, LEGL, NOAS or NOOR. The recall flow runs camt.056pacs.004 if accepted, or camt.056camt.029 if refused, with pacs.028 as the chaser. A pacs.004 is a new credit transfer travelling back, not a reversal of the original entry. Your ledger should post it as a new inbound movement linked to the original, not un-post the outbound one.

MT103 to pacs.008: What Replaced Each Swift MT Message

MT/MX coexistence for cross-border payments ended on 22 November 2025. The mappings, per BNY's end-of-coexistence notice:

Legacy MTISO 20022 replacement
MT103, MT103 STPpacs.008
MT200, MT202, MT205pacs.009
MT202 COV, MT205 COVpacs.009 COV
MT103/202 returnpacs.004
MT103/202 rejectpacs.002
MT940, MT950camt.053
MT941, MT942camt.052

Two details from that notice matter more than the table. MT102, MT102 STP, MT103 REMIT, MT201 and MT203 were withdrawn outright. And the statement and customer-initiation messages (MT101, MT900, MT910, MT940, MT942, MT950 among them) stay on FIN "until an end date is defined by Swift". So your treasury integration probably still parses MT940 while your payments integration emits pacs.008. Swift also began charging for in-flow MX-to-MT translation in January 2026, which gives banks still asking to receive MTs a reason to stop, even though no end date has been set.

CHAPS ISO 20022 Enhanced Data Dates in the UK

CHAPS went live on ISO 20022 on 19 June 2023 and has layered data mandates on top:

  • 1 May 2025: LEIs and purpose codes mandatory for payments between financial institutions, plus six property-transaction purpose codes.
  • November 2027: structured remittance data mandatory, purpose codes on all CHAPS payments, LEIs on pacs.004 and pacs.009.
  • November 2026: rejection of unstructured addresses. On 27 August 2026 the Bank of England said its November 2026 RTGS standards release "has therefore been deferred in its entirety", following Swift's deferral of every payments change in Standards Release 2026.
The Fed has moved its November 2026 Fedwire release to November 2027. As of 13 September I found no EPC notice moving the SEPA 22 November 2026 hybrid-address date. That leaves SEPA as the one rail where the address rule might still take effect this year.

Should You Build One Canonical ISO 20022 Payment Model?

My position: yes, one internal model, but never one serialiser. Build the canonical payment as a superset of the ISO elements you use, sized to the most generous limits (140-char names, full structured address, UETR always populated). Then put a rail profile at egress that owns charge bearer, character transliteration, cardinality, address form and message version. Validate against the rail's own XSD and usage guideline at that layer, and persist the exact XML you sent and received next to the canonical record.

Two reasons. First, the mandates are diverging, not converging. Swift's payments timeline is unknown until December, Fedwire and CHAPS both point at November 2027, and SEPA's address date has not moved. Those are three separate calendars, and a single global validator cannot follow three. Second, disputes are argued over the message, not your model. When a correspondent says your address arrived truncated, the stored pacs.008 settles it in minutes.

I'd also generate a UETR for every payment on every rail, including SEPA where it is optional. It is the only identifier designed to survive every hop, and populating it costs nothing.

My prediction is that per-rail divergence gets worse through 2027, not better. The December Swift update will set a new CBPR+ date, the domestic infrastructures will each pick their own response, and "ISO 20022 compliant" will mean even less as a single claim than it does today.

What This Means for Payment Engineers

1. Key XSD selection by rail and message version, not message name. pacs.004.001.09 and .10 coexist in production today. 2. Test your UUID generator against the CBPR+ UETR regex. Lowercase, version 4, variant [89ab]. Add it as a unit test so a library upgrade cannot break it silently. 3. Transliterate at egress, per rail. Keep the customer's original name in storage; produce SEPA-safe Latin output only when serialising. 4. Map ACSP to "processing", never "paid". Decide explicitly whether ACSC or ACCC drives your completed state, and write down which banks never send ACCC. 5. Confirm positive pain.002 behaviour with each SEPA bank. The scheme default is reject-only. 6. Post pacs.004 as a new inbound entry. Do not reverse the original outbound posting. 7. Treat a trailing + in an inbound MT field as truncation. Flag the record for review instead of reconciling on it. 8. Put the SEPA 22 November 2026 address date in your plan until the EPC says otherwise, and keep hybrid address output configurable per rail and per counterparty.

None of this is in the ISO catalogue, because the catalogue describes messages and the rulebooks describe payments. If you'd like to compare notes on building rail profiles, Tom Wang is the easiest place to find me.