tollgate
Catches ISO 20022 payment messages that pass schema validation and still get rejected by the network — before you find out the hard way.
A pacs.008 payment message can be 100% valid XML, pass every XSD check, and still bounce off a real clearing network — because some of the rules that matter live outside the schema entirely. Tollgate catches that gap.
Quickstart
pip install iso-tollgate
tollgate validate payment.xml
1 error(s), 0 warning(s) found in payment.xml:
ERROR charset_violation -- FIToFICstmrCdtTrf/CdtTrfTxInf/Dbtr/Nm
Contains character(s) outside SWIFT's character set X: 'ü'. This is
schema-valid XML (ISO 20022 permits full Unicode) but SWIFT's network
layer restricts allowed characters independently of the schema --
this will not be caught by XSD validation alone.
That's a real example, not a mockup — every command in this README was actually run before being written down. No payment file handy? Generate one:
tollgate generate --count 1 --rule-id charset_violation --output-dir /tmp/fixtures
tollgate validate /tmp/fixtures/charset_violation_0.xml
→ Full usage guide — every command, every flag, the Python library API, batch directory checking, the GitHub Action → Why this exists — the dated deadline behind it, the AI design philosophy, what was found and fixed during development → Sources — every rule traced to a citation
What it checks
One message type in v1: pacs.008.001.08, the FI-to-FI customer credit transfer used across Fedwire, CHIPS, and SWIFT CBPR+.
| Check | Catches |
|---|---|
| Schema validity | Standard XSD structural validation. The floor everything else stands on. |
| SWIFT character set | A character outside SWIFT's allowed set — schema-valid, network-invalid. |
| Address structure | Free-format addresses used where structure is required, or line counts the schema allows but a network's guidelines don't. |
| Truncation signals | A value landing at exactly 35 or 70 characters — old legacy line limits — in a field with a much higher modern limit. Reported as a warning, not a certainty. |
| Network-mandatory gaps | Fields the schema marks optional that a real network requires in practice (e.g. UETR for Fedwire). |
| Currency decimal precision | An amount's decimal places don't match its currency's defined exponent (e.g. JPY, which has zero decimal places, formatted with two). Reported as a warning — the failure mode is silent misinterpretation, not certain rejection. |
Every rule traces to a primary source — see docs/SOURCES.md. No rule ships without one.
Not a compliance tool
Tollgate is a developer-facing sanity check, not a replacement for SWIFT certification or MyStandards testing. It covers one message type, checks structure and format (not business logic like BIC reachability), and is explicit in docs/why.md about every limitation found during development. If it can't catch something, the docs say so.
Three ways to use it
| CLI | tollgate validate payment.xml · tollgate validate-dir payments/ |
| Python library | from tollgate import check_message, check_file, check_directory |
| CI | uses: iso-tollgate/tollgate/.github/actions/validate@main |
Details and examples for all three: docs/usage.md.
Status
168 tests passing, 3 skip cleanly without an ANTHROPIC_API_KEY set (these 3 exercise --explain against the real Anthropic API and were live-verified once, 2026-06-21, on a real machine with a real key — see CLAUDE.md for the re-verification rule if explainer.py or prompts.py change). The full deterministic suite — every validation rule, the generator, the eval harness, both APIs — needs zero API key to verify.
--explain has been live-tested against the real model: it correctly names the violated field and cause, and correctly hedges on warning-severity (heuristic) findings rather than asserting them as certain failures — verified, not assumed.
Published on PyPI: pip install iso-tollgate. A Homebrew tap exists at homebrew-tollgate — CI verifies the formula's syntax and style on every change, but a full brew install hasn't been confirmed end-to-end yet, so pip install is the recommended path for now.
License
Apache 2.0. See LICENSE.
Metadata
Release files for iso-tollgate 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| iso_tollgate-0.1.1.tar.gz | 312.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| iso_tollgate-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 368.2 kB
Release files / iso_tollgate-0.1.1.tar.gz
| Download URL | iso_tollgate-0.1.1.tar.gz |
|---|---|
| Size | 312.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7734ffab03e749eb2b3c2a2f37081ff1ca405aa3ac1c41b6735e36d4b3e17fb1
|
|
BLAKE2b-256 checksum How to use checksums |
f568b9f488d2e310eae49b375cfdee295b6bd7c43fd66c3fcd1464613fa673ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Release files / iso_tollgate-0.1.1-py3-none-any.whl
| Download URL | iso_tollgate-0.1.1-py3-none-any.whl |
|---|---|
| Size | 55.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
11d75abe5bfaed80357f3e69940d3da27151a8111638103cb4f36972c71cfcf8
|
|
BLAKE2b-256 checksum How to use checksums |
6de85578542ad264cdc90b12b0c2abd007f7093b07c0ccfd82ab6dd20fce1a69
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|