ISO 20022 Purpose Codes: Purp, CtgyPurp, and What They Drive Downstream
Written by Ahmed at Analyst Engineering, a Senior Technical Business Analyst with 10+ years in banking and payments delivery.
Key takeaways
- Purp and CtgyPurp look interchangeable and are not. Purp describes why the debtor is paying and is meant for the creditor. CtgyPurp tells the agents how to handle the payment, and it is the one that changes routing, priority, and settlement behavior.
- CtgyPurp is the field that makes payroll work. A batch marked SALA can be given salary treatment: masked on statements, prioritised for a value date, and in some schemes routed differently. Populate it wrong and a payroll run behaves like an ordinary bulk transfer.
- Purpose codes come from external code lists published separately from the schema, which means they change without a schema version change. A hardcoded enumeration in your validator will start rejecting valid payments the first time the list is updated.
- Purpose is increasingly mandatory rather than optional. Several domestic schemes and enhanced-data regimes require a purpose code on specific payment types for regulatory reporting, so treating it as a nice-to-have field creates a migration problem later.
- Never infer purpose from the remittance text. A model or a rule that reads 'INVOICE 4471' and writes SUPP is guessing, and a wrong purpose code on a regulated corridor is a reporting breach rather than a cosmetic error.
Purp says why the debtor is paying and is meant for the creditor. CtgyPurp tells the banks how to handle the payment and can change routing, priority, and treatment. They are not interchangeable, they come from external code lists that change without a schema version, and a wrong SALA is discovered on payday.
Two fields, four characters each, both optional in the base standard, both routinely left empty. And then a payroll batch of eleven thousand salary payments settles as an ordinary bulk transfer, individual amounts appear on a shared statement, and the client’s HR director calls.
This is the purpose article in the field-by-field track of The ISO 20022 Reference, following charges. Purpose codes are the clearest example of a field that looks cosmetic and is load-bearing.
Purp or CtgyPurp: which is which?
The distinction is about audience.
Purp | CtgyPurp | |
|---|---|---|
| Question answered | Why is the debtor paying? | How should this be handled? |
| Intended reader | The creditor | The agents in the chain |
| Effect on processing | Generally none | Routing, priority, treatment, pricing |
| Typical location | Payment transaction | Payment information or transaction |
| Example | SUPP supplier payment | SALA salary batch |
Purp travels through to the beneficiary and helps them reconcile and account for the receipt. It is commercial information.
CtgyPurp is an instruction to the banks. It is the one that changes what actually happens to the money.
Both draw from external code lists with overlapping values, which is exactly why they get confused. SALA exists in both contexts. Putting it in Purp tells the beneficiary this was a salary. Putting it in CtgyPurp tells your bank to treat the batch as payroll. Only the second one makes payday work.
The codes that actually change behavior
You do not need the whole list. A working analyst meets perhaps a dozen regularly.
Category purpose, the operationally significant ones:
SALA: salary. Triggers payroll treatment: confidentiality on aggregated statements, value-date prioritisation, sometimes a distinct processing path.PENS: pension payment, usually handled alongside salary.TAXS: tax payment. Frequently routed to a dedicated settlement arrangement with the tax authority.INTC: intra-company transfer. Often exempt from certain checks and priced differently.TREA: treasury payment.CASH: general cash management transfer.SUPP: supplier payment.DIVI: dividend.SECU: securities-related.
Purpose, commonly used for reconciliation and reporting: SUPP, TAXS, SALA, RENT, LOAN, INSU, GOVT, and a long tail of industry-specific values.
Two behaviors are worth calling out because analysts consistently underestimate them:
Salary confidentiality. Under SALA, many schemes and banks suppress individual payment amounts on statements available to the whole finance team, because individual salaries are confidential. Without the code, every employee’s salary appears as a line item that anyone with statement access can read. That is a data protection incident produced by an empty four-character field.
Value date prioritisation. SALA batches are frequently given processing priority so employees are credited on the promised date. An unmarked batch queues behind ordinary traffic, and the failure is visible to eleven thousand people simultaneously.
The external code list trap
Purpose codes are not in the schema. They come from ISO 20022 external code lists, published and maintained separately from the message definitions.
That separation is deliberate and useful: the taxonomy can evolve without reissuing schemas. It also creates a specific, predictable implementation defect.
A developer implements validation. The natural approach is an enumeration compiled into the application, validated against the code list as it stands today. Six months later the list is updated, a counterparty starts sending a newly added code, and your perfectly correct validator rejects a perfectly valid payment. The rejection reason will be useless, because the code genuinely is not in your list.
So the specification must say:
- The purpose code list is configuration, not code.
- It has an owner and a refresh cadence.
- An unrecognised code goes to a defined path: repair queue, or pass-through with a flag, but never a silent default and never an unexplained rejection.
The same applies to reason codes and every other external list. It is the same class of problem as reason code mapping: the values move, and hardcoding them converts a data update into a release.
Optional in the standard, mandatory in practice
The base standard makes both fields optional. This is the single most misleading fact about them.
The usage guideline layer above frequently makes purpose mandatory for particular payment types, corridors, amounts, or counterparty categories, usually to satisfy central bank statistical reporting or regulatory regimes. Several domestic schemes require it outright. Enhanced-data regimes in RTGS systems have been extending these requirements rather than relaxing them.
This is the four layers problem in its purest form: optional in the standard, mandatory in the scheme, constrained to a subset by your correspondent, and absent from your database because the original mapping read the standard. Determine the net rule per flow and write it into the rules register. Do not read the base schema and conclude the field is optional, because the base schema is the one layer that will not reject your message.
The forward-looking version of this: if your programme is scoping an ISO 20022 migration and treating purpose as out of scope because it is optional, you are deferring a mandatory field into a second project. That is a blast radius item, and it is cheaper to carry now.
Never infer purpose from text
This needs saying explicitly because it is an attractive shortcut and it is being automated more often now that pattern-matching is cheap.
The remittance information field contains free text written by the debtor for the creditor. It might say INVOICE 4471. A rule, or a model, can read that and write SUPP with high apparent accuracy.
Do not. On corridors where the purpose code feeds regulatory reporting, central bank statistics, or tax treatment, a wrong value is a reporting breach, not a cosmetic error, and “our system inferred it from the payment description” is not a defence anyone wants to make to a regulator.
The purpose code must come from the originating party, or from a documented product rule (this product is always SALA), or from a customer-configured default. It must never be pattern-matched. If you are using AI anywhere near payment data, this is exactly the boundary described in the AI guardrails: a generated statement of fact that enters a regulated field is a defect with a compliance dimension.
What to specify and what to test
Specification:
- Which of
PurpandCtgyPurpyour systems populate, per product and per scheme, and from what source. - The net mandatory rule per flow, from the guideline layers, not from the schema.
- The behavior triggered by each category purpose you support: routing, priority, statement treatment, pricing.
- How the code list is maintained: owner, source, refresh cadence, and what happens to an unrecognised code.
- An explicit prohibition on inferring purpose from free text.
Test conditions:
- A
SALAbatch proving both confidentiality handling and value-date priority actually fire. Assert the observable behavior, not the presence of the field. - Each supported category purpose producing its documented treatment.
- An unrecognised purpose code following the defined path rather than a silent default.
- A flow where the scheme makes purpose mandatory, sent without it, which must be rejected before it reaches the scheme.
PurpandCtgyPurpboth populated with different values, which is legal and must not confuse routing.
The second and last are the ones teams skip, and they are where the behavior lives.
The takeaway
Purp tells the creditor why they were paid. CtgyPurp tells the banks how to handle it, and it is the field that moves money differently. SALA is the one that makes payroll behave like payroll, including the confidentiality that stops every salary appearing on a shared statement.
Treat the code lists as configuration with an owner and a refresh cadence, because they change without a schema version. Determine the mandatory rule from the scheme rather than the standard, since the standard says optional everywhere and the scheme is what rejects you. And never infer a regulated code from free text.
Next: remittance information and the RF creditor reference, the field the beneficiary actually reconciles against. The full map is on The ISO 20022 Reference.
Ahmed is a Senior Technical Business Analyst with 10+ years in banking and payments. He builds practical guides and tools for analysts at The Tech BA Toolkit.
Tags: ISO 20022, Payments, Banking, Regulatory Reporting, Functional Analysis
About the author
Analyst Engineering is written by Ahmed, a Senior Technical Business Analyst with 10+ years of banking and payments delivery experience: ISO 20022 and SWIFT messaging, payments API integration, Kafka event validation, and production support. Every article comes from real delivery work, and each one is reviewed and updated as tools and standards change.
Related articles
- ISO 20022 Remittance Information: Structured, Unstructured, and RF References How remittance information works in ISO 20022: the 140-character unstructured field, the structured block, ISO 11649 RF references, and remittance location.
- Reading an ISO 20022 Usage Guideline: The Four Layers That Decide Your Field Rules A field can be optional in ISO 20022, mandatory in CBPR+, forbidden by your correspondent, and absent from your database. How to build the net rule matrix.
- Sanctions Screening on ISO 20022: What Structured Data Changed Which ISO 20022 fields sanctions screening reads, why structured addresses cut false positives, and the screening defects an analyst finds in every migration.
- The ISO 20022 Blast Radius: The Systems Nobody Scoped Migration programmes scope the payment rail and forget everything reading it: screening, monitoring, the warehouse, reports. The downstream impact register.
Free account
Practice on the Labs, keep your progress
A free account, no password: an email link signs you in. It saves your steps and self-assessments on the Labs, shows your missions on a dashboard, unlocks the solutions, and, if you tick the box, sends you new missions and articles when they ship.
Your email is used to sign you in. Nothing else, unless you ask. Privacy.