From forgiving PDFs to strict XML

A PDF invoice is forgiving. If your ERP prints unit of measure "Kart." instead of "XCT", leaves the buyer’s VAT number on the second address line, or has a one-cent rounding difference between the sum of line items and the invoice subtotal, a human accounts-payable clerk still processes it.

A structured electronic invoice—governed by European standard EN 16931 and national profiles such as Peppol BIS Billing 3.0, Germany’s XRechnung / ZUGFeRD 2.x, or Spain’s Veri*factu billing-record schema—is validated by machine before it ever reaches a person. If a single required semantic field (`BT-*`) is missing or a single mathematical rule (`BR-CO-*`) fails by €0.01, the access point or tax authority gateway rejects the document outright—blocking revenue collection until the underlying ERP record is corrected.

The European regulatory calendar

For multi-entity businesses operating across Europe, domestic mandates and the EU-wide VAT in the Digital Age (ViDA) directive converge over the next four years:

Jurisdiction & frameworkStandard / technical formatKey statutory milestones
Germany
Wachstumschancengesetz
EN 16931 (XRechnung XML or hybrid ZUGFeRD 2.x) 1 Jan 2025: Mandatory B2B receipt for all domestic firms.
1 Jan 2027: Mandatory B2B issuance (turnover > €800k).
1 Jan 2028: Mandatory B2B issuance for all remaining firms.
Belgium
B2B Peppol Mandate
EN 16931 via Peppol BIS Billing 3.0 (UBL 2.1) 1 Jan 2026: Mandatory structured B2B e-invoicing for VAT-registered Belgian enterprises.
France
Finance Law Mandate
EN 16931 (Factur-X, UBL, CII) via PDP / PPF 1 Sep 2026: Mandatory receipt for all firms; mandatory issuance for large and mid-cap companies.
1 Sep 2027: Mandatory issuance for SMEs and micro-enterprises.
Spain
Veri*factu & Ley Crea y Crece
AEAT Veri*factu chained hash XML (RD 1007/2023, RD 254/2025, RDL 15/2025) 1 Jan 2027: Mandatory Veri*factu billing-system integrity for Corporate Income Tax entities.
1 Jul 2027: Mandatory for self-employed professionals (IRPF).
European Union
VAT in the Digital Age (ViDA)
EN 16931 structured e-invoice + near-real-time Digital Reporting (DRR) 1 Jul 2030: Mandatory structured e-invoicing within 10 days and transaction-level DRR for all intra-EU cross-border B2B trade.

Statutory timelines as enacted through March 2025 (EU ViDA) and December 2025 (Spain RDL 15/2025 extension). Primary legal citations listed below.

Worked example: the BR-CO-10 rounding trap

One of the most common reasons an ERP’s XML export fails Peppol or XRechnung validation is Rule BR-CO-10 of EN 16931: the document-level sum of invoice line net amounts (BT-106) must equal the exact sum of the individual rounded line net amounts (Σ BT-131), where each BT-131 is rounded to two decimal places in the XML.

Consider a three-line wholesale invoice where each line bills 333 units of a fastener at a net price of €0.0310 per unit (333 × €0.0310 = €10.323 unrounded):

Invoice elementEN 16931 validation resultERP floatXML (2 dec)
Line 1 · BT-131 (333 × €0.0310)Valid line extension (rounded to 2 decimals)€10.3230€10.32
Line 2 · BT-131 (333 × €0.0310)Valid line extension (rounded to 2 decimals)€10.3230€10.32
Line 3 · BT-131 (333 × €0.0310)Valid line extension (rounded to 2 decimals)€10.3230€10.32
Naive ERP header · BT-106REJECTED (BR-CO-10): BT-106 (€30.97) ≠ Σ BT-131 (€30.96)€30.9690€30.97
Compliant header · BT-106PASSED: Header sums already-rounded BT-131 values—€30.96

Under EN 16931 Schematron rules BR-CO-10 and BR-CO-15, header totals must be computed from the rounded 2-decimal line values (or bridged via BT-114 RoundingAmount).

Four ERP master-data fields that break

Beyond rounding logic, four master-data gaps cause the majority of schema rejections during e-invoicing rollouts:

  1. Custom units of measure instead of UN/ECE Recommendation 20 codes. EN 16931 requires every invoiced quantity (BT-129) to carry a standard unit code (BT-130) from UN/ECE Rec 20 / Rec 21 (such as C62 for piece, KGM for kilogram, HUR for hour). Free-text ERP units like "Stück", "pcs", "caja" or "day" fail schema validation unless mapped in the item master.
  2. Missing or malformed Buyer VAT / Endpoint IDs. Peppol routing requires a valid participant identifier (BT-49) and properly formatted VAT registration number (BT-48, prefixed with the two-letter ISO country code) on the billing entity, not buried in a free-text comment field.
  3. Unmapped VAT exemption reason codes. When an invoice line carries 0% VAT (intra-Community supply, reverse charge or export), EN 16931 rules BR-AE-*, BR-IC-* and BR-G-* require both the exact tax category code (BT-151: AE, K, G) and an explicit exemption reason or legal reference (BT-120 / BT-121).
  4. Missing Buyer Reference (BT-10). Both XRechnung (where BT-10 carries the Leitweg-ID or buyer reference) and Peppol BIS Billing 3.0 require either a buyer reference (BT-10) or a purchase order reference (BT-13) on every invoice header.

SQL pre-flight audit on ERP tables

Before connecting an e-invoicing gateway, run a pre-flight SQL audit against your ERP billing tables over the last 90 days of invoices to quantify exactly which records would fail EN 16931 validation today:

SQL pre-flight · EN 16931 readiness checkERP invoice & master tables
WITH invoice_rollup AS (
  SELECT
    h.invoice_id,
    c.vat_id                                                 AS bt_48_buyer_vat,
    h.buyer_reference                                        AS bt_10_buyer_ref,
    ROUND(SUM(l.qty * l.net_unit_price), 2)                  AS unrounded_header_sum,
    SUM(ROUND(l.qty * l.net_unit_price, 2))                  AS sum_of_rounded_bt131,
    COUNT(*) FILTER (WHERE u.unece_rec20_code IS NULL)       AS unmapped_uom_lines
  FROM erp_invoice_headers h
  JOIN erp_invoice_lines l USING (invoice_id)
  LEFT JOIN erp_customers c ON h.customer_id = c.erp_customer_id
  LEFT JOIN ref_uom_unece_map u ON l.erp_uom_code = u.erp_uom_code
  GROUP BY 1, 2, 3
)
SELECT
  COUNT(*)                                                                  AS total_invoices_checked,
  COUNT(*) FILTER (WHERE bt_48_buyer_vat IS NULL OR bt_48_buyer_vat = '')   AS missing_bt48_vat,
  COUNT(*) FILTER (WHERE bt_10_buyer_ref IS NULL OR bt_10_buyer_ref = '')   AS missing_bt10_ref,
  COUNT(*) FILTER (WHERE unmapped_uom_lines > 0)                            AS fails_unece_uom,
  COUNT(*) FILTER (WHERE unrounded_header_sum <> sum_of_rounded_bt131)      AS fails_brco10_rounding
FROM invoice_rollup;

Sources & regulatory references