CRATEAPI

What is EN 16931? The standard under every EU e-invoice

Standards3 min read

If you're implementing e-invoicing for a European market, you'll hit the name EN 16931 before anything else. It's not a file format you can open — it's the semantic rulebook that every EU e-invoice format is built on, or at least measured against.

What EN 16931 actually is

EN 16931 is a European standard (published by CEN, the European Committee for Standardization) that defines a semantic data model for invoices: a list of roughly 150 business terms (seller name, VAT identifier, invoice line net amount, and so on — each with a stable code like BT-1 for the invoice number or BT-10 for the buyer reference) and a set of business rules that say how those terms must relate to each other (each with a code like BR-CO-15, "the invoice total amount must equal the sum of the invoice line net amounts, minus allowances, plus charges").

Crucially, EN 16931 does not say what the XML has to look like. It says what the invoice has to mean. That separation is why the same semantic content can be serialized in more than one XML syntax — which is exactly what happens in practice.

Two syntaxes, one model

The standard officially supports two XML syntaxes:

Because both syntaxes carry the same underlying business terms, a compliant invoice can usually be converted between them without losing information — that's what our own /v1/convert/ubl-to-cii and /v1/convert/cii-to-ubl endpoints do, and why they can afford to be lossless-or-rejected: if a document uses something the shared EN 16931 subset can't carry (document-level allowances/charges, prepaid amounts, attachments), conversion fails loudly with a 422 unsupported_features instead of quietly dropping data.

CIUS: national and sector flavors on top

EN 16931 leaves some room deliberately open — optional fields, a few places where a country can be stricter than the baseline. A CIUS (Core Invoice Usage Specification) is a formal restriction of EN 16931 for a specific context. The ones you'll run into most:

None of these invent new business terms. They restrict which of the existing EN 16931 fields are mandatory, and sometimes add rules of their own (that's why German XRechnung errors carry a BR-DE-* code and French ones carry BR-FR-* — same rule family, different national layer).

Not every EU invoice format is EN 16931. Italy's FatturaPA, Spain's Facturae and Poland's KSeF / FA_VAT are separate, older national XML vocabularies that cover domestic B2B/B2C invoicing outside the EN 16931 family — they existed before, or run in parallel to, the EU-wide EN 16931 push. See our formats hub for the full split between the pan-EU core and these national terminal formats.

Validating against it

In practice you rarely validate "against EN 16931" alone — you validate against a profile (plain EN 16931, Peppol, XRechnung, the French fr profile, RO). Every finding in the response carries the exact rule id, so you know which of the ~250 official rules failed and why:

curl -X POST "$BASE/v1/validate/ubl?profile=en16931" \
  -H "Content-Type: application/xml" --data-binary @invoice.xml
{
  "valid": false,
  "profile": "en16931",
  "counts": {"fatal": 1, "warning": 0},
  "findings": [
    {"severity": "fatal", "rule_id": "BR-CO-15",
     "message": "Invoice total amount without VAT (BT-109) must equal ..."}
  ]
}

Every BR-* and PEPPOL-* code we return links to a plain-language explanation with a fix — browse the full error code reference, or start with the official model itself in our UBL / Peppol landing page.

Keep reading

Want to try this against a real invoice?

Every example above calls the same API you can call today — validate for free, or read the full reference.