Skip to main content

Ironfang Finance Python client and CLI

ironfang-finance, Python 3.10+, no runtime dependencies. This package calls the Ironfang Finance HTTPS API; PHIVE and registered artefacts determine the validation outcome. It performs no local invoice/business-rule validation.

pip install ironfang-finance

2.0.0 removed the launch-era names: the ironfang_financewolf module, the Financewolf and FinancewolfError classes, the financewolf command and the FINANCEWOLF_API_KEY variable. Use ironfang_finance, IronfangFinance, ironfang-finance and IRONFANG_API_KEY.

Provide an Ironfang key with finance:einvoices:write using your secret manager or IRONFANG_API_KEY. Never commit a key or pass it as a CLI argument.

import os
from pathlib import Path
from ironfang_finance import IronfangFinance, IronfangFinanceError

client = IronfangFinance(os.environ["IRONFANG_API_KEY"])
result = client.validate(
    Path("invoice.xml").read_bytes(),
    ruleset="fwrs_bis3_billing_invoice_2026_5_r5",
)
print(result["outcome"])

validate takes bytes and returns the structured result for valid or invalid. Client, HTTP, transport and indeterminate/malformed response failures raise IronfangFinanceError, with a safe code and optional HTTP status. It verifies response hash, length, completed layers and the selected immutable ruleset. It never changes the document. latest defaults to the active detected ruleset; pin a type-specific ID for reproducible CI. A ruleset's lifecycle may later prevent new validations, in which case the API error is retained as a failure.

V2: XRechnung and ZUGFeRD / Factur-X, XML or PDF

The *_v2 methods use the V2 API, which validates Peppol BIS Billing 3, XRechnung 3.0.2 (UBL or CII) and ZUGFeRD 2.5.2 / Factur-X 1.09.2 in its five profiles, as XML or as a PDF with its embedded invoice XML. V1 methods are unchanged.

pdf = Path("invoice.pdf").read_bytes()
result = client.validate_v2(pdf)  # family, variant and scope detected
print(result["outcome"], result["ruleset"]["id"])
for group in result["groups"]:  # pdfa, attachment_metadata, invoice_xml
    print(group["group"], group["status"])
for finding in result["findings"]:
    print(finding["rule_id"], finding["location"])  # kind: xpath, line-column, pdf or none
  • validate_v2(document, *, media_type=None, ruleset="latest", family=None, variant=None, document_type=None, scope=None, idempotency_key=None) sends the exact bytes once. A PDF is recognised from its header (or pass media_type). XML is at most 5 MiB, a PDF 20 MiB. Left at its default, the timeout is 45 seconds for a PDF (the server's hybrid deadline is 30).
  • The verdict is checked like V1's: hash, length and media type of the bytes sent, the scope they imply (xml or hybrid_pdf), the selection asked for, both engines for a PDF, and layers consistent with the outcome. coverage.not_checked states what a verdict does not establish, such as the visible PDF matching its XML.
  • A refusal or indeterminate answer raises IronfangFinanceError with problem set to the API's code (for example family_mismatch, no_embedded_invoice or validation_timeout) and request_id for support. The problem's other text is never kept.
  • idempotency_key (8-128 of A-Z a-z 0-9 _ -) makes a retry after a lost response return the first result instead of a second operation.

Reads and durable work, all V1 and V2 together where the API lists both: rulesets_v2, results_v2, result_v2, delete_result_v2; submit_job_v2, job_v2, jobs_v2, cancel_job_v2, wait_for_job_v2; submit_batch_v2 (a list of up to 100 dicts: document bytes, plus any of media_type, ruleset, family, variant, document_type, scope), batch_v2, batches_v2, cancel_batch_v2; deliveries_v2, delivery_v2, retry_delivery_v2 (the retry needs finance:einvoices:destinations:manage). Reads need finance:einvoices:read.

job = client.submit_job_v2(pdf, idempotency_key="invoice-2026-0042")
job = client.wait_for_job_v2(job["id"], timeout=300)
verdict = client.result_v2(job["operation_id"])

CLI

ironfang-finance validate 'invoices/**/*.xml' --ruleset fwrs_bis3_billing_invoice_2026_5_r5 --output invoice-results.json
ironfang-finance validate credit-notes --ruleset fwrs_bis3_billing_creditnote_2026_5_r5 --output credit-results.json
ironfang-finance validate e-invoices --api v2 --ruleset latest --output e-invoice-results.json
ironfang-finance validate 'zugferd/*.pdf' --api v2 --family zugferd-facturx --ruleset latest --output zugferd-results.json
# Equivalent: python3 -m ironfang_finance validate ...

--api v2 validates through V2: directories select *.pdf as well as *.xml, --family, --variant and --scope narrow the selection (they are refused without --api v2), and each file gets one line naming its outcome and check groups, for example e-invoices/invoice.pdf: invalid (pdfa passed, attachment_metadata failed, invoice_xml passed). A refusal shows its problem code. The report adds "api_version": "v2".

The CLI requires an explicit --ruleset (immutable ID or latest) and a new --output path. Individual files, directories and quoted recursive globs work; duplicates are submitted once, unmatched patterns and paths/symlinks outside --workspace (default current directory) fail. Directories select *.xml. Reports are mode 0600 on POSIX. Existing paths, including symlinks, are refused before a request; the CLI never overwrites an input or prior report.

Exit codes are 0 all valid, 1 at least one invalid and no service error, 2 configuration, input, HTTP, transport or response-integrity failure. Errors take precedence in a mixed run. Once input/output setup succeeds, the JSON report is written for both valid and failed validations. Setup failures print only a safe diagnostic. Human output contains counts, check groups and problem codes, never finding messages.

Every document is sent exactly once per run, at most 5 MiB (20 MiB for a V2 PDF), with a default 30-second HTTP timeout (45 for a V2 PDF) and a 4 MiB response limit. Redirects are refused. There are no automatic retries or idempotency keys: a new run/call may be a new billable operation, even if an earlier response was lost. A timeout does not cancel work already accepted by the API. Do not retry automatically on 429/5xx without accounting for that behaviour.

The report schema remains financewolf/action-results/v1, shared with the GitHub Action: totals, valid/invalid/error counts and per-file results. Full results can contain invoice text; review storage, access and retention. XML is sent to Ironfang Finance under the authenticated API retention policy. Validation neither transmits through Peppol nor certifies tax/legal compliance or recipient acceptance. Public PyPI publication is not claimed by this review candidate.

Metadata

Release files for ironfang-finance 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ironfang-finance 2.0.0
File Size Uploaded Provenance
ironfang_finance-2.0.0.tar.gz 24.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ironfang-finance 2.0.0
File Interpreter ABI Platform
ironfang_finance-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.1 kB

Release files / ironfang_finance-2.0.0.tar.gz

Download URL ironfang_finance-2.0.0.tar.gz
Size 24.7 kB
Tags Source
SHA-256 checksum
How to use checksums
f103c6bf516af14f4c2220d577682e90ccfbcbd603f81b3cdbf16ccf0c5d8abb
BLAKE2b-256 checksum
How to use checksums
ea2e8330d99d9769635175b5c15d336fc1cf9548a53fb4cd3c5d271d097a4e1a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / ironfang_finance-2.0.0-py3-none-any.whl

Download URL ironfang_finance-2.0.0-py3-none-any.whl
Size 18.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ac158ca385264c59b39489a97614225f807a5b0414686a6df7336ee2c56d3df4
BLAKE2b-256 checksum
How to use checksums
4c5d2fe4434edae1b47b40bd89a1451d22eaa343956bc3e00570362a9fb4c1d7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Security for ironfang-finance 2.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page