A lightweight Python package to flatten complex ISO 20022 XML messages into usable data.
Project description
OpenPurse
The Ultra-Lightweight, Production-Grade Engine for ISO 20022 and SWIFT MT Financial Messaging.
⚡️ 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
lxmlfor 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, nopydantic. 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:
- Flattening: We extract only the most critical fields needed for reconciliation and payment processing.
- Immutability: Once parsed, messages are stored in lightweight, typed
@dataclasses. - Lossless-Ready: While we flatten for convenience, we preserve raw data integrity (e.g., keeping amounts as
strto 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
lxmlcompiled 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file openpurse-0.1.12.tar.gz.
File metadata
- Download URL: openpurse-0.1.12.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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b80b9b3c0dd637a2749a2370f6669a1209a88012d812fe761391296c6f82e0a4
|
|
| MD5 |
7624ac103cbe6698e88de0a2fdc94a4b
|
|
| BLAKE2b-256 |
77d099408189b0156c203166a3b813b3d1fe34c82de70182f0e2fdb52c76332c
|
File details
Details for the file openpurse-0.1.12-py3-none-any.whl.
File metadata
- Download URL: openpurse-0.1.12-py3-none-any.whl
- Upload date:
- Size: 30.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f07c1d6c37d23e85d3f3e6f81c74c0f66b87eb593cc3227a75c6312f3f10bf15
|
|
| MD5 |
27b3984ba8c2799ea071b22e4eeb560d
|
|
| BLAKE2b-256 |
e6ddc79d5be3d5d868317f77035c120a65d2295e34c2362c9852e00db85bd33d
|