Ironfang Finance validates XRechnung invoices and credit notes in both of its syntaxes, UBL 2.1 and UN/CEFACT CII, against the official XRechnung validator configuration, and reads them as documents. Try it without an account in the XRechnung validator and the XRechnung viewer, also in German.
What is checked
A document passes through these layers in order. A layer that fails stops the ones after it, and the result says each layer was not reached rather than passed.
| Layer | What it checks |
|---|---|
input | The size and framing of the request, before anything is parsed. |
xml | Well-formed XML within the limits, with no DTD, entities beyond the predefined five, or XInclude. |
xsd | The XML schema of the document's syntax: UBL 2.1, or UN/CEFACT CII D16B, the edition XRechnung uses. |
en16931 | The European standard's business rules, in the edition the XRechnung bundle pins. |
xrechnung | The XRechnung rules (BR-DE-* and the Peppol-derived rules XRechnung includes). |
The rules are the official configuration run byte for byte, with the levels it sets. That configuration lowers some rules from their own flag, so a finding carries both: severity, which decides the outcome, and rule_flag, the rule's own. Only fatal findings fail a document; warning and information never do.
Versions and variants
- XRechnung 3.0.2, in the technical bundle of 31 August 2026. The result names the exact release in
ruleset.official_releaseandruleset.technical_release. - UBL 2.1 Invoice and CreditNote; CII invoices and credit notes, the kind decided by the type code.
- The core variant. The Extension and the CVD variant are recognised and refused with
unsupported_variant, never checked against the core rules as if they were something else. - XML only. A PDF, including ZUGFeRD and Factur-X, is answered
scope_unavailable.
Validate with the API
POST /finance/v2/einvoices/validate takes the XML as the body. Name the family, as this script does, so that a document which declares no family is still checked as XRechnung and one which declares another is refused with what it declares. The script keeps the result in result.json and derives the Idempotency-Key from the file, so a retry returns the first result and is not charged again.
#!/usr/bin/env bash
# Validate one XRechnung with the Ironfang Finance API and keep the result.
#
# IRONFANG_API_KEY=... ./validate-xrechnung.sh invoice.xml
#
# The result is written to result.json. A retry with the same file sends
# the same Idempotency-Key, so it returns the first result and is not
# charged again.
set -euo pipefail
file="$1"
base="${IRONFANG_FINANCE_API:-https://api.ironfang.uk/finance}"
key="xr-$(sha256sum "$file" | cut -c1-40)"
curl --fail-with-body --silent --show-error \
"$base/v2/einvoices/validate?family=xrechnung" \
-H "Authorization: Bearer $IRONFANG_API_KEY" \
-H "Content-Type: application/xml" \
-H "Idempotency-Key: $key" \
--data-binary "@$file" \
--output result.json
grep -o '"outcome":"[a-z]*"' result.json | head -n 1
| Query parameter | Meaning |
|---|---|
family | xrechnung. Without it the family is read from the document's specification identifier. |
variant | core, the default for XRechnung. |
document_type | invoice, credit_note or auto (the default: read from the document). |
ruleset | latest (the default) or an exact release id from GET /finance/v2/einvoices/rulesets. An exact release names the whole selection; a selector that contradicts it is selection_conflict. |
Without an API key the same request is anonymous: nothing is stored and tighter rate limits apply. With a key, a completed validation is one operation from your Finance allowance, charged once the schema check reaches a verdict, and the result is kept for 30 days at GET /finance/v2/einvoices/results/{id}. The full contract is the V2 OpenAPI document.
Reading a result
outcome is valid or invalid for a completed validation; anything that stopped a verdict, such as a timeout, is a Problem with outcome: indeterminate and nothing charged. coverage says what the result establishes: at XML scope, the XML document and nothing about a PDF. Each finding has its rule id unchanged, a fixed message for its layer, and an XPath location; the official rule texts are not repeated, because they can carry invoice values. next_actions includes view when the document can be opened in the viewer.
Explained rules
These rules have a reviewed explanation, in English and German, which the tools show beside the finding. Each was checked against the official validator with a fixture that breaks it.
| Rule | Level | What it means |
|---|---|---|
BR-DE-1 | fatal | Payment instructions are missing |
BR-DE-2 | fatal | The seller contact is missing |
BR-DE-3 | fatal | The seller's city is missing |
BR-DE-4 | fatal | The seller's post code is missing |
BR-DE-6 | fatal | The seller contact's telephone number is missing |
BR-DE-7 | fatal | The seller contact's email address is missing |
BR-DE-8 | fatal | The buyer's city is missing |
BR-DE-9 | fatal | The buyer's post code is missing |
BR-DE-15 | fatal | The buyer reference (Leitweg-ID) is missing |
BR-DE-16 | fatal | The seller's VAT identifier or tax number is missing |
BR-DE-19 | warning | The payment account is not a valid IBAN |
BR-DE-23-a | fatal | A credit transfer names no account |
BR-DE-27 | warning | The contact telephone number has fewer than three digits |
BR-DE-TMP-32 | information | No delivery date or service period is given |
Viewing
POST /tools/v2/invoice/view reads a UBL or CII document into the invoice-view/2 model: the document's parties, lines, VAT breakdown, totals and payment details, each value the exact source string with its XML path and line. CII dates are read from their format code; a date in a format that cannot be read safely is kept as written, with a notice. An amount without its own currency has none: the document currency is never assumed. Anything the model does not show is counted in unshown_elements and the first few are named in notices, so a partial reading says so. Viewing never validates.
Problems
| Code | When |
|---|---|
family_mismatch | The document declares another family than the one named; detected says what it declares. |
family_undetected | No family was named and the document declares none Ironfang recognises. |
unsupported_variant | The XRechnung Extension or CVD. |
unsupported_document_type | Not an invoice or credit note, or a type that contradicts the one named. |
scope_unavailable | A PDF, or a hybrid scope asked for XML. |
payload_too_large | XML over 5 MiB. |
idempotency_conflict | The Idempotency-Key was used for different bytes or a different selection. |
validator_unavailable, validation_timeout, internal_error | No verdict: indeterminate and not charged. Retry. |
