Skip to main content

Convert legacy SWIFT MT101 requests for transfer to ISO 20022 pain.001 flat records.

Project description

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.1. 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.1:

  • :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.

Project details


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.1.tar.gz (23.8 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.1-py3-none-any.whl (16.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pain001_loader_mt101-0.0.1.tar.gz
  • Upload date:
  • Size: 23.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pain001_loader_mt101-0.0.1.tar.gz
Algorithm Hash digest
SHA256 9c26e071e91caef2bece953876d6b16115df3e4164bbea1fa5625eb347803916
MD5 bd0884bf77964beb17a983248f78ab26
BLAKE2b-256 5eeec0433173ceaffe1d494b8b44cf64aa9639d143de05af9ccf53f2d7812244

See more details on using hashes here.

Provenance

The following attestation bundles were made for pain001_loader_mt101-0.0.1.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.1-py3-none-any.whl.

File metadata

File hashes

Hashes for pain001_loader_mt101-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fefe56f809b3769ef41b3b60ab8490ca0a9e49d80bbc5c392c3e09cfa9b11ca3
MD5 fb7d82c492849c60ed3e1ef2c4ba7156
BLAKE2b-256 5a8df9d725729e43e58ea82f9ee7206007b48f5f381970c3c2312c11acf0026b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pain001_loader_mt101-0.0.1-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.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page