TL;DR: SWIFT will retire MT940 by November 2028. Bank Statement Parser handles both MT940 and CAMT.053 with a single API, so your parsing pipeline works during the transition and after.
Why This Migration Matters
SWIFT is retiring legacy MT message formats in favour of the richer ISO 20022 standard. For treasury and finance teams, this means your bank statement processing pipelines must evolve from MT940 to CAMT.053 before the hard deadlines.
SWIFT Migration Timeline
| Date | Milestone | Impact |
|---|---|---|
| November 2025 | MT-to-MX coexistence ended for cross-border payments | PACS messages are now ISO 20022 only |
| November 2026 | Structured/hybrid addresses mandatory; MT101 multi-instruction rejected; Case Management Phase 1 | Address formats must comply; some MT messages will be rejected |
| Late 2026 | Opt-in begins for receiving CAMT.052/.053/.054 | Financial institutions can start receiving native ISO statements |
| November 2027 | All FIs must receive CAMT.053 natively | SWIFT stops converting MT format to ISO; your systems must parse CAMT directly |
| November 2028 | MT940/MT942/MT950/MT900/MT910 fully retired | Legacy statement formats no longer available; CAMT.052/.053/.054 are the only option |
What Changes for Your Code
Before: MT940 Only
from bankstatementparser import Mt940Parser
parser = Mt940Parser("statement.mt940")
df = parser.parse()
After: Both Formats with Auto-Detection
from bankstatementparser import create_parser, detect_statement_format
fmt = detect_statement_format("statement.xml") # or .mt940
parser = create_parser("statement.xml", fmt)
df = parser.parse() # Same DataFrame schema regardless of format
The detect_statement_format() function identifies whether the file is MT940, CAMT.053, PAIN.001, or any other supported format. The create_parser() function returns the correct parser. Your downstream code works identically regardless of the source format.
CAMT.053 vs MT940: Key Differences
| Feature | MT940 | CAMT.053 |
|---|---|---|
| Data richness | Limited fields | 3-5x more data per transaction |
| Character set | Limited (SWIFT charset) | Full Unicode |
| Structure | Flat text with tags | XML with namespaces |
| Balance reporting | Opening/closing only | Multiple balance types |
| References | Single reference field | Multiple reference types |
| Currency handling | Basic | Full multi-currency with exchange rates |
How Bank Statement Parser Helps
- Unified API: Parse MT940, CAMT.053, and PDF statements with the same workflow, producing consistent DataFrame output.
- Auto-detection: No need to know the format in advance.
detect_statement_format()identifies it automatically. - Hybrid PDF pipeline: Banks that provide PDF-only statements during the transition are handled by
smart_ingest()with automatic balance verification. - Namespace-agnostic: Handles any CAMT.053 variant (001.02, 001.04, or bank-specific wrappers) without configuration.
- Multi-currency verification:
verify_balance_multi_currency()runs the Golden Rule per currency group — essential for multi-currency CAMT statements. - Streaming: Process large CAMT files (50 MB+, 50K+ transactions) with bounded memory.
- Ledger export: Export directly to hledger or beancount journal format for treasury accounting.
- Migration testing: Run both parsers side-by-side on the same date range to verify output consistency before switching.
Getting Started
pip install bankstatementparser
from bankstatementparser import create_parser, detect_statement_format
# Works with MT940 today, CAMT.053 tomorrow, PDF anytime
for file in bank_statement_files:
fmt = detect_statement_format(file)
parser = create_parser(file, fmt)
df = parser.parse()
process(df) # Your code doesn't change
For PDF statements from banks that don't yet offer structured CAMT exports:
from bankstatementparser.hybrid import smart_ingest
result = smart_ingest("statement.pdf")
assert result.verification.status == "VERIFIED"