{"id":51557361,"url":"https://github.com/sebastienrousseau/camt053","last_synced_at":"2026-07-10T06:31:44.729Z","repository":{"id":365539210,"uuid":"1272336344","full_name":"sebastienrousseau/camt053","owner":"sebastienrousseau","description":"Read ISO 20022 camt Bank-to-Customer Statements (camt.052/053/054) and generate validated reversing entries by return reason code such as AC04 Closed Account. Core library with a Click CLI and FastAPI REST API.","archived":false,"fork":false,"pushed_at":"2026-06-25T14:26:06.000Z","size":481,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-25T16:14:06.195Z","etag":null,"topics":["bank-statement","banking","camt","camt052","camt053","camt054","cash-management","cli","fintech","iban","iso20022","payments","python","rest-api","return-reason","reversing-entry","treasury","xml"],"latest_commit_sha":null,"homepage":"https://camt053.com","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sebastienrousseau.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-17T14:08:24.000Z","updated_at":"2026-06-25T14:27:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sebastienrousseau/camt053","commit_stats":null,"previous_names":["sebastienrousseau/camt053"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/sebastienrousseau/camt053","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sebastienrousseau%2Fcamt053","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sebastienrousseau%2Fcamt053/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sebastienrousseau%2Fcamt053/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sebastienrousseau%2Fcamt053/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sebastienrousseau","download_url":"https://codeload.github.com/sebastienrousseau/camt053/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sebastienrousseau%2Fcamt053/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35323809,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-10T02:00:06.465Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bank-statement","banking","camt","camt052","camt053","camt054","cash-management","cli","fintech","iban","iso20022","payments","python","rest-api","return-reason","reversing-entry","treasury","xml"],"created_at":"2026-07-10T06:31:44.648Z","updated_at":"2026-07-10T06:31:44.714Z","avatar_url":"https://github.com/sebastienrousseau.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# camt053: ISO 20022 Bank Statements and Reversing Entries\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://cloudcdn.pro/camt053/v1/logos/camt053.svg\" alt=\"camt053 logo\" width=\"128\" /\u003e\n\u003c/p\u003e\n\n[![PyPI Version][pypi-badge]][07]\n[![Python Versions][python-versions-badge]][07]\n[![License][license-badge]][01]\n[![Tests][tests-badge]][tests-url]\n[![Quality][quality-badge]][quality-url]\n[![OpenSSF Scorecard][scorecard-badge]][scorecard-url]\n[![OpenSSF Best Practices][bestpractices-badge]][bestpractices-url]\n[![Documentation][docs-badge]][docs-url]\n\n**Read ISO 20022 `camt` Bank-to-Customer Cash Management messages, extract\nbooked entries by return reason code (e.g. AC04 Closed Account), and generate\nvalidated reversing entries** — the core of a modern, AI-assisted treasury\nstack with native MCP and LSP integrations.\n\n\u003e **Latest release: v0.0.5** — namespace-agnostic camt.052/053/054 parsing and\n\u003e one-shot reversing-entry generation, validated against the official ISO 20022\n\u003e `camt.053.001.14` schema, for Python 3.10+.\n\u003e [See what's new →][release-005]\n\n## Contents\n\n- [Overview](#overview)\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Features](#features)\n- [Usage](#usage)\n- [Supported messages](#supported-messages)\n- [Architecture](#architecture)\n- [Examples](#examples)\n- [The camt053 suite](#the-camt053-suite)\n- [When not to use camt053](#when-not-to-use-camt053)\n- [Development](#development)\n- [Security](#security)\n- [Documentation](#documentation)\n- [License](#license)\n- [Contributing](#contributing)\n- [Acknowledgements](#acknowledgements)\n\n## Overview\n\n**camt053** reads ISO 20022 `camt` cash-management messages — the standardised\nbank-to-customer **statements** (camt.053), **account reports** (camt.052), and\n**debit/credit notifications** (camt.054) — into a typed model, lets you filter\nbooked entries by ISO external return reason code, and generates a **validated\nreversing entry** for the matching transactions.\n\nThe headline capability is the one-shot reversing-entry workflow: read an\nincoming camt.053 statement, find the entries carrying a return reason code\n(e.g. **AC04 Closed Account**), and emit a validated reversing entry — answering\nthe prompt-engineering dream:\n\n\u003e *\"Read this incoming bank statement XML, parse out the transactions with error\n\u003e code AC04, and automatically generate the reversing entry.\"*\n\n- **Documentation:** \u003chttps://sebastienrousseau.github.io/camt053/\u003e\n- **Source code:** \u003chttps://github.com/sebastienrousseau/camt053\u003e\n- **Bug reports:** \u003chttps://github.com/sebastienrousseau/camt053/issues\u003e\n\nA single shared facade (`camt053.services`) backs four developer surfaces — the\nPython API, the CLI, the REST API, and the companion MCP and LSP servers — so\nevery interface behaves identically. This package is part of the **camt053\nsuite** (all Python 3.10+):\n\n| Package | Role |\n|---------|------|\n| `camt053` | Core library + Click CLI + FastAPI REST API (this package) |\n| [`camt053-mcp`][mcp-pkg] | Model Context Protocol server (for AI agents) |\n| [`camt053-lsp`][lsp-pkg] | Language Server Protocol server (for editors) |\n\n```mermaid\nflowchart LR\n    A[\"Inbound camt.05x XML\"] --\u003e|parse| B[\"camt053.services\"]\n    B --\u003e|filter by reason code| C[\"AC04 entries\"]\n    C --\u003e|reverse + validate| D[\"camt.053.001.14 reversing entry\"]\n```\n\n## Install\n\n**camt053** runs on macOS, Linux, and Windows and requires **Python 3.10+** and\n**pip**.\n\n```sh\npython -m pip install camt053\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing an isolated virtual environment (recommended)\u003c/summary\u003e\n\n```sh\npython -m venv venv\nsource venv/bin/activate        # macOS/Linux\nvenv\\Scripts\\activate           # Windows\npython -m pip install -U camt053\n```\n\u003c/details\u003e\n\n## Quick Start\n\n```python\nfrom camt053 import services\n\n# An incoming camt.053 statement (truncated for brevity — see examples/).\nstatement_xml = open(\"statement.xml\", encoding=\"utf-8\").read()\n\n# Find the entries returned AC04 (Closed Account).\nac04 = services.filter_entries(statement_xml, \"AC04\")\nprint(f\"{len(ac04)} AC04 entr{'y' if len(ac04) == 1 else 'ies'}\")\n\n# Generate the reversing entry: parse -\u003e filter -\u003e reverse, in one call.\nreversal_xml = services.generate_reversal(statement_xml, reason_code=\"AC04\")\nprint(reversal_xml)  # validated camt.053.001.14 document\n```\n\nOr from the command line:\n\n```sh\n# Generate a reversing entry for every AC04 entry on a statement\ncamt053 reverse -i statement.xml -r AC04 -o reversal.xml\n\n# List the entries on a statement (filter by reason, status, date, or amount)\ncamt053 entries -i statement.xml -r AC04\ncamt053 entries -i statement.xml --status BOOK --from 2026-06-01 --min 1000\n\n# Export the (filtered) entries as CSV or JSON, to stdout or a file\ncamt053 entries -i statement.xml --export csv -o entries.csv\ncamt053 entries -i statement.xml -r AC04 --export json\n\n# Choose the output format: a Rich table (default) or structured JSON\ncamt053 entries -i statement.xml --format json\ncamt053 reverse -i statement.xml -r AC04 --format json   # JSON envelope\n\n# Inspect the parsed statement as JSON, or validate an identifier\ncamt053 parse -i statement.xml\ncamt053 validate-id -k iban -v GB29NWBK60161331926819\n\n# Validate an incoming statement against its official ISO camt XSD\ncamt053 validate -i statement.xml\n```\n\n`parse`, `entries`, `reverse`, and `validate` accept `-i -` to read from stdin,\nso they compose in a pipeline.\n\n## Features\n\n- **Parse** camt.053 / camt.052 / camt.054 into a typed, JSON-serialisable\n  model. Parsing is **namespace-agnostic**, so every ISO version (`.001.01`\n  through `.001.14`) and real-world bank file is read.\n- **Filter** booked entries by ISO external return reason code (AC04, AC06,\n  MD07, …), and by **status**, **booking-date range**, and **amount range**\n  (all ANDed) via `services.filter_entries(...)` or the `camt053 entries`\n  flags.\n- **Return reason codes** — a substantial slice of the ISO 20022\n  `ExternalReturnReason1Code` set (the common SEPA / CBPR+ return reasons),\n  listed via `camt053 reasons`, with case-insensitive lookup through\n  `services.validate_reason_code(code) -\u003e {\"code\", \"name\", \"valid\"}`.\n- **Reason-code action policy** — classify a return reason into a handling\n  action (`\"return\"`, `\"retry\"`, or `\"ignore\"`) via\n  `services.classify_reason(code) -\u003e {\"code\", \"name\", \"action\"}`, with a\n  sensible built-in default (account-level rejections return, transient\n  conditions such as `AM04` / `AM05` retry, informational reasons ignore). The\n  full mapping is `services.reason_policy()`; both accept an `overrides`\n  mapping and a custom `default`. The `camt053 reasons` table shows the action\n  column and `camt053 classify -r AC04` classifies a single code.\n- **Export** the (filtered) entries to **CSV** or **JSON** (`camt053 entries\n  --export {csv,json} [-o file]`); CSV columns are `reference, amount,\n  currency, credit_debit_indicator, status, booking_date, value_date,\n  reason_code`.\n- **Structured output** — `camt053 entries --format json` emits the entries\n  as a JSON array, and `camt053 reverse --format json` emits a\n  `{\"message_type\", \"reason_code\", \"xml\"}` envelope instead of raw XML\n  (`--format table`, the default, keeps the Rich table / raw XML).\n- **Reverse** — generate a `camt.053.001.14` reversing entry from the matching\n  entries (credit/debit indicator flipped, `RvslInd` set, return reason carried\n  in `RtrInf`), in one call.\n- **Validated output** — generated reversals are checked against the **official\n  ISO 20022 `camt.053.001.14` XSD** bundled with the package.\n- **SWIFT charset cleansing** — opt-in cleansing of the name / narrative fields\n  (`Nm` / `AddtlInf` / party / counterparty names) bound for SWIFT FIN / CBPR+\n  rails: characters outside the **SWIFT X** set are transliterated (`é` → `e`,\n  `ß` → `ss`, smart quotes / dashes folded) or stripped, and field maximum\n  lengths are enforced. Enable it on the reversal path with\n  `services.generate_reversal(xml, cleanse=True)` /\n  `services.generate(records, cleanse=True)` (default off, so existing output\n  is unchanged), or cleanse records directly with\n  `services.cleanse_records(records) -\u003e {\"changed\", \"fields\": [report, ...]}`,\n  which returns an audit report of exactly what changed. Cleansed reversals\n  still validate against the bundled XSD.\n- **Validate incoming statements** — `services.validate_statement(xml)` (and the\n  `camt053 validate` command) check an inbound camt.052 / camt.053 / camt.054\n  document against the matching **official ISO 20022 XSD**, detected from its\n  namespace, returning `{\"valid\", \"message_type\", \"errors\"}`.\n- **Re-serialise (round-trip)** — render a parsed `ParsedDocument` / `Statement`\n  back to a validated `camt.053.001.14` document via\n  `services.serialize_statement(xml)` (or `camt053.serialize_document(doc)` /\n  `camt053.serialize_statement(stmt)`). The output is **deterministic** and\n  round-trip stable: `parse_document(serialize_statement(parse_document(xml)))`\n  preserves the account, balances, and entries (references, amounts,\n  currencies, credit/debit indicators, and return reasons).\n- **Safe by default** — XML is parsed with `defusedxml` (XXE / billion-laughs\n  safe); output paths are traversal-checked.\n- **One facade, four interfaces** — the CLI, REST API, MCP server, and LSP\n  server all call `camt053.services`.\n- **IBAN / BIC / LEI validators** (ISO 13616 / 9362 / 17442).\n- **Decimal amounts \u0026 ISO 4217 currencies** — `Entry.amount_decimal` /\n  `Balance.amount_decimal` parse the string amount into a `Decimal` (the\n  string is kept verbatim for XML fidelity), and\n  `services.validate_currency(code) -\u003e {\"code\", \"valid\", \"minor_units\"}`\n  checks a code against a bundled ISO 4217 set and reports its minor units\n  (EUR=2, JPY=0, …).\n- **Typed** (mypy `--strict`) and **tested** (100% coverage), validated against\n  the official ISO 20022 business samples.\n\n## Usage\n\n```python\nfrom camt053 import parse_statement, services\n\n# A minimal incoming camt.053 statement: a EUR 1,500 credit transfer that was\n# booked, then returned because the beneficiary account was closed (AC04).\nstatement_xml = \"\"\"\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cDocument xmlns=\"urn:iso:std:iso:20022:tech:xsd:camt.053.001.14\"\u003e\n  \u003cBkToCstmrStmt\u003e\n    \u003cGrpHdr\u003e\u003cMsgId\u003eSTMT-MSG-0001\u003c/MsgId\u003e\u003cCreDtTm\u003e2026-06-15T08:00:00\u003c/CreDtTm\u003e\u003c/GrpHdr\u003e\n    \u003cStmt\u003e\n      \u003cId\u003eSTMT-0001\u003c/Id\u003e\u003cCreDtTm\u003e2026-06-15T08:00:00\u003c/CreDtTm\u003e\n      \u003cAcct\u003e\u003cId\u003e\u003cIBAN\u003eGB29NWBK60161331926819\u003c/IBAN\u003e\u003c/Id\u003e\u003cCcy\u003eEUR\u003c/Ccy\u003e\u003c/Acct\u003e\n      \u003cBal\u003e\u003cTp\u003e\u003cCdOrPrtry\u003e\u003cCd\u003eCLBD\u003c/Cd\u003e\u003c/CdOrPrtry\u003e\u003c/Tp\u003e\n        \u003cAmt Ccy=\"EUR\"\u003e10000.00\u003c/Amt\u003e\u003cCdtDbtInd\u003eCRDT\u003c/CdtDbtInd\u003e\n        \u003cDt\u003e\u003cDt\u003e2026-06-15\u003c/Dt\u003e\u003c/Dt\u003e\u003c/Bal\u003e\n      \u003cNtry\u003e\n        \u003cNtryRef\u003eNTRY-0001\u003c/NtryRef\u003e\n        \u003cAmt Ccy=\"EUR\"\u003e1500.00\u003c/Amt\u003e\u003cCdtDbtInd\u003eCRDT\u003c/CdtDbtInd\u003e\n        \u003cSts\u003e\u003cCd\u003eBOOK\u003c/Cd\u003e\u003c/Sts\u003e\n        \u003cNtryDtls\u003e\u003cTxDtls\u003e\n          \u003cRtrInf\u003e\u003cRsn\u003e\u003cCd\u003eAC04\u003c/Cd\u003e\u003c/Rsn\u003e\u003c/RtrInf\u003e\n        \u003c/TxDtls\u003e\u003c/NtryDtls\u003e\n      \u003c/Ntry\u003e\n    \u003c/Stmt\u003e\n  \u003c/BkToCstmrStmt\u003e\n\u003c/Document\u003e\"\"\"\n\n# 1. Parse into the typed model.\nstatement = parse_statement(statement_xml)\nprint(statement.account.identifier())          # -\u003e GB29NWBK60161331926819\nprint(len(statement.entries))                   # -\u003e 1\n\n# 2. Select the entries returned AC04 (Closed Account).\nac04 = statement.entries_with_reason(\"AC04\")\nprint(ac04[0].amount, ac04[0].credit_debit_indicator)   # -\u003e 1500.00 CRDT\n\n# 3. Generate the validated reversing entry (the original CRDT becomes DBIT).\nreversal_xml = services.generate_reversal(statement_xml, reason_code=\"AC04\")\nassert \"\u003cRvslInd\u003etrue\u003c/RvslInd\u003e\" in reversal_xml\nassert \"\u003cCdtDbtInd\u003eDBIT\u003c/CdtDbtInd\u003e\" in reversal_xml\n```\n\n## Supported messages\n\n| Message type | Name | Direction |\n|--------------|------|-----------|\n| `camt.052.001.14` | Bank To Customer Account Report | read |\n| `camt.053.001.14` | Bank To Customer Statement | read + **reverse** |\n| `camt.054.001.14` | Bank To Customer Debit Credit Notification | read |\n\nThe parser is namespace-agnostic and reads every ISO version of these messages;\nthe official XSDs for `.001.01`–`.001.14` are bundled under `camt053/xsd/`.\nReversing entries are emitted as `camt.053.001.14`.\n\n## Architecture\n\n```mermaid\nflowchart TD\n    CLI[\"Click CLI\"] --\u003e S[\"camt053.services\"]\n    API[\"FastAPI REST API\"] --\u003e S\n    MCP[\"camt053-mcp\"] --\u003e S\n    LSP[\"camt053-lsp\"] --\u003e S\n    S --\u003e P[\"parse/ — statement_parser, reason_codes\"]\n    S --\u003e R[\"reversal/ — reversal builder\"]\n    S --\u003e X[\"xml/ — template + official ISO XSD\"]\n    S --\u003e V[\"validation/ — IBAN, BIC, LEI, JSON Schema\"]\n```\n\n| Module | Responsibility |\n|--------|----------------|\n| `camt053.parse` | Namespace-agnostic statement parser and return-reason helpers |\n| `camt053.reversal` | Builds flat reversing-entry records from parsed entries |\n| `camt053.xml` | Renders the camt.053 reversal template and validates it via the ISO XSD |\n| `camt053.validation` | IBAN / BIC / LEI and JSON-Schema validators |\n| `camt053.security` | XXE-safe parsing and path-traversal-checked output |\n| `camt053.services` | The shared facade backing every interface |\n\n## Error handling\n\nEvery exception in [`camt053.exceptions`](camt053/exceptions.py) inherits from\n`Camt053Error` and carries a stable, machine-readable `code`. These codes are\npart of the public API — they are guaranteed unique and will not change across\nreleases — so you can switch on `exc.code` (e.g. to map a failure onto an HTTP\nstatus) without depending on the class name or message text.\n\n| Code | Exception | Meaning |\n|------|-----------|---------|\n| `CAMT053_ERROR` | `Camt053Error` | Base error for any Camt053 failure |\n| `ACCOUNT_VALIDATION_ERROR` | `AccountValidationError` | Account/input data failed validation |\n| `XML_GENERATION_ERROR` | `XMLGenerationError` | XML rendering or template failure |\n| `CONFIGURATION_ERROR` | `ConfigurationError` | Invalid configuration or CLI arguments |\n| `DATA_SOURCE_ERROR` | `DataSourceError` | A data source could not be read |\n| `SCHEMA_VALIDATION_ERROR` | `SchemaValidationError` | XML did not conform to its ISO 20022 XSD |\n| `INVALID_IBAN_ERROR` | `InvalidIBANError` | IBAN format / checksum validation failed |\n| `INVALID_BIC_ERROR` | `InvalidBICError` | BIC/SWIFT format validation failed |\n| `INVALID_LEI_ERROR` | `InvalidLEIError` | LEI format / checksum validation failed |\n| `MISSING_REQUIRED_FIELD_ERROR` | `MissingRequiredFieldError` | A required field was absent |\n| `STATEMENT_PARSE_ERROR` | `StatementParseError` | An incoming statement could not be parsed |\n| `REVERSAL_GENERATION_ERROR` | `ReversalGenerationError` | A reversing entry could not be generated |\n\n```python\nfrom camt053 import services\nfrom camt053.exceptions import Camt053Error\n\ntry:\n    services.generate_reversal(statement_xml, reason_code=\"AC04\")\nexcept Camt053Error as exc:\n    log.error(\"[%s] %s\", exc.code, exc)\n```\n\n## Robustness\n\nThe statement parser is built for the messy reality of inbound bank files:\nmalformed-but-recoverable statements degrade gracefully rather than failing\noutright.\n\n- **Missing optional elements** (owner name, currency, balances, booking date,\n  return reason, ...) read as `None` / empty — only the `\u003cDocument\u003e` envelope\n  wrapping a recognised camt.05x container is mandatory.\n- **Unknown or extra elements** (vendor extensions, unexpected siblings) are\n  ignored: children are matched by local name, not by a fixed schema.\n- **Unexpected namespaces and prefixes** are tolerated — a prefixed\n  `\u003ccamt:Document\u003e` root, a missing namespace, or a non-ISO namespace URI all\n  parse the same way.\n\nGenuinely non-well-formed XML (unclosed / mismatched tags, bad entities) still\nraises `StatementParseError`, which carries the 1-based source `line` (and\ncolumn, where reported) so the offending byte can be located. See\n[`camt053/parse/statement_parser.py`](camt053/parse/statement_parser.py) for\nthe documented recovery limits.\n\n## Examples\n\nRunnable, self-contained scripts live in [`examples/`](examples/):\n\n| Example | Demonstrates |\n|---------|--------------|\n| [`reverse_ac04.py`](examples/reverse_ac04.py) | The headline workflow — find AC04 entries and generate the reversing entry |\n| [`parse_statement.py`](examples/parse_statement.py) | Parsing a statement into the typed model |\n| [`services_facade.py`](examples/services_facade.py) | The shared `camt053.services` facade |\n| [`validate_identifiers.py`](examples/validate_identifiers.py) | IBAN / BIC / LEI validation |\n| [`rest_api_client.py`](examples/rest_api_client.py) | Driving the FastAPI REST API in-process |\n\n```sh\ngit clone https://github.com/sebastienrousseau/camt053.git \u0026\u0026 cd camt053\npython examples/reverse_ac04.py\n```\n\n## The camt053 suite\n\n`camt053` is the core of a set of independently installable packages\n— pick whichever ones your stack needs:\n\n| Package | Role |\n| :--- | :--- |\n| [`camt053`](https://pypi.org/project/camt053/) | **Core library + CLI + FastAPI REST API (this package)** |\n| [`camt053-mcp`](https://pypi.org/project/camt053-mcp/) | Model Context Protocol server (for AI agents) |\n| [`camt053-lsp`](https://pypi.org/project/camt053-lsp/) | Language Server Protocol server (for editors) |\n| [`camt053-writer-xlsx`](https://pypi.org/project/camt053-writer-xlsx/) | Excel `.xlsx` writer for parsed statements |\n| [`camt053-loader-mt940`](https://pypi.org/project/camt053-loader-mt940/) | SWIFT MT940 → camt.053 loader |\n\nThe MCP, LSP, writer-xlsx, and loader-mt940 packages are thin wrappers\nover the shared `camt053.services` facade exported here, so every\ninterface behaves identically.\n\n## When not to use camt053\n\n- **You need to generate payment files** (pain.001 Customer Credit\n  Transfer, pain.008 Direct Debit). Use\n  [`pain001`](https://github.com/sebastienrousseau/pain001) — the\n  sibling library for outbound ISO 20022.\n- **You need to parse pacs.\\* (FI-to-FI) messages.** Out of scope; this\n  library targets the camt.05x (Bank-to-Customer) family only.\n- **You need bank API transport** (PSD2, EBICS, SWIFTNet). camt053\n  reads files and emits files; it does not move them. Pair with a\n  dedicated transport library.\n- **You need a GUI.** This is a library + CLI + REST API; the closest\n  thing to a UI is the LSP server's in-editor diagnostics.\n- **You need real-time processing** (FedNow / TIPS / RTP). Those rails\n  use camt.052 intraday reporting, not camt.053 end-of-day statements;\n  the parser accepts camt.052 but the reversing-entry workflow is\n  camt.053-shaped.\n\n## Development\n\n**camt053** uses [Poetry](https://python-poetry.org/) and\n[mise](https://mise.jdx.dev/).\n\n```bash\ngit clone https://github.com/sebastienrousseau/camt053.git \u0026\u0026 cd camt053\nmise install\npoetry install\npoetry shell\n```\n\nA `Makefile` orchestrates the quality gates (kept in lockstep with CI):\n\n```bash\nmake check        # all gates (REQUIRED before commit)\nmake test         # pytest with coverage (100% gate)\nmake lint         # ruff + black --check\nmake type-check   # mypy --strict\nmake examples     # run the example scripts\n```\n\n## Security\n\n`camt053` is the entry point for **untrusted XML from banks** for\nevery consumer in the suite. Defence-in-depth is taken seriously:\nparsing uses `defusedxml` (XXE / billion-laughs neutralised), a\npre-flight `xml_guard` enforces a configurable byte cap and refuses\ninline DOCTYPE / ENTITY declarations, and the REST API additionally\ncaps request bodies via middleware. Reporting practice, supported\nversions, fix-window SLAs, and the full supply-chain posture (PyPI\nTrusted Publishing, sigstore attestations, signed tags) live in\n[`SECURITY.md`](SECURITY.md). Vulnerabilities go via GitHub Private\nVulnerability Reporting, not public issues.\n\n## News / Releases\n\n- **2026-06-22 — [Shipping camt053 v0.0.6 for the 14-16 November 2026 ISO 20022 cliff](docs/posts/2026-06-22-shipping-camt053-v006-for-the-november-2026-cliff.md)** (v0.0.6 release announcement + Nov 2026 cliff narrative).\n\n## Documentation\n\n- [`README.md`](README.md) — this file\n- [`CHANGELOG.md`](CHANGELOG.md) — release notes\n- [`ROADMAP.md`](ROADMAP.md) — milestones and the explicit Declined/Deferred list\n- [`GOVERNANCE.md`](GOVERNANCE.md) — decision model + becoming a maintainer\n- [`SECURITY.md`](SECURITY.md) — disclosure + supported versions + supply chain + NIST SSDF mapping\n- [`SUPPORT.md`](SUPPORT.md) — how to get help, by need\n- [`MAINTAINERS.md`](MAINTAINERS.md) — who can merge and cut releases\n- [`CONTRIBUTING.md`](CONTRIBUTING.md) — submission process + style\n- [`STYLEGUIDE.md`](STYLEGUIDE.md) — cross-suite style guide (linked from every package README)\n- [`docs/version-matrix.md`](docs/version-matrix.md) — supported `camt.05x` revisions with the Nov 2026 cliff\n- [`examples/`](examples/) — runnable scripts, exercised in CI\n- [`docs/`](docs/) — extended reference (API, quickstart, deployment cookbook)\n- Hosted Sphinx docs: \u003chttps://sebastienrousseau.github.io/camt053/\u003e\n\n## License\n\nLicensed under the [Apache License, Version 2.0][01]. Any contribution submitted\nfor inclusion shall be licensed as above, without additional terms.\n\n## Contributing\n\nContributions are welcome — see the [contributing instructions][04]. Thanks to\nall [contributors][05].\n\n## Acknowledgements\n\nBuilt on [Click](https://click.palletsprojects.com/),\n[Rich](https://rich.readthedocs.io/), [Jinja2](https://jinja.palletsprojects.com/),\n[xmlschema](https://github.com/sissaschool/xmlschema),\n[defusedxml](https://github.com/tiran/defusedxml), and\n[FastAPI](https://fastapi.tiangolo.com/), against the official ISO 20022\n`camt.05x` schemas.\n\n[01]: https://opensource.org/license/apache-2-0/\n[04]: https://github.com/sebastienrousseau/camt053/blob/main/CONTRIBUTING.md\n[05]: https://github.com/sebastienrousseau/camt053/graphs/contributors\n[07]: https://pypi.org/project/camt053/\n[mcp-pkg]: https://github.com/sebastienrousseau/camt053-mcp\n[lsp-pkg]: https://github.com/sebastienrousseau/camt053-lsp\n[release-005]: https://github.com/sebastienrousseau/camt053/releases/tag/v0.0.5\n[docs-badge]: https://img.shields.io/badge/Docs-GitHub%20Pages-blue?style=for-the-badge\n[docs-url]: https://sebastienrousseau.github.io/camt053/\n[license-badge]: https://img.shields.io/pypi/l/camt053?style=for-the-badge\n[pypi-badge]: https://img.shields.io/pypi/v/camt053?style=for-the-badge\n[python-versions-badge]: https://img.shields.io/pypi/pyversions/camt053.svg?style=for-the-badge\n[quality-badge]: https://img.shields.io/github/actions/workflow/status/sebastienrousseau/camt053/ci.yml?branch=main\u0026label=Quality\u0026style=for-the-badge\n[quality-url]: https://github.com/sebastienrousseau/camt053/actions/workflows/ci.yml\n[scorecard-badge]: https://api.scorecard.dev/projects/github.com/sebastienrousseau/camt053/badge?style=for-the-badge\n[scorecard-url]: https://scorecard.dev/viewer/?uri=github.com/sebastienrousseau/camt053\n[bestpractices-badge]: https://www.bestpractices.dev/projects/13373/badge\n[bestpractices-url]: https://www.bestpractices.dev/projects/13373\n[tests-badge]: https://img.shields.io/github/actions/workflow/status/sebastienrousseau/camt053/ci.yml?branch=main\u0026label=Tests\u0026style=for-the-badge\n[tests-url]: https://github.com/sebastienrousseau/camt053/actions/workflows/ci.yml\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsebastienrousseau%2Fcamt053","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsebastienrousseau%2Fcamt053","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsebastienrousseau%2Fcamt053/lists"}