Skip to main content

A lightweight Python package to flatten complex ISO 20022 XML messages into usable data.

Project description

OpenPurse Logo

OpenPurse

The Ultra-Lightweight, Production-Grade Engine for ISO 20022 and SWIFT MT Financial Messaging.

PyPI version License Python Versions Ruff


⚡️ The OpenPurse Mission

Financial messaging is transitioning from archaic, line-based SWIFT MT to deeply nested, namespace-heavy ISO 20022 (MX) XML. Engineers are often caught in the middle, forced to deal with massive XML schemas, fragmented versions, and complex reconciliation logic.

OpenPurse solves this by providing a unified, zero-bloat API that flattens this complexity into clean, structured Python objects.

  • 🚀 Performance-First: Built with C-optimized lxml for lightning-fast parsing even under heavy load.
  • 🛡️ Production-Hardened: Strict validation for IBANs (Modulo-97) and BICs (ISO 9362).
  • 🔌 Schema-Dynamic: Not just one version. OpenPurse dynamically detects and supports 770+ ISO namespaces across Cash Management, Payments Initiation, and Securities.
  • 📦 Zero-Dependency Core: No pandas, no pydantic. Just pure, native Python @dataclasses.

🏗️ Technical Philosophy: The @dataclass Way

Most financial libraries overwhelm you with nested dictionaries or heavy ORM-like objects. OpenPurse uses the Uniform Data Model (UDM) philosophy:

  1. Flattening: We extract only the most critical fields needed for reconciliation and payment processing.
  2. Immutability: Once parsed, messages are stored in lightweight, typed @dataclasses.
  3. Lossless-Ready: While we flatten for convenience, we preserve raw data integrity (e.g., keeping amounts as str to avoid floating-point errors).

🛠️ Feature Deep Dive

1. The Unified Parser

One caller to rule them all. Whether your file starts with <?xml or {1:, the OpenPurseParser handles the routing.

import openpurse

# Parses MT103, MT202, pacs.008, camt.053, pain.001, etc.
raw_data = get_incoming_payload()
parser = openpurse.OpenPurseParser(raw_data)
msg = parser.parse()

print(f"Ref: {msg.message_id} | Amt: {msg.amount} {msg.currency}")

The Uniform Data Model (UDM)

Every parsed message returns a PaymentMessage object (or an extended subclass like Pacs008Message) with these standardized attributes:

Attribute Description
message_id Unique ID from Group Header (:20: in MT)
end_to_end_id Original e2e reference (EndToEndId)
amount Transaction value (stored as string for precision)
currency ISO 3-letter currency code (e.g. USD, EUR)
sender_bic / receiver_bic Validated 8/11 char BIC codes
debtor_name / creditor_name Party names
debtor_account / creditor_account IBAN or local account identifiers
uetr SWIFT gpi Unique Transaction Reference

2. Bidirectional Translator

Move between MX (ISO 20022) and MT legacy formats without losing precision.

from openpurse.translator import Translator

# Convert a parsed message object to a legacy MT103 block
mt_payload = Translator.to_mt(msg, mt_type="103")

3. Smart PII Anonymizer

Essential for testing in staging environments with real data. OpenPurse scrubs names and addresses while keeping IBAN checksums valid, so your downstream systems don't reject the files.

from openpurse.anonymizer import Anonymizer

anonymized_xml = Anonymizer().anonymize_xml(raw_xml_bytes)

4. Lifecycle Reconciler

The "Holy Grail" of treasury engineering: linking fragmented messages into a single payment lifecycle (e.g., linking a pain.001 to its pain.002 status report and final camt.054 notification).

from openpurse.reconciler import Reconciler

# Trace the entire life of a payment across your message history
timeline = Reconciler.trace_lifecycle(seed_msg, message_pool)

📊 Capability Matrix

Format Category Supported Message Types
ISO 20022 (MX) Payments pacs.008, pacs.009, pacs.004
Cash Mgmt camt.052, camt.053, camt.054, camt.004
Initiation pain.001, pain.002, pain.008
SWIFT MT Customer MT101, MT103
Financial MT202
Reporting MT900, MT910, MT940, MT942, MT950

🚦 Smart Validation Engine

OpenPurse doesn't just check if a field exists; it checks if it's valid.

  • IBAN: Full Modulo-97 validation across all supported country formats.
  • BIC: Strict ISO 9362 8- or 11-character alphanumeric check.
  • UETR: Strict UUIDv4 checking for SWIFT gpi tracking.
from openpurse.validator import Validator

report = Validator.validate(msg)
if not report.is_valid:
    for err in report.errors:
        print(f"Critical Error: {err}")

🔍 Exporter: Automated API Specs

Instantly sync your internal financial models with your REST API documentation. Exporter generates OpenAPI 3.0 / JSON Schema definitions directly from the codebase.

# Generate openapi.json for your web team
python3 scripts/export_schema.py --output docs/api_spec.json

⚖️ Performance Benchmarks (Qualitative)

OpenPurse is optimized for high-throughput reconciliation pipelines. By leveraging lxml's C-bindings for XML traversal and specialized RegEx engines for MT parsing, OpenPurse can process:

  • Small Messages: ~0.001s / message.
  • Large Statements (CAMT.053/MT940): Typically < 0.05s for statement blocks with 5,000+ entries.

🤝 Contributing

OpenPurse is a community project for financial engineers. We welcome PRs for:

  • New ISO version mappings.
  • New MT block pattern regex improvements.
  • Performance optimizations.
# Setup for development
pip install -e ".[dev]"
pytest tests/

📜 License

OpenPurse is released under the MIT License. Build something great.

Built with ❤️ for modern financial engineering by the OpenPurse team.

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

openpurse-0.1.10.tar.gz (3.6 MB view details)

Uploaded Source

Built Distribution

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

openpurse-0.1.10-py3-none-any.whl (27.7 kB view details)

Uploaded Python 3

File details

Details for the file openpurse-0.1.10.tar.gz.

File metadata

  • Download URL: openpurse-0.1.10.tar.gz
  • Upload date:
  • Size: 3.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for openpurse-0.1.10.tar.gz
Algorithm Hash digest
SHA256 bb1c81afa11b971fa91e5d24a21056a7f68234964250df000094b2e39ddf62cc
MD5 523d93ee31d9d430d5500f16297a3e20
BLAKE2b-256 4a59ca8a57f0708b3a8133e8de1aad5d9c1f6974e6a7381fe9dc7158d5967d61

See more details on using hashes here.

File details

Details for the file openpurse-0.1.10-py3-none-any.whl.

File metadata

  • Download URL: openpurse-0.1.10-py3-none-any.whl
  • Upload date:
  • Size: 27.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for openpurse-0.1.10-py3-none-any.whl
Algorithm Hash digest
SHA256 af03d21921985a40f16fac8ce5bde6d0f0e6318d99ac207ba234c666a1b3424d
MD5 d020ca982f350b0d74e3566311d81510
BLAKE2b-256 8751865e47d601f038595c1a2738fb7b428f8be09d9cc29af96001d5bb543bfd

See more details on using hashes here.

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