Post-cutover triage · SWIFT MX/CBPR+ active since 14 Nov 2026

Your bank started rejecting your wires. Here’s why — and how to fix it in 24 hours.

The SWIFT MX/CBPR+ structured-address mandate took effect 2026-11-14. Mid-market ERPs that emit free-text <AdrLine> addresses are now bank-rejectable. iso-compliant is the file-readiness layer that solves this on the same day a customer signs up — no migration, no contract negotiation, no sales-cycle delay.

If you arrived here from a pain.002 reject report, skip to the reason-code table first — that’s the fastest path from "is this me?" to "yes, here’s the fix."

Diagnosis

First, confirm it’s the mandate.

Three cards. Read them in order. By the end you will know which pain.002 reason codes you’re seeing, whether the structured-address mandate is the actual root cause, and what the minimal fix looks like.

Card 1 · What the codes mean

Your bank’s pain.002 rejection codes — translated.

The pain.002 file your bank returns carries a <StsRsnInf><Rsn><Cd> element with one of the ISO 20022 reason codes below. The structured-address subset overlaps with several umbrella codes — banks vary on which they raise.

AC03
Creditor account number invalid. Often surfaces as the umbrella code when the <PstlAdr> block on the creditor party is malformed — bank IGs vary on whether they raise AC03 vs a more specific code.
BE05
Identification of the end customer is not consistent with the associated account number. The structured-address subset: <Nm> + <PstlAdr> on Dbtr or Cdtr fails the bank’s screening because the address is still in <AdrLine> form.
FF01
File format invalid or incompatible with the bank IG. After 2026-11-14 this is the most common code for a pain.001 that still emits unstructured <AdrLine> elements.
DT01
Invalid date — commonly the requested execution date is in the past. Unrelated to the address mandate, but it often co-occurs in the same pain.002 batch because rejected files are re-queued and miss their execution window.
NARR
Narrative / free-text reason. Some bank IGs (Crédit Agricole, BNP Connexis) return a NARR reason with a free-text body like "PstlAdr structured form required" instead of a structured code. Grep the AddtlInf field.

Full pain.001 / pain.002 field reference at /docs/pain-001 and /docs/pain-008.

Card 2 · Are you actually affected?

Five questions. Two yeses = yes.

The mandate doesn’t touch every business equally. Run through these; if you answer "yes" to any two, you’re in the affected population.

  1. 01

    Do you emit pain.001 or pain.008 files to a bank — directly, via EBICS, via SFTP, or via your ERP’s payment module?

    If you don’t emit ISO 20022 today, the mandate doesn’t reach you yet. If your ERP emits it on your behalf, you are still affected — the bank rejects the file, not the ERP.

  2. 02

    Do you store customer or vendor addresses as address_line_1 / address_line_2 / city / postal_code in your database?

    The hybrid shape (street + house number squashed into address_line_1) is the most common failure mode. The <StrtNm> and <BldgNb> fields must be separated.

  3. 03

    Have you received pain.002 reports from your bank with RJCT status messages dated on or after 2026-11-14?

    The cutover was a hard date, not a phased rollout for new files. Files submitted before 2026-11-14 but processed after may also reject — some IGs check at acceptance, not submission.

  4. 04

    Are any of your customer’s or vendor’s banks on the SWIFT MX/CBPR+ cross-border rail?

    Banks with active rule-pack work on iso-compliant: UBS Switzerland, PostFinance Switzerland, Deutsche Bank, BNP Paribas, ING Bank, Crédit Agricole CIB. The mandate also reaches the planned tier: HSBC UK, JPMorgan Chase, Citi, Bank of America, and any other bank routing through SWIFT FINplus.

  5. 05

    Do you batch-emit payroll, supplier, or refund files — i.e., a single reject halts dozens or hundreds of transactions?

    Some bank IGs reject the entire <PmtInf> block when a single <Cdtr> address is malformed; others fail per-transaction. Either way, the operational cost of a reject scales with batch size.

Card 3 · The fix in 24 hours

Three steps. None of them is "rewrite the ERP."

  1. 01

    Lint your customer database.

    Install @iso-compliant/mcp-server in your IDE or CI, then run isocompliant.structured_address_lint against your customer / vendor / employee tables. Output: a CSV of rows that will reject, with the specific missing field per row.

  2. 02

    Restructure freeform addresses.

    POST your failing rows to /v1/address/restructure. The endpoint is deterministic and returns a confidence label (high / medium / low) per row. Route high-confidence results into the structured columns; queue medium and low for human review.

  3. 03

    Emit pain.001 through the bank-validated path.

    Call isocompliant.sepa.credit_transfer (MCP) or POST /v1/iso20022/pain.001. Pin your bank’s rule pack and the response is a pain.001 XML that passes that bank’s IG validation before it leaves our pipeline.

Honest pricing

The fix costs less than the next reject.

iso-compliant prices per document, on a volume curve. First 100 documents per month are free, no card. Beyond that:

  • 1 – 9,999 docs/mo: $0.050 / doc
  • 10,000 – 99,999 docs/mo: $0.030 / doc
  • 100,000 – 999,999 docs/mo: $0.015 / doc
  • 1M – 9.9M docs/mo: $0.008 / doc
  • 10M+ docs/mo: $0.005 / doc

Never a percentage of transaction volume. Never a per-seat fee. The full calculator with annualised cost and DIY break-even math is at /pricing.

We shipped this

Three calls. Working pain.001 out the other side.

No SDK lock-in, no proprietary file format. The MCP server is a thin wrapper over the same HTTP API. Both paths emit deterministic ISO 20022 XML.

1 · Install the MCP server

# In your IDE (Claude Desktop, Cursor, Continue.dev)
npm install -g @iso-compliant/mcp-server

# Then add to your MCP config:
{
  "iso-compliant": {
    "command": "isocompliant-mcp",
    "env": { "ISOCOMPLIANT_API_KEY": "sk_live_..." }
  }
}

Full installation guide: /docs/mcp.

2 · Validate an IBAN

curl -X POST https://api.iso-compliant.com/v1/iban/validate \
  -H "Authorization: Bearer $ISOCOMPLIANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"iban": "CH9300762011623852957"}'

# → { "valid": true, "country": "CH", "bank_code": "00762",
#     "is_qr_iban": false, "format": "CH21" }

Deterministic mod-97 + per-country BBAN format check. Free tier covers IBAN validation generously.

3 · Emit a structured-address pain.001

curl -X POST https://api.iso-compliant.com/v1/iso20022/pain.001 \
  -H "Authorization: Bearer $ISOCOMPLIANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "bank": "ubs-ch",
    "debtor": {
      "name": "Acme AG",
      "iban": "CH9300762011623852957",
      "address": {
        "street_name": "Bahnhofstrasse",
        "building_number": "45",
        "post_code": "8001",
        "town_name": "Zurich",
        "country": "CH"
      }
    },
    "transactions": [{
      "amount": 1250.00,
      "currency": "CHF",
      "creditor": {
        "name": "Müller GmbH",
        "iban": "DE89370400440532013000",
        "address": {
          "street_name": "Maximilianstrasse",
          "building_number": "12",
          "post_code": "80539",
          "town_name": "Munich",
          "country": "DE"
        }
      },
      "remittance_info": "Invoice 2026-1187"
    }]
  }'

# → 200 OK
#   Content-Type: application/xml
#   <Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09">
#     ... structured-address pain.001, validated against UBS-CH IG ...
#   </Document>

The response is XML you can pipe straight to your EBICS T client or SFTP uploader. We do not hold your bank credentials or your EBICS keys.

Where iso-compliant sits in your stack

┌─────────────────────┐   POST /v1/iso20022/pain.001
│ Your ERP / payroll  │   (or MCP tool call)
│ scheduler / batcher │ ─────────────────────────┐
└─────────────────────┘                          │
         │                                       ▼
         │                          ┌──────────────────────────┐
         │                          │  iso-compliant pipeline  │
         │                          │  ─────────────────────── │
         │                          │  · address lint          │
         │                          │  · bank rule pack apply  │
         │                          │  · pain.001 build        │
         │                          │  · ASCII fold + sign     │
         │                          └──────────────────────────┘
         │                                       │
         │   pain.001 XML (validated, signed)    │
         │ ◀─────────────────────────────────────┘
         ▼
┌────────────────────────────┐
│ Your existing EBICS / SFTP │  ───→  Your bank
│ client (Stetwin, openEBICS,│        (UBS, PostFinance,
│ in-house, etc.)            │         Deutsche Bank, ...)
└────────────────────────────┘

iso-compliant is the file-shaping layer, not the channel layer. You keep your EBICS / SFTP integration with the bank; we replace the part of your stack that writes the XML.

Endpoint references: pain.001 · pain.008 · camt.053 · reconciliation.

FAQ

Ten honest answers.

Phrased the way we would answer them in a discovery call. No hand-waving on SLAs we haven’t signed; no claims of bank endorsement we don’t have.

Do I need to change anything in my code, or just my data?

Most teams need both, but the data is the bigger lift. The code change is small: replace the <AdrLine> writer in your pain.001 builder with a structured-address writer that populates <StrtNm>, <BldgNb>, <PstCd>, <TwnNm>, <Ctry>. The data change is bigger: your existing customer / vendor / payroll table likely has freeform address strings, and those need to be parsed into structured fields. POST /v1/address/restructure does the parse deterministically and returns a confidence label; route high-confidence results into the new structured columns and queue medium / low for human review.

Will my bank accept files emitted via iso-compliant immediately?

If your bank is on the shipped or in-development tier of our rule-pack registry, yes — the pain.001 we emit is validated against that bank’s IG before it leaves our pipeline. If your bank is on the planned tier or off our registry entirely, we still emit a SWIFT-MX-baseline-compliant file; you should run it through your bank’s test environment first. We will not claim a bank "accepts" us when we have no signed attestation from that bank.

What about banks not in your rule-pack matrix yet?

We ship a SWIFT MX / CBPR+ baseline rule pack that satisfies the structured-address mandate at the SWIFT FINplus layer. If your bank layers additional rules on top — a country-sub-division requirement, an IBAN-country consistency check, a building-name fallback — those overlays may need a bank-specific rule pack. Email engineering with the bank name and your IG link and we will scope it; the standing target is two weeks from IG receipt to shipped rule pack.

How does this work with my existing EBICS/SFTP integration?

iso-compliant emits the pain.001 XML; you submit it through whatever channel your bank requires. The most common pattern: your ERP or scheduler calls POST /v1/iso20022/pain.001, persists the returned XML to disk, then hands it to your existing EBICS T client (e.g., openEBICS, Stetwin) or SFTP uploader. You keep the channel layer; we replace the file-shaping layer. We do not currently emit EBICS frames or hold EBICS bank keys.

What’s the SLA if iso-compliant is part of my payment-emission path?

The Free tier has no SLA — it is for evaluation and low-volume use. The Production tier carries a standard commercial availability commitment with monthly credits for breaches; the exact percentage and credit table are in the order form. For embedded payment-emission paths where iso-compliant sits in the critical path of payroll or supplier runs, talk to engineering about an embedded SLA and a dedicated on-call rotation. We will not commit to numbers on a public page that we haven’t reviewed with you against your traffic profile.

Can I sign up for free first to test?

Yes. The Free tier gives you 100 documents per month — enough to validate every pain.001 / pain.008 emission path you care about and run a UAT against your bank’s test environment. No credit card. No expiry. When you cross the threshold, the API is identical — you change a billing flag, not your integration code.

My ERP vendor told me they’ll ship the structured-address fix in their next release. Should I wait?

Two questions to ask the vendor: (1) what is the actual release date and is it before your next batch run, and (2) does their fix include a one-time backfill of your existing address data, or only new records going forward? If the answer to (1) is "later than your next payroll" or (2) is "new records only", you need a bridge. iso-compliant is a deterministic file-shaping layer in front of your bank — it does not replace the ERP fix, it absorbs the gap until the ERP fix lands and runs against your historical data.

We already passed the bank’s UAT before 2026-11-14. Why are we rejecting now?

Three common reasons. First, some banks ran UAT against a permissive validator and tightened it at the cutover — your test pain.001 passed, your production one doesn’t. Second, UAT often runs with synthetic clean data; production runs against your actual messy customer database. Third, some IGs added per-bank overlays in the final two weeks before the cutover (HSBC’s building-name fallback, Deutsche Bank’s country-sub-division). Pull the pain.002 file, find the AddtlInf or NARR field, and the specific rule violated should be in there.

How is this different from just using my bank’s portal to enter payments manually?

For one-off payments, manual entry is fine. For payroll, supplier batches, or any automated emission path, manual entry is operationally untenable — you lose batching, audit trails, idempotency, and reconciliation. iso-compliant is the file-readiness layer for systems that need to emit pain.001 at scale; the bank portal is the fallback when those systems break.

What happens to our data — do you store the addresses we lint?

The free /address-lint widget on the structured-address page is pure browser-side — no network call, no storage. The /v1/address/restructure API endpoint logs a hash of the input for billing-counter purposes, not the input itself; the structured output is returned and discarded after the response. For full pain.001 emission, the file is persisted (encrypted at rest) for the configured retention window so you can replay or audit; the retention default is 30 days, configurable per workspace.

Start free. Ship today.

Stop the rejects on the next batch run.

100 documents per month. No credit card. No SLA on Free (read the FAQ for the honest version). Full validation, structured-address output, deterministic XML.

Already at scale? Reach engineering directly: hello@iso-compliant.com. For vulnerability reports, see /legal/security (security@iso-compliant.com).