Skip to content
einvoicing.dev

The guideChapter 04

The invoice itself

Business terms, the totals ladder that has to reconcile exactly, and the VAT breakdown that is not one number.

By now you have a network that can carry a document and an identifier that says where it goes. This chapter is about the document.

Three names get used loosely and it is worth pinning them down, because they are three different things.

EN 16931 is the European standard. It is a semantic model: it says what an invoice means, not what it looks like. Every piece of an invoice gets a code, BT-1 for the invoice number, BT-5 for the currency, BG-25 for the group that is an invoice line. Nothing in it is XML.

Peppol BIS Billing 3.0 is a profile of that standard, narrowed. Where EN 16931 permits a choice, the profile often makes it for you, and it adds rules of its own. The current release is 3.0.21.

UBL 2.1 is the syntax: the XML that carries the model.

So the document you have to produce is UBL 2.1, shaped by EN 16931, and constrained further by Peppol. When a validator tells you something is wrong it will name the rule, and the rule tells you which of those three is unhappy.

Business terms are the vocabulary

Once you know the codes, the rules become readable. BR-02 says “An Invoice shall have an Invoice number (BT-1).” It is not asking for a field called number; it is asking for the thing that means “the invoice’s number”, which in UBL happens to be cbc:ID.

That indirection is the point. The same semantic model can be expressed in UBL or in CII, and a rule written against business terms holds for both. It also means an error message that only quotes XPath is doing half a job: you want the business term, because that is what maps back to your own data model.

A handful you will meet immediately:

  • BT-1 invoice number, BT-2 issue date, BT-5 currency
  • BT-27 seller name, BT-44 buyer name
  • BT-10 buyer reference, BT-13 purchase order reference
  • BG-25 invoice line, BT-131 line net amount
  • BT-109 total without VAT, BT-110 total VAT, BT-112 total with VAT

The minimum

Strip away everything optional and a valid invoice still needs an invoice number, an issue date, a currency, both party names, and at least one line. Those are BR-02, BR-03, BR-05, BR-06, BR-07 and BR-16, and they are the five-second sanity check on any document your code produces.

Peppol adds one that catches people out, because no other system has ever asked for it: a buyer reference or a purchase order reference, on every invoice. That is PEPPOL-EN16931-R003, and if your application has no field for either, it is the first thing to add.

The totals have to reconcile

This is where most rejections come from, and it is arithmetic rather than structure.

The totals form a ladder. Each line has a net amount, BT-131. Those sum to BT-106, the sum of line net amounts, which is BR-CO-10. Take off document-level allowances and add document-level charges and you get BT-109, the total without VAT, which is BR-CO-13. Add the total VAT, BT-110, and you get BT-112, the total with VAT, which is BR-CO-15. Then subtract anything already paid and you get the amount payable.

Every one of those is an equality that has to hold exactly, which is why chapter 1 insisted on decimals rather than floats. Two invoices out of a thousand failing on a rounding difference of a penny is not an edge case, it is a Tuesday.

The safest approach is to stop storing totals as decisions and start computing them from the lines at the moment you build the document. If your system holds a total that somebody once typed, and the lines say otherwise, the document will say so too. POST /v1/conversions takes lines and computes the ladder for you, precisely so this class of failure cannot happen.

VAT is a breakdown, not a number

In your database VAT is probably one column. In the document it is a group, BG-23, repeated once per combination of category and rate, each carrying the taxable amount and the tax amount for that combination.

The category codes are the part worth learning:

  • S standard rate
  • Z zero rated
  • E exempt
  • AE reverse charge
  • K intra-community supply
  • G export outside the EU
  • O outside the scope of VAT

They are not interchangeable labels for “no VAT”. Each carries its own rules. BR-E-10 requires an exemption reason on an exempt breakdown. BR-AE-10 requires one on reverse charge. BR-Z-10 says a zero-rated breakdown must not have one. Getting the category right and the reason wrong is a rejection; so is the reverse.

If your invoicing code has a boolean for “VAT applies”, this is the section that will cost you the most, and it is worth finding out now rather than in the quarter you have to ship.

Parties, and what they need

A party is more than a name. Each side needs a name, a postal address with a country code, and for the seller a VAT identifier where one applies. The electronic address is the Peppol identifier from chapter 3, and it is a different thing from the postal address and from the VAT number, even when it contains the VAT number.

A registration name and a company number can both appear, and this is where the UK shape gets slightly awkward: the company number has a home in the document, and no home on the network.

Lines

A line needs an identifier, a name, a quantity with a unit of measure, a net price, and a VAT category. The unit code comes from a published list rather than free text, so “each” is C62, and a line that says hours will be rejected where one that says HUR is not.

Line-level detail is another place where invoicing software has usually taken a shortcut. A single line that says “Consulting, £1,000” is a valid invoice. It is also the point at which a buyer’s system cannot match your invoice to their purchase order, which is the entire reason they wanted an e-invoice.

Credit notes

A credit note is the same document with BT-3 set to 381 instead of 380, and a reference to the invoice it corrects, BG-3. Everything above still applies: the totals ladder, the VAT breakdown, the parties. There is no separate schema to learn, which is a relief, and no separate code path worth writing.

What this means for your model

Reading the standard, the mapping tends to come out like this:

  • You have a number, a date, a currency and two parties, and they map cleanly.
  • You have totals, and they should be computed rather than mapped.
  • You have a VAT figure, and it needs to become a breakdown.
  • You have lines, and they need a unit code and a category per line.
  • You have no buyer reference, and you need one.

Which is a morning’s schema work and a week of thinking about tax categories. Once the document exists, the next question is whether it passes, and that is chapter 5.

Checked against its sources on 18 September 2026

Get the rest by email

One email when the guide is finished, and an explainer on Budget day.

Developer docs

Getting a key, validating a document, and the API reference.