Back to Changelog

XRechnung 3.0.2 Conformance

May 7, 2026

100% KoSIT conformance: all 86 official reference messages validate green. Plus XRechnung Extension, construction-sector tax (§13b/§48 EStG), a cross-country helper rollout, and 8 new request fields + 3 new endpoints in the REST API.

100% KoSIT conformance

All 86 official KoSIT reference messages validate green against Schematron 3.0.2.

XRechnung Extension

Sub-invoice lines (BG-DEX-01) and third-party payments (BG-DEX-09) — switch via profile: xrechnung-extension.

Construction: §13b / §48

Reverse charge §13b UStG (norm-supported) and §48 EStG construction withholding via structured note.

REST API schema sync

8 new optional fields and 3 new endpoints, all documented in /openapi-1-3.json.

Full KoSIT Conformance

Previously: ~70% norm-conformant — some BTs were in the interface but not in the XML. Now: all 86 official KoSIT reference messages from the xrechnung-testsuite repository validate green via xmllint-wasm + Schematron 3.0.2 in the test suite.

A corpus-driven round-trip test parses → regenerates → re-parses each fixture and compares the canonical shape (type, invoice number, currency, item count, tax rates, line totals, seller/buyer presence, sub-item depth, third-party payment count).

XRechnung Extension

Activated via invoice.profile = "xrechnung-extension". The CustomizationID switches to the extension URN and the following structures become available:

Sub-Invoice-Lines (BG-DEX-01)

items[].subItems[] renders as nested cac:SubInvoiceLine inside the parent cac:InvoiceLine in UBL. Arbitrary depth (KoSIT corpus uses 2-3 levels). Each sub-line has exactly one cac:ClassifiedTaxCategory (BR-DEX-03). Sum check BR-DEX-02 (Σ child BT-131 = parent BT-131) is enforced by Schematron.

Third-Party Payments (BG-DEX-09)

thirdPartyPayments[] with type, paidAmount, description emits as cac:PrepaidPayment with ID + PaidAmount + InstructionID. Satisfies BR-DEX-10..14 (required field combinations, max 2 decimals, currency = BT-5).

Example: Extension request with sub-items + third-party payment

json
1{
2 "invoice": {
3 "invoiceNumber": "BAU-2026-042",
4 "type": "invoice",
5 "issueDate": "2026-05-07",
6 "currency": "EUR",
7 "profile": "xrechnung-extension",
8 "serviceCategory": "construction",
9 "constructionTax": {
10 "exemptionCertificateNumber": "FNR-2026-12345",
11 "recipientTaxOffice": "Finanzamt Berlin Nord"
12 },
13 "seller": { "name": "Bau Acme GmbH", "countryCode": "DE", "vatId": "DE123456789" },
14 "buyer": { "name": "Großbau AG", "countryCode": "DE", "vatId": "DE987654321" },
15 "items": [
16 {
17 "position": 1,
18 "description": "Bauabschnitt A — Rohbau",
19 "quantity": 1,
20 "unitPrice": 50000.00,
21 "taxRate": 19,
22 "subItems": [
23 { "type": "DETAIL", "description": "Fundament", "netAmount": 20000.00 },
24 { "type": "DETAIL", "description": "Mauerwerk", "netAmount": 30000.00 }
25 ]
26 }
27 ],
28 "thirdPartyPayments": [
29 { "type": "advance", "paidAmount": 10000.00, "description": "Bauherren-Vorauszahlung" }
30 ],
31 "subtotal": 50000.00,
32 "total": 59500.00
33 }
34}

Construction Sector: §13b + §48 EStG

§13b UStG

Reverse charge (norm-supported)

Set serviceCategory: "construction" and use the AE tax category. The standard note „Steuerschuldnerschaft des Leistungsempfängers gemäß §13b UStG“ is emitted in both UBL and CII.

§48 EStG

Construction withholding (norm gap)

XRechnung has no field for exemption certificate or 15% withholding. Solution: structured note in BT-22 following the KoSIT #SKONTO# convention. Use constructionTax with exemptionCertificateNumber / withholdingPercent / recipientTaxOffice — emitted as #FREISTELLUNG#NR=...#PROZENT=15.00#FA=...# note in both UBL and CII.

Cross-Country Helper Rollout

Three reusable helpers close structural gaps across multiple countries at once. Previously: only DE had them. Now rolled out to 12 countries:

  • BG-24Attachments (BT-122..125) — embedded documents in UBL and CII, 200 MiB cap per attachment (KoSIT-aligned). Rolled out to DE, BE, NL, PT, FR.
  • BR-CL-01UBL CreditNote Root Switch — TypeCode 381 lives under ubl:CreditNote root (not ubl:Invoice). Rolled out to DE, BE, NL, PT.
  • BG-20/21Document-Level Allowance/Charge — BT-95/96 + BT-102/103 with ReasonCode and TaxCategory. Rolled out to DE, BE, NL, PT, FR.

Additionally: new GR myDATA structural validator (lib-invoice-validator-gr) and a CH ZUGFeRD wrapper (DE CII generator with CHF + CHE VAT-ID propagation), enabling EN-16931-conformant XML next to the QR-Bill PDF.

REST API: 8 New Fields + 3 New Endpoints

The OpenAPI/Zod schema was two sprints out of sync with the invoice-backend interface. Now everything is explicitly typed, documented, and example-payloaded. All fields are optional and .passthrough() is preserved — no breaking changes for existing clients.

New Optional Fields in invoiceSchema

  • profilexrechnung | xrechnung-extension — switches Extension mode on
  • items[].subItemsRecursive sub-invoice lines (BG-DEX-01), arbitrary depth
  • thirdPartyPaymentsThird-party payments (BG-DEX-09)
  • attachmentsEmbedded documents (BG-24, BT-122..125)
  • referencedInvoiceNumber + DatePredecessor invoice (BG-3, BT-25/26) for credit notes
  • deliveryNoteDelivery note reference (BT-16/17)
  • serviceCategoryconstruction | general — enables §13b reverse charge behavior
  • constructionTax§48 EStG construction withholding (exemption cert, withholding percent, tax office)

New Endpoints

POST

/api/v1/invoice/es/verifactu-qr

Spanish VeriFactu QR code per Real Decreto 1007/2023 Annex II — URL, PNG, SVG.

POST

/api/v1/invoice/ch/zugferd/generate

CH wraps the DE CII generator with CHF + CHE-VAT-ID. Use case: CH supplier invoicing DE/AT recipients needs EN-16931-conformant XML next to the QR-Bill PDF.

Schema

validationErrorSchema.code

Tightened from free string to a discriminated union of 50+ explicit DE_* / GR_* codes plus a fallback string for dynamic Schematron rule IDs.

Example: VeriFactu QR request

bash
1POST /api/v1/invoice/es/verifactu-qr
2 
3{
4 "sellerNif": "B12345674",
5 "invoiceSeries": "2026/A",
6 "invoiceNumber": "0001",
7 "invoiceDate": "07-05-2026",
8 "total": 1234.56,
9 "verifactuMode": false
10}
11 
12# Response
13{
14 "url": "https://prewww2.aeat.es/wlpl/TIKE-CONT/ValidarQR?nif=B12345674&numserie=2026%2FA-0001&fecha=07-05-2026&importe=1234.56",
15 "png": "<base64 PNG>",
16 "svg": "<svg ...>"
17}