·14 min read

The Nov 14, 2026 structured-address mandate — a deep dive

Every field that changes, every bank that has published readiness guidance, and the deterministic restructurer that gets you to compliant in an afternoon.

November 14, 2026 is the SWIFT-network cutover for structured-address enforcement on cross-border MX flows. After that date, a pain.001 instruction that carries the debtor or creditor address in <AdrLine> form is rejected at the SWIFT FINplus level before it ever reaches the beneficiary bank.

This post is the field guide. What exactly does "structured address" mean inside ISO 20022 <PstlAdr>? Which fields are mandatory? Which are optional but materially affect reject rates? Which banks have published their readiness guidance and what overlays do they layer on top of the SWIFT minimum?

The ISO 20022 <PstlAdr> grammar

The <PstlAdr> (postal address) element under any party block (Dbtr, Cdtr, UltmtDbtr, UltmtCdtr) admits the following sub-elements (this is the post-mandate-friendly subset):

  • <StrtNm> — street name. 1–70 chars. Mandatory under any rule pack with structuredAddressRequired.
  • <BldgNb> — building number. 1–16 chars. Mandatory.
  • <BldgNm> — building name. Optional, used where a building has no street number (e.g. corporate towers with named addresses).
  • <Flr> / <Room> / <PstBx> — floor / room / PO-box. Optional sub-modifiers.
  • <PstCd> — postal code. 1–16 chars. Mandatory.
  • <TwnNm> — town name. 1–35 chars. Mandatory.
  • <TwnLctnNm> — town-location (e.g. district / borough). Optional.
  • <DstrctNm> — district name. Optional.
  • <CtrySubDvsn> — country sub-division (state, canton, province). Optional but required by some bank overlays (US, CA, AU).
  • <Ctry> — ISO 3166-1 alpha-2 country code. Mandatory.

The <AdrLine> element (1..7 occurrences, 1..70 chars each) is the unstructured form. It is what most pre-2024 pain.001 emitters generated. After the November 14 cutover, an <AdrLine> in a cross-border MX <PstlAdr> is a hard reject.

The character-set rule

CBPR+ pins the character set to the SWIFT "x" set — Latin alphabet, digits, and a constrained punctuation list. Accented characters (ä, é, ñ), non-Latin scripts (Cyrillic, Han, Arabic), and many punctuation marks (em-dash, smart quotes) are out.

The customer-side implication: any pain.001 emission for cross-border MX requires an ASCII-fold pass over every <Nm>, <StrtNm>, <TwnNm>, <CtrySubDvsn> value. Common folds: ä → ae or a (per local convention), é → e, ñ → n. The choice matters less than the consistency — pick a fold rule per locale and stick with it across emit + parse.

Per-bank overlays

The SWIFT-network minimum (street_name + building_number + post_code + town_name + country) is the floor. Several major banks have published overlays that add more required fields:

  • UBS Switzerland — minimum, plus <Ctry> consistency check against the IBAN country prefix.
  • PostFinance Switzerland — minimum, plus <PstCd> validated against the Swiss postal code catalog (4-digit numeric).
  • Deutsche Bank — minimum, plus <CtrySubDvsn> required for DE addresses (Bundesland) and for US / CA.
  • JPMorgan — minimum, plus <CtrySubDvsn> mandatory for US addresses (state) and for AU.
  • BNP Paribas — minimum, plus a hard reject on accented characters in <Nm> fields.
  • HSBC — minimum, plus <BldgNm> required when <BldgNb> is empty.

iso-compliant captures these overlays in per-bank rule packs (the registry is at apps/api/src/lib/rule-pack-loader.ts; today it ships with a SKELETON pack for ubs-ch as the first rule-pack on the road to the full Tier-2 set). The customer-side win is that the pain.001 builder enforces the per-bank overlay at emission, so a pre-UAT smoke test catches the field-level reject before the bank does.

The restructurer route

POST /v1/address/restructure takes a single freeform address line (up to 280 chars) and emits the structured form. The algorithm is deterministic token-mapping — same input always produces same output. It is not perfect: poor on multi-line freeform addresses, poor on non-European postal formats, poor when the country is implicit.

The route returns three things: the structured block, a confidence label (high / medium / low), and a list of caveats. Customer-side: route high-confidence results straight to the pain.001 builder; route medium / low through a human-review queue.

For browser-side compliance lint without an API key, use the free /address-lint page on the marketing site. Same field-presence checks, runs in your browser, no network call.

A migration checklist

  • 1. Inventory every place your codebase emits <AdrLine>. grep \bAdrLine\b across your repos.
  • 2. Inventory every place your customer data carries an address. Is it freeform, structured, or hybrid?
  • 3. Build the freeform-to-structured restructurer (or use POST /v1/address/restructure).
  • 4. Add a pre-flight lint at your pain.001 emission boundary. Reject the build if any required structured field is empty.
  • 5. Add an ASCII-fold pass over <Nm>, <StrtNm>, <TwnNm>, <CtrySubDvsn> with a documented locale-specific rule.
  • 6. UAT against each of your banks. Capture the pain.002 reasons and tune the per-bank rule pack.
  • 7. Cut over in production with a parallel-emit shadow lane for the first two weeks.

Why this is the timing forcing function

Treasury teams have a finite attention budget. November 14, 2026 is a fixed externally-imposed deadline. That is the forcing function — the reason a treasury platform engineer puts ISO 20022 work on the calendar this quarter rather than in 2027. The structured-address mandate is the smallest single change with the largest reject-prevention impact; it is the right wedge to lead with.

← All posts