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

🚦 Dual-Tier Validation Engine

OpenPurse doesn't just extract data; it actively defends your downstream systems against corrupted financial payloads using a two-tier validation engine.

Tier 1: Deep Structural Validation

Instantly checks the raw payload syntax before you even attempt to parse it.

  • XML (MX): Automatically evaluates the raw bytes against the precise matching lxml compiled XSD definition from the 770+ ISO schemas in the library.
  • SWIFT MT: Enforces rigorous Regex structural checks ensuring Block 1-5 definitions, proper :tag: spacing, and correct termination syntax are met.
from openpurse.validator import Validator

raw_payload = b"{1:F01BANKUS33XXX0000000000}{2:I103BANKGB22XXXN}{4:\n:20:REF123\n-}"
report = Validator.validate_schema(raw_payload)
if not report.is_valid:
    print(report.errors) # Caught malformed block 4 before parsing

Tier 2: Logical Field Validation

Validates the actual extracted business values of a parsed PaymentMessage.

  • IBAN: Full Modulo-97 checksum execution across all supported country formats.
  • BIC: Strict ISO 9362 8- or 11-character alphanumeric check for Senders/Receivers.
  • UETR: Strict UUIDv4 checking for SWIFT gpi tracking strings.
parsed_msg = parser.parse()
logic_report = Validator.validate(parsed_msg)
if not logic_report.is_valid:
    print(f"Critical Business Error: {logic_report.errors}")

🔍 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.13.tar.gz (13.9 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.13-py3-none-any.whl (32.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: openpurse-0.1.13.tar.gz
  • Upload date:
  • Size: 13.9 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.13.tar.gz
Algorithm Hash digest
SHA256 72468aafaa2c51660c500203fcb717044b4719258ff95a01c1c40802f96967e4
MD5 fd32b81e236b15d11b1820cc8093eba6
BLAKE2b-256 2355c58511e52299eb5bf895567b6b8d68b2a6fd8286df9adceaed186f8ac4a6

See more details on using hashes here.

File details

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

File metadata

  • Download URL: openpurse-0.1.13-py3-none-any.whl
  • Upload date:
  • Size: 32.3 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.13-py3-none-any.whl
Algorithm Hash digest
SHA256 d0eaa9419206fbc5622d743b14edc5c3ff7166d1d4c0484be928a4666d7b87cd
MD5 a9e33afc952d99b69640bd3ccd4a0393
BLAKE2b-256 831656c1a454458a52f2692a8a673c69c65f8690fe33d8d7bd041ec72fa32430

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