Skip to main content

pain001-loader-mt101: MT101 → pain.001 loader

Convert legacy SWIFT MT101 requests for transfer into the flat records that the pain001 library validates and turns into ISO 20022 pain.001 XML. A single parse_mt101(text) call returns a list[dict] — one record per transaction — ready to feed straight into pain.001 generation.

Latest release: v0.0.2. The second deliverable of the MT→MX converter project (after pacs008-loader-mt103). SWIFT MT-MX coexistence ends in November 2025; this loader bridges the window where upstream systems still emit MT101 but downstream tooling expects pain.001.

Contents

Overview

pain001-loader-mt101 is a small, focused companion to the pain001 ISO 20022 Customer Credit Transfer Initiation library. It does one thing well: parse the mandatory + common-denominator MT101 grammar and hand back flat records whose keys are exactly the ones pain001 validates against the pain.001.001.09 JSON schema. Unlike an MT103 (one transfer), an MT101 can carry many transactions (repeating sequence B), so parse_mt101 returns one record per transaction. The correctness proof is that a realistic multi-transaction MT101 maps to records that pass SchemaValidator("pain.001.001.09").validate_batch(...) with zero errors.

Install

pain001-loader-mt101 requires Python 3.10+ and pulls in pain001 automatically.

pip install pain001-loader-mt101

Quick Start

from pain001_loader_mt101 import parse_mt101

mt101 = """:20:MSGREF2026070901
:21R:CUSTREF-A
:50H:/DE89370400440532013000
GLOBAL IMPORTS GMBH
100 HAFEN STRASSE
HAMBURG
:52A:DEUTDEFF
:30:260712
:21:TXN-REF-0001
:32B:EUR12345,67
:57A:CHASUS33
:59:/GB29NWBK60161331926819
ACME TRADING LTD
1 CORPORATE AVENUE
LONDON
:70:INVOICE 998877
:71A:SHA
:21:TXN-REF-0002
:32B:USD5000,00
:57A:BOFAUS3N
:59:/FR1420041010050500013M02606
LES FLEURS SARL
:70:CONTRACT 445566
:71A:OUR
"""

records = parse_mt101(mt101)
print(len(records))                       # 2
print(records[0]["payment_amount"])       # 12345.67
print(records[0]["charge_bearer"])        # SHAR
print(records[0]["nb_of_txs"])            # 2 (message-level)

# Validate against the real pain.001 schema:
from pain001.validation.schema_validator import SchemaValidator
total, valid, errors = SchemaValidator("pain.001.001.09").validate_batch(records)
assert valid == total and not errors

Field Mapping

parse_mt101(text: str) -> list[dict] — one record per sequence-B transaction. Sequence-A :50a: / :52a: apply to every transaction unless a sequence-B block overrides them.

MT101 field Seq Meaning pain.001 key Notes
:20: A Sender's Reference id, payment_information_id Message-level
:30: A Requested Execution Date (YYMMDD) requested_execution_date, date → YYYY-MM-DD; SWIFT sliding year window
:21: B Transaction Reference payment_id One per transaction
:32B: B Currency + Amount currency, payment_amount No value date; comma-decimal → float
:50H/50G/50F/50K/50A: A/B Ordering Customer debtor_name, debtor_account_IBAN, initiator_name Name from F (1/), K/H (name lines) or A (BIC); account from /IBAN line
:52A/52C/52D: A/B Account Servicing Institution debtor_agent_BIC BIC from A/C (or a BIC in D)
:57A/57C/57D: B Account With Institution creditor_agent_BIC BIC from A/C (or a BIC in D)
:59/59A/59F: B Beneficiary creditor_name, creditor_account_IBAN Name from plain 59, A (BIC) or F (1/)
:70: B Remittance Information remittance_information Whitespace-collapsed, capped at 140 chars
:71A: B Details of Charges charge_bearer OURDEBT, BENCRED, SHASHAR
(synthesised) nb_of_txs, ctrl_sum Count of, and total amount over, sequence-B blocks
(synthesised) payment_method, batch_booking, service_level_code TRF, False, SEPA

Assumptions and defaults

The pain.001 schema requires fields MT101 does not carry; these are synthesised (override downstream as needed):

  • payment_method = "TRF" — an MT101 requests credit transfers.
  • batch_booking = False.
  • service_level_code = "SEPA" — the schema enum admits only SEPA / URNS; override for non-SEPA payments.
  • charge_bearer = "SLEV" when :71A: is absent or unrecognised — the schema requires a charge bearer.
  • remittance_information = "NOTPROVIDED" when :70: is absent — the schema requires a non-empty value.
  • nb_of_txs / ctrl_sum describe the whole message (count of and total over sequence-B blocks) and are repeated on every record, as in a pain.001 group header.
  • date (message creation date) reuses :30: — MT101 has no separate creation timestamp. Two-digit years follow the SWIFT sliding window (00–79 → 20YY, 80–99 → 19YY).
  • initiator_name reuses the ordering-customer name.
  • Absent optional fields are omitted, not guessed. A schema-valid pain.001 record needs the ordering-customer name + IBAN (:50a:), the account-servicing and account-with BICs (:52a: / :57a:) and the beneficiary IBAN (:59a:); a well-formed MT101 carries all of these.
  • Hard requirements — only :20:, :30:, at least one transaction, and per transaction :21:, :32B: and a named beneficiary (:59:/:59A:/:59F:) raise ValueError. Everything else is best-effort; the loader never crashes on unexpected input.

Out of scope

This is the correct core MT101 → pain.001 mapping, not every optional field. Deliberately excluded in v0.0.2:

  • :23E: instruction codes, :25: / :28D: authorisation / sequence fields.
  • :33B: instructed currency/amount, :36: exchange rate, :21F: FX deal reference (FX legs).
  • :56a: intermediary and :51A: sending institutions.
  • :77B: regulatory reporting and :25A: charges account.
  • The SWIFT application header (blocks 1/2). This loader reads block 4 only (it unwraps a {4:...-} envelope if present).

Examples

Two runnable scripts live in examples/, exercised in CI:

Development

git clone https://github.com/sebastienrousseau/pain001-loader-mt101
cd pain001-loader-mt101
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest                            # 100% line + branch coverage gate
interrogate pain001_loader_mt101  # 100% docstring gate
mypy pain001_loader_mt101         # strict

Security

pain001-loader-mt101 parses a flat text format with no XML envelope — the XXE / billion-laughs surface lives upstream. Field regexes are anchored and bounded, so catastrophic backtracking is not a concern. See SECURITY.md.

License

Licensed under the Apache License, Version 2.0. Any contribution submitted for inclusion shall be licensed as above, without additional terms.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pain001_loader_mt101-0.0.65.tar.gz (45.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pain001_loader_mt101-0.0.65-py3-none-any.whl (17.3 kB view details)

Uploaded Python 3

File details

Details for the file pain001_loader_mt101-0.0.65.tar.gz.

File metadata

  • Download URL: pain001_loader_mt101-0.0.65.tar.gz
  • Upload date:
  • Size: 45.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pain001_loader_mt101-0.0.65.tar.gz
Algorithm Hash digest
SHA256 9046c7afa5ee7f1637897f450e307803d2313fb105baab9cda78dbd3cbde9b51
MD5 48c47966c3a78e490ec80614b4ed96f6
BLAKE2b-256 7c25419fae66238dcee42b870db3ee7ec6d92fd528df8a1f7f5026998b545acf

See more details on using hashes here.

Provenance

The following attestation bundles were made for pain001_loader_mt101-0.0.65.tar.gz:

Publisher: release.yml on sebastienrousseau/pain001-loader-mt101

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pain001_loader_mt101-0.0.65-py3-none-any.whl.

File metadata

File hashes

Hashes for pain001_loader_mt101-0.0.65-py3-none-any.whl
Algorithm Hash digest
SHA256 7ebd6abb62fe2e62ea262676a4167f8809b0faeff3a7140c47aa1e9421ec3864
MD5 5bc23749b763817715099c96474601cb
BLAKE2b-256 6b1f4449b6058a4aec6ab0418e1a1b342cb9f3a17d5919c08514b90d886a5718

See more details on using hashes here.

Provenance

The following attestation bundles were made for pain001_loader_mt101-0.0.65-py3-none-any.whl:

Publisher: release.yml on sebastienrousseau/pain001-loader-mt101

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.0.65 This release

2 files

0.0.62

2 files

0.0.61

2 files

0.0.60

2 files

0.0.2

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page