pain001-loader-mt101
Turns SWIFT MT101 requests for transfer into the flat records pain001 validates and writes as ISO 20022 pain.001.
Contents
Getting started
- Install —
pip, one runtime dependency - Requirements — toolchain floor, platforms
- Quick Start — one call from MT101 text to schema-valid pain.001 records
The pain001-loader-mt101 ecosystem
- The pain001-loader-mt101 ecosystem — the pain001 core, its MCP and LSP servers and its loaders
Library reference
- Capabilities at a glance — the current surface by theme
- Ecosystem comparison — short matrix; full table at
docs/COMPARISON.md - Benchmarks — headline numbers; full table at
docs/BENCHMARKS.md - Features — module-level capability list
- Configuration — core options
- Examples — runnable example index
Operational
- When not to use pain001-loader-mt101 — limitations
- Development — make targets, fuzzing, CI
- Security — guarantees and compliance
- Documentation — all reference docs
- Stability guarantees — SemVer axis, output stability, minimum toolchain discipline
- License
Install
As a Python library
pip install pain001-loader-mt101
Latest release: v0.0.74: impossible
:30:dates and:32B:amounts outside the SWIFT form are rejected, released in lockstep with the pain001 suite, for Python 3.10+.
The package pulls in pain001 (0.0.74 or newer, below 1) and
nothing else. There is no command-line entry point: it is a library.
Requirements
- Python 3.10 or newer, tested in CI on 3.10, 3.11, 3.12, 3.13 and 3.14 on Linux (toolchain policy).
pain0010.0.74 or newer on the 0.x line.- Pure Python, so any platform CPython runs on; CI exercises Linux only.
Quick Start
from pain001.validation.schema_validator import SchemaValidator
from pain001_loader_mt101 import parse_mt101
mt101 = """:20:MSGREF2026070901
:30:260712
:50H:/DE89370400440532013000
GLOBAL IMPORTS GMBH
:52A:DEUTDEFF
:21:TXN-REF-0001
:32B:EUR12345,67
:57A:CHASUS33
:59:/GB29NWBK60161331926819
ACME TRADING LTD
:70:INVOICE 998877
:71A:SHA
"""
records = parse_mt101(mt101)
print(len(records)) # 1
print(records[0]["payment_amount"]) # 12345.67
print(records[0]["charge_bearer"]) # SHAR
total, valid, errors = SchemaValidator("pain.001.001.09").validate_batch(records)
assert valid == total and not errors
parse_mt101 returns one record per sequence-B transaction, with the keys
pain001 validates against the pain.001.001.09 schema, so the records go
straight into pain.001 generation.
The pain001-loader-mt101 ecosystem
This package is one of the pain001 suite. The core, its MCP and LSP servers and its two loaders release together at one version, core first. New to the target format? What is pain.001? explains it, and https://pain001.com/mt101-migration/ sets out the MT101 migration case.
| Component | Purpose | Use case |
|---|---|---|
pain001 |
Generates and validates ISO 20022 payment files from tabular data | The core library these records feed |
pain001-loader-mt101 |
SWIFT MT101 text to pain.001 flat records | A treasury or ERP system still emits MT101 |
pain001-loader-xlsx |
Excel loader plugin for .xlsx / .xlsm |
Payment batches kept in spreadsheets |
pain001-mcp |
MCP server exposing pain001 validation, generation and inspection | Agent workflows over payment files |
pain001-lsp |
Language server for pain001 input files | Editor support |
Capabilities at a glance
| Area | Capability | Status |
|---|---|---|
| Parsing | Sequence A (:20:, :30:, :50a:, :52a:) and repeating sequence B (:21:, :32B:, :50a:, :52a:, :57a:, :59a:, :70:, :71A:) |
Supported |
| Envelope | A raw {4:...-} block 4, CRLF or LF |
Supported |
| Output | One pain.001 record per transaction; nb_of_txs and ctrl_sum on each |
Supported |
| Validation | Missing :20:, :30:, :21:, :32B: or named beneficiary |
Rejected with ValueError |
| Validation | :30: dates that do not exist, :32B: amounts outside the SWIFT form |
Rejected since 0.0.74 |
| FX legs | :33B:, :36:, :21F: |
Not mapped |
| Header blocks | SWIFT blocks 1 and 2 | Not read |
Ecosystem comparison
pain001 takes rows (CSV, SQLite, JSON, JSONL, Python records) and
pain001-loader-xlsx takes spreadsheets. This package is the path for
MT101 text. A search of likely names on PyPI found no other MT101 parser;
the nearest is mt103, which reads MT103 only.
| Project | Input | Records per input | Licence |
|---|---|---|---|
| pain001-loader-mt101 | MT101 text | One per transaction | Apache-2.0 OR MIT |
pain001-loader-xlsx |
.xlsx / .xlsm |
One per row | Apache-2.0 OR MIT |
mt103 1.1.1 |
MT103 text | One message | GPL-3.0-or-later |
See docs/COMPARISON.md for the evidence and complete matrix.
Benchmarks
benches/bench_parse_mt101.py grows one message from 10 to 5,000
transactions and reports microseconds per transaction and a growth
exponent. The number to read is the shape: per-transaction cost should
stay flat. Nothing asserts a time; tests/test_benchmarks.py asserts the
scaling ratio, and CI runs the benchmark with --quick.
| Scenario | Result | Environment |
|---|---|---|
| One MT101, 1,000 transactions (145 KB) | 14.61 ms, 14.61 µs/txn | Apple A18 Pro, CPython 3.12.15, shared machine under load |
| One MT101, 5,000 transactions (725 KB) | 89.34 ms, 17.87 µs/txn | same run |
| Growth exponent, 10 to 5,000 transactions | 1.06 (linear) | same run |
See docs/BENCHMARKS.md for methodology and full results.
Features
-
One function.
parse_mt101(text)returnslist[dict], one record per sequence-B transaction. Sequence-A:50a:and:52a:apply to every transaction unless a sequence-B block overrides them. -
Field mapping.
MT101 field Seq Meaning pain.001 key :20:A Sender's reference id,payment_information_id:30:A Requested execution date ( YYMMDD)requested_execution_date,date:21:B Transaction reference payment_id:32B:B Currency and amount currency,payment_amount:50H/G/F/K/A:A/B Ordering customer debtor_name,debtor_account_IBAN,initiator_name:52A/C/D:A/B Account servicing institution debtor_agent_BIC:57A/C/D:B Account with institution creditor_agent_BIC:59/59A/59F:B Beneficiary creditor_name,creditor_account_IBAN:70:B Remittance information remittance_information(140 characters at most):71A:B Details of charges charge_bearer(OURtoDEBT,BENtoCRED,SHAtoSHAR) -
Synthesised fields, documented so callers can override them:
payment_method="TRF",batch_booking=False,service_level_code="SEPA",charge_bearer="SLEV"when:71A:is absent or unknown,remittance_information="NOTPROVIDED"when:70:is absent;datereuses:30:andinitiator_namethe ordering customer's name. -
Absent optional fields are omitted, not guessed.
-
Errors name the field. Every
ValueErrornames the MT101 field that is missing or malformed.
Configuration
None. parse_mt101 takes the text and nothing else; the synthesised
defaults above are fixed, and callers override them on the returned
records.
Examples
examples/01_minimal_parse.py: parse a two-transaction MT101 and print each record, with names, IBANs and BICs redacted.examples/02_validate_against_pain001.py: parse, then validate against thepain.001.001.09schema.
Both run in CI on every pull request.
When not to use pain001-loader-mt101
- Your batch is already rows or a spreadsheet. Use the
pain001core loaders orpain001-loader-xlsx. - You have MT103. That is a single transfer going to pacs.008; see
pacs008-loader-mt103. - You need FX legs, regulatory reporting or authorisation fields
(
:33B:,:36:,:21F:,:77B:,:25:,:28D:,:23E:): they are not mapped. - You need the SWIFT header blocks. Only block 4 is read.
- Your payments are not SEPA.
service_level_codedefaults toSEPA; setURNSon the records yourself. - Your MT101 arrives PGP-encrypted. Decrypt it first; the loader takes plaintext.
Development
git clone https://github.com/sebastienrousseau/pain001-loader-mt101
cd pain001-loader-mt101
make install # .venv from the hash-pinned requirements/test.txt and lint.txt
make check
make check runs ruff, mypy in strict mode, the complexity ceilings, the
version-agreement check, pytest with a 100% line and branch coverage gate
(Hypothesis fuzzing included), interrogate at 100% docstring coverage and
the examples. CI also runs the dependency audit (pip-audit over every
requirements/*.txt), Atheris fuzzing of parse_mt101 (two minutes per
change, thirty weekly, seeded from fuzz/corpus/), mutation testing of
the parser, CodeQL, OpenSSF Scorecard, the DCO check and a daily Suite
Consistency check against PyPI. See CONTRIBUTING.md.
Security
The loader parses text: it reads no files, opens no sockets and parses no
XML. Input outside the grammar (including dates that do not exist and
amounts outside the SWIFT form) is rejected with a ValueError naming
the field. Cap the size of untrusted input before parsing it. The parser is fuzzed with Atheris in CI and
with Hypothesis in the test suite. Releases are published from a signed
tag through PyPI Trusted Publishing, with SLSA build provenance, sigstore
signatures and SPDX and CycloneDX SBOMs.
Report vulnerabilities according to SECURITY.md.
Documentation
User manual · API reference · Developer guide · Family map · Changelog · Policies · Architecture · Decisions
Stability guarantees
The project is pre-1.0 and versions advance in 0.0.1 steps, in lockstep
with the pain001 suite. The breaking axis is parse_mt101's signature and
the records it produces for a given input: a change to that output is
breaking even when no signature moves, and the changelog calls it out
(0.0.74 rejecting impossible :30: dates and :32B: amounts with a dot).
The Python floor moves only as described in the
toolchain policy.
License
This project is dual-licensed under either:
- Apache License, Version 2.0 (
LICENSE-APACHEor https://www.apache.org/licenses/LICENSE-2.0) - MIT License (
LICENSE-MITor https://opensource.org/licenses/MIT)
at your option. Dependencies keep their own licences.
Metadata
Release files for pain001-loader-mt101 0.0.74
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pain001_loader_mt101-0.0.74.tar.gz | 639.7 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pain001_loader_mt101-0.0.74-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 659.6 kB
Release files / pain001_loader_mt101-0.0.74.tar.gz
| Download URL | pain001_loader_mt101-0.0.74.tar.gz |
|---|---|
| Size | 639.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
123b36fadbdd5637b9609bc1cec4f033aa39e2209caf5634e10596c2f570a8e4
|
|
BLAKE2b-256 checksum How to use checksums |
bdb13cc57d11608dc26e3047c0aff973a76a0c6efb70b0fa587c3c7c806a7107
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logRelease files / pain001_loader_mt101-0.0.74-py3-none-any.whl
| Download URL | pain001_loader_mt101-0.0.74-py3-none-any.whl |
|---|---|
| Size | 19.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9c62e5036ff3acc7601751a2ec94ac09d19a794d029b4c4014864e16cc854f53
|
|
BLAKE2b-256 checksum How to use checksums |
7cdc01ae0c31e9137df98778835de538f1b1055a8dad27034985ff83d6ea642e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logSecurity for pain001-loader-mt101 0.0.74
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for pain001_loader_mt101-0.0.74.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.