← Back to all articles

Understanding EN16931: Europe's invoice data model

SealDoc Team · · 7 min read

EN16931 is the European standard that defines what an e-invoice must contain. It is not an XML format. It is a semantic data model. Every major European e-invoicing format, whether Peppol BIS Billing 3.0, Factur-X, ZUGFeRD, or XRechnung, is an implementation of EN16931 in a specific XML syntax.

Understanding EN16931 saves time when debugging validation failures, explaining integration requirements to ERP vendors, or implementing a new invoice profile from scratch.

What EN16931 actually specifies

EN16931 consists of two parts:

  • EN 16931-1 defines the semantic data model: what data elements an invoice can contain, which are mandatory, and what the business rules are
  • EN 16931-2 defines the syntax bindings: how the semantic model maps to UBL 2.1 XML and UN/CEFACT CII XML

The result is that a Peppol BIS Billing 3.0 UBL invoice and a Factur-X CII invoice can represent the same business invoice. The semantic content is identical. The XML syntax is completely different.

Business Terms and Business Groups

EN16931 organizes invoice data into Business Groups (BG) and Business Terms (BT).

A Business Group is a collection of related terms. A Business Term is a single data element with a defined identifier, name, cardinality, and data type.

The most important groups at the top level:

GroupContent
BG-2 Process controlSpecification identifier (BT-24), business process type (BT-23)
BG-4 SellerName, address, VAT number, legal registration
BG-7 BuyerName, address, reference identifier, electronic address
BG-22 Document totalsTax basis, invoice total, VAT amount, amount due
BG-25 Invoice lineQuantity, unit price, VAT rate, line net amount

The full model runs to over 150 BTs across all groups. Most implementations only need a subset, but validating a document requires knowing which BTs are mandatory for the target profile.

Business Terms developers stumble on

Most validation failures come from a small set of BTs that are either misunderstood or poorly documented in implementation guides.

BT-24: Specification identifier

This must be a specific URI identifying which profile the invoice claims to conform to. For Peppol BIS Billing 3.0:

urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1

Getting this wrong causes the receiver’s validator to reject the invoice before it checks any field contents. Each profile (EN16931 core, Peppol BIS 3.0, Peppol BIS 3.0 with national extension) has a different URI.

BT-10: Buyer reference

Used differently across countries. In Germany, this carries the Leitweg-ID, a mandatory routing identifier for B2G invoices. In most other countries it is an internal purchase order reference or left empty. The field is optional in EN16931 base but mandatory in the German national profile.

BT-49: Buyer electronic address

The Peppol participant ID of the buyer. Format: scheme:identifier. For a Belgian company identified by enterprise number:

<cbc:EndpointID schemeID="0208">0468863455</cbc:EndpointID>

Required when transmitting over the Peppol network. Many implementations omit it for B2B invoices outside Peppol, which is acceptable in base EN16931 but invalid in Peppol BIS profiles.

BT-131: Invoice line net amount

The net amount for a single line, calculated as quantity times unit price minus any line-level allowances. EN16931 business rule BR-CO-10 requires that the sum of all BT-131 values equals BT-106 (sum of invoice line net amounts).

Rounding matters here. The standard expects arithmetic to be performed on raw values and rounded at the aggregate level, not per line. Rounding each line independently and then summing produces discrepancies that fail BR-CO-10 for large quantities.

BT-110: VAT category tax amount

The VAT amount per tax category. EN16931 rule BR-CO-15 requires that the invoice total minus the tax basis equals the sum of all BT-117 (VAT category tax amounts). Errors here are often caused by floating-point arithmetic or premature rounding.

Business Rules: the validation layer

Business Rules (BR) are formal constraints expressed in Schematron. There are two categories.

Structural rules enforce field presence and format:

BR-01: An Invoice shall have a Specification identifier (BT-24).
BR-02: An Invoice shall have an Invoice number (BT-1).
BR-04: An Invoice shall have an Invoice currency code (BT-5).

Calculation rules enforce arithmetic consistency:

BR-CO-10: Sum of Invoice line net amount (BT-106) = sum of all BT-131 values.
BR-CO-15: Invoice total VAT amount (BT-110) = sum of all BT-117 values.
BR-CO-16: Amount due for payment (BT-115) = Invoice total with VAT (BT-112)
          - Paid amount (BT-113) + Rounding amount (BT-114).

Peppol BIS 3.0 adds national extension rules on top of EN16931 base rules. Examples:

BR-DE-TMP-32: Delivery date (BT-72) is required for German B2G invoices.
BR-DE-18:     VAT identifier of the seller (BT-31) or tax registration (BT-32)
              shall be present.

These extension rules vary by country profile and are published with each Peppol BIS release.

How EN16931 maps to UBL and CII

The two XML syntaxes handle the same BTs but use completely different element names and structures. This is why code that parses UBL invoices cannot parse CII invoices without a separate implementation, even though both are EN16931-compliant.

Seller name (BT-27) in both syntaxes:

UBL 2.1:

<cac:AccountingSupplierParty>
  <cac:Party>
    <cac:PartyName>
      <cbc:Name>Acme GmbH</cbc:Name>
    </cac:PartyName>
  </cac:Party>
</cac:AccountingSupplierParty>

UN/CEFACT CII:

<ram:SellerTradeParty>
  <ram:Name>Acme GmbH</ram:Name>
</ram:SellerTradeParty>

Both map to BT-27. The semantic content is identical. The XML path differs completely.

Peppol BIS 3.0 uses UBL. Factur-X and ZUGFeRD use CII. XRechnung supports both. The EN16931-2 mapping document (free from CEN/TC 434) lists both paths for every BT and is worth keeping open during implementation.

Schematron validation

EN16931 validation is implemented as Schematron rules that are pre-compiled to XSLT 2.0. The official rule sets are published with each Peppol BIS release:

github.com/OpenPEPPOL/peppol-bis-invoice-3/releases

The artifacts contain compiled XSLT files:

peppol-en16931-ubl.xsl    (for UBL invoices)
peppol-en16931-cii.xsl    (for CII invoices)

Running either against an invoice returns SVRL (Schematron Validation Report Language). A failed rule looks like:

<svrl:failed-assert test="..." location="/Invoice/...">
  <svrl:text>
    [BR-CO-10]-Sum of Invoice line net amount (BT-106) = 
    sum of Invoice line net amount (BT-131).
  </svrl:text>
</svrl:failed-assert>

An XSLT 2.0 processor is required. In .NET, Saxon HE (open source, no enterprise license needed) is the standard choice. In Java, Saxon or Xerces both work.

Common implementation mistakes

Mixing UBL and CII element paths. Developers working with both formats paste element names from the wrong binding. The EN16931-2 mapping document prevents this.

Assuming presence rules are the same across profiles. A field that is optional in EN16931 base may be mandatory in Peppol BIS 3.0 or in a national extension. Validate against the target profile, not the base standard.

Rounding at the wrong level. Compute raw arithmetic totals across all lines, then round the aggregate. Rounding each line independently and summing rounded values produces arithmetic inconsistencies that fail BR-CO-10, often by a few cents on large invoices with many lines.

Wrong BT-24 for the target profile. Each profile has a specific specification identifier URI. Using the EN16931 base URI on a Peppol BIS 3.0 invoice causes profile-level validation to reject the document immediately.

Hardcoding VAT category codes. EN16931 defines specific code values for VAT categories (S, Z, E, AE, K, G, O, L, M). Many implementations hardcode “S” (standard rate) and break when processing reverse-charge or zero-rated invoices.

EN16931 is infrastructure knowledge

EN16931 underpins every European e-invoicing mandate. As requirements roll out across Belgium, France, Germany, and Poland, understanding the semantic model becomes increasingly important for developers building or maintaining invoice pipelines.

Understanding the BT/BG structure, the calculation rules, and the syntax bindings puts you in a position to debug validation failures that would otherwise require hours of spec reading, implement new profiles cleanly, and communicate clearly with ERP vendors and compliance teams.

The practical problem is not learning EN16931 once. It is keeping implementations correct as rule sets are updated with each Peppol BIS release, as national extensions add new mandatory fields, and as rounding edge cases surface in production with real invoice data from real ERP systems.

SealDoc ships with rule sets that track Peppol BIS releases. When you generate an invoice through the SealDoc API, the document is validated against the correct profile before it leaves the system. BR-CO-10 and BR-CO-15 are enforced server-side so that rounding errors do not reach your buyers. When you receive a validation failure from a trading partner, the SealDoc public validator accepts the document and maps each failure back to the specific BT and BR that was violated, which cuts diagnosis time from hours to minutes.

If you are implementing EN16931 from scratch, the validator is a useful calibration tool: generate a candidate document, run it through, fix what the report identifies, repeat.


← Back to all articles