Convert legacy SWIFT MT940 bank statements to camt.053 ParsedDocument.
Project description
camt053-loader-mt940: MT940 → camt.053 loader
Convert legacy SWIFT MT940 bank statements into the same
camt053 data model as native camt.053 input. A single
parse_mt940(text) call returns a camt053.models.ParsedDocument,
ready for every downstream consumer in the suite (writer, validator,
reversal builder, MCP and LSP servers).
Latest release: v0.0.1. SWIFT MT940 is scheduled for retirement in November 2028. This loader bridges the 2-year window where banks still produce MT940 but downstream tooling expects camt.053.
Contents
- Overview
- Install
- Quick Start
- Supported Fields
- Examples
- The camt053 suite
- When not to use camt053-loader-mt940
- Development
- Security
- Documentation
- License
- Contributing
- Acknowledgements
Overview
camt053-loader-mt940 is a small, focused companion to the
camt053 ISO 20022 cash-management library. It does one thing
well: parse the common-denominator MT940 grammar shipped by EU and UK
commercial banks, and hand back the same ParsedDocument shape that
the camt.053 XML parser produces. The rest of the suite then works
unchanged.
This package is part of the camt053 suite, a set of independently
installable packages that share the camt053.services layer:
camt053- the core library (CLI + REST API)camt053-mcp- the Model Context Protocol server for AI agentscamt053-lsp- the Language Server Protocol server for editorscamt053-writer-xlsx- Excel.xlsxwriter for parsed statementscamt053-loader-mt940- this package, the MT940 loader
Install
camt053-loader-mt940 runs on macOS, Linux, and Windows and requires
Python 3.10+ and pip. It pulls in camt053 automatically and
has no other runtime dependencies.
pip install camt053-loader-mt940
Quick Start
from camt053_loader_mt940 import parse_mt940
mt940 = """:20:STMT-REF-1
:25:COBADEFFXXX/DE89370400440532013000
:28C:42/1
:60F:C260620EUR1000,00
:61:2606210621CR500,00NMSCREF1//CREF1
:86:Customer payment for invoice 123
:62F:C260621EUR1500,00
"""
document = parse_mt940(mt940)
print(document.msg_id)
# STMT-REF-1
print(document.statements[0].account.iban)
# DE89370400440532013000
print(document.statements[0].balances[0].amount)
# 1000.00
That's a camt053.models.ParsedDocument, ready to feed to
camt053-writer-xlsx (Excel output), the camt053 REST API,
or any other consumer in the suite.
Supported Fields
| Tag | Meaning | Mapped to |
|---|---|---|
:20: |
Transaction reference number | ParsedDocument.msg_id |
:25: |
Account identification (BIC/account or account) |
Statement.account (IBAN or proprietary other_id + optional servicer_bic) |
:28C: |
Statement / sequence number | Statement.id + Statement.electronic_seq_nb |
:60F: / :60M: |
Opening balance (Final / intermediary) | Balance with type_code="OPBD" |
:61: |
Statement line (booked entry) | Entry with amount, credit_debit_indicator, value_date, booking_date, reference, account_servicer_ref |
:86: |
Information to account owner | TransactionDetails.additional_info attached to the preceding entry |
:62F: / :62M: |
Closing balance | Balance with type_code="CLBD" |
:64: |
Closing available balance | Balance with type_code="CLAV" |
:65: |
Forward available balance | Balance with type_code="FWAV" |
Reversal detection
A :61: line whose debit/credit indicator is RD (reversal of
debit) or RC (reversal of credit) becomes an Entry with
reversal_indicator=True. Direct support for SEPA / NACHA / CBPR+
return-reason mapping is on the v0.0.2 roadmap.
Unknown fields
Unrecognised tags (e.g. :13D: creation timestamp, bank-specific
extensions) are silently ignored, so future SWIFT additions do
not break parsing. This follows Postel's law: be liberal in what you
accept.
Examples
Two runnable examples live in examples/:
01_minimal_parse.py- the smallest valid MT940 + parse + inspect.02_round_trip_to_xlsx.py- MT940 in, Excel.xlsxout (requirescamt053-writer-xlsx).
Both are exercised in CI on every commit.
The camt053 suite
camt053-loader-mt940 is part of a set of independently installable
packages built around the camt053 library — pick whichever
ones your stack needs:
| Package | Role |
|---|---|
camt053 |
Core library + CLI + FastAPI REST API |
camt053-mcp |
Model Context Protocol server (for AI agents) |
camt053-lsp |
Language Server Protocol server (for editors) |
camt053-writer-xlsx |
Excel .xlsx writer for parsed statements |
camt053-loader-mt940 |
SWIFT MT940 → camt.053 loader (this package) |
flowchart LR
A["MT940 text"] -->|parse_mt940| B["camt053-loader-mt940"]
B -->|ParsedDocument| C["camt053"]
C -->|writer / validator / reversal / MCP / LSP| D["Downstream consumers"]
When not to use camt053-loader-mt940
- You already have native camt.053 input. Use the camt053 core parser directly — this loader is the bridge for legacy MT940-only data sources, not an alternative for native camt.05x.
- You need MT941 / MT942 (intraday-balance / intermediate-statement messages). Out of scope today; the data model supports adding them if you'd like to contribute a separate loader.
- You need bank-specific
:86:sub-field parsing (e.g. Deutsche Bank's?20/?30/?32GVC codes). The raw:86:value is preserved verbatim inTransactionDetails.additional_info; downstream tooling can parse it if needed. - You need direct ISO return-reason mapping for
RD/RClines. Currentlyreversal_indicator=Trueis set; mapping to ISOExternalReturnReasonCodeis on the v0.0.2 roadmap. - Your MT940 is PGP / GPG encrypted. Decrypt upstream and pass the plaintext to the loader.
Development
git clone https://github.com/sebastienrousseau/camt053-loader-mt940
cd camt053-loader-mt940
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest # 100% line + branch coverage gate
interrogate camt053_loader_mt940 # 100% docstring gate
mypy camt053_loader_mt940 # strict
Security
camt053-loader-mt940 parses a flat text format with no XML envelope
— the XXE / billion-laughs surface lives upstream in the camt053
core (defusedxml + xml_guard). Field regexes are anchored and
bounded, so catastrophic backtracking is not a concern. Reporting
practice, supported versions, and supply-chain posture (PyPI Trusted
Publishing, sigstore attestations, signed tags) are documented in
SECURITY.md. Vulnerabilities go via GitHub Private
Vulnerability Reporting, not public issues.
Documentation
README.md— this fileCHANGELOG.md— release notesSECURITY.md— disclosure + supported versionsSUPPORT.md— how to get helpMAINTAINERS.md— who can mergeexamples/— runnable scripts, exercised in CI
License
Licensed under the Apache License, Version 2.0. Any contribution submitted for inclusion shall be licensed as above, without additional terms.
Contributing
Contributions are welcome. Open an issue or PR on the repository.
Acknowledgements
Built on the camt053 ISO 20022 Bank Statement library. The
MT940 grammar follows the SWIFT User Handbook MT940 specification and
the common-denominator subset shipped by major EU and UK commercial
banks.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file camt053_loader_mt940-0.0.8.tar.gz.
File metadata
- Download URL: camt053_loader_mt940-0.0.8.tar.gz
- Upload date:
- Size: 21.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6696aed0c99e9bc60046826655a419a6e115c0694d2c49533268844b968131e1
|
|
| MD5 |
6f4c89e338da5085dbb04519f9257711
|
|
| BLAKE2b-256 |
ec4be0ee4aab546f21a69c0ef1ec4da2461b6ea74fd6febb7029fa9a501d7216
|
Provenance
The following attestation bundles were made for camt053_loader_mt940-0.0.8.tar.gz:
Publisher:
release.yml on sebastienrousseau/camt053-loader-mt940
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
camt053_loader_mt940-0.0.8.tar.gz -
Subject digest:
6696aed0c99e9bc60046826655a419a6e115c0694d2c49533268844b968131e1 - Sigstore transparency entry: 1970333148
- Sigstore integration time:
-
Permalink:
sebastienrousseau/camt053-loader-mt940@0a4acc4cbe94feceaa635a2e8afe81347e5105a6 -
Branch / Tag:
refs/tags/v0.0.8 - Owner: https://github.com/sebastienrousseau
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0a4acc4cbe94feceaa635a2e8afe81347e5105a6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file camt053_loader_mt940-0.0.8-py3-none-any.whl.
File metadata
- Download URL: camt053_loader_mt940-0.0.8-py3-none-any.whl
- Upload date:
- Size: 14.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ebdc19b89b8a0b5bedc3f965760ac9bcace0dc83abc82c5217d597f66d962e77
|
|
| MD5 |
d4f1b7a67a8f7c0cc982e46a1078ff00
|
|
| BLAKE2b-256 |
5449712fd9424f88205aa63830f5cbd5325331ca10d98bb61a5de4de7b29330d
|
Provenance
The following attestation bundles were made for camt053_loader_mt940-0.0.8-py3-none-any.whl:
Publisher:
release.yml on sebastienrousseau/camt053-loader-mt940
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
camt053_loader_mt940-0.0.8-py3-none-any.whl -
Subject digest:
ebdc19b89b8a0b5bedc3f965760ac9bcace0dc83abc82c5217d597f66d962e77 - Sigstore transparency entry: 1970333281
- Sigstore integration time:
-
Permalink:
sebastienrousseau/camt053-loader-mt940@0a4acc4cbe94feceaa635a2e8afe81347e5105a6 -
Branch / Tag:
refs/tags/v0.0.8 - Owner: https://github.com/sebastienrousseau
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0a4acc4cbe94feceaa635a2e8afe81347e5105a6 -
Trigger Event:
push
-
Statement type: