Formats & syntax

UBL (Universal Business Language): structure and use of the OASIS syntax

UBL (Universal Business Language) is the OASIS-standardised XML syntax for business documents and the second syntax EN 16931 permits. It is laid out more flatly than CII and groups fields by business object. Peppol BIS Billing 3.0 requires UBL, and the XRechnung variant common in Germany is UBL as well.

Also:
Universal Business Language · OASIS UBL · UBL 2.1
Reviewed on 2026-08-26.

Origin and role

UBL is maintained by OASIS, a consortium for open standards, and describes not only invoices but a whole family of business documents — order, despatch advice, catalogue, credit note. The invoice is one document type within it.

In Europe UBL is ubiquitous mainly because Peppol builds on it. Wherever public procurement is handled electronically, UBL is almost always the syntax.

The structure

UBL lays its groups out flat rather than nesting them deeply:

text
1ubl:Invoice
2 cbc:CustomizationID which rule set applies (BT-24)
3 cbc:ID invoice number (BT-1)
4 cbc:IssueDate issue date (BT-2)
5 cbc:BuyerReference buyer reference (BT-10)
6 cac:AccountingSupplierParty seller (BG-4)
7 cac:AccountingCustomerParty buyer (BG-7)
8 cac:PaymentMeans payment instructions (BG-16)
9 cac:TaxTotal tax
10 cac:LegalMonetaryTotal totals
11 cac:InvoiceLine lines (BG-25)

Anyone opening an invoice in XML for the first time usually finds their way around here faster than in CII: the order roughly follows that of a printed document.

cbc and cac

The two prefixes divide every element into two classes:

  • cbccommon basic components: single values. A number, a date, an amount.
  • caccommon aggregate components: groups that in turn contain elements. A party, an address, a line.

The rule of thumb: what is a leaf on the tree is cbc. What forms a branch is cac.

One field in its place

The same VAT identification number (BT-31) as in the CII article, here in UBL:

xml
1<cac:AccountingSupplierParty>
2 <cac:Party>
3 <cac:PartyLegalEntity>
4 <cbc:RegistrationName>Muster GmbH</cbc:RegistrationName>
5 </cac:PartyLegalEntity>
6 <cac:PartyTaxScheme>
7 <cbc:CompanyID>DE811128135</cbc:CompanyID>
8 <cac:TaxScheme>
9 <cbc:ID>VAT</cbc:ID>
10 </cac:TaxScheme>
11 </cac:PartyTaxScheme>
12 </cac:Party>
13</cac:AccountingSupplierParty>

The contrast with CII is easy to see: where CII distinguishes the kind of number through an attribute (schemeID="VA"), UBL uses a dedicated sub-element (cac:TaxScheme carrying VAT). Same statement, different mechanics.

The specification identifier

One element deserves particular attention, because it governs the entire validation:

xml
1<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_3.0</cbc:CustomizationID>

By this identifier (BT-24) a recipient recognises which rule set to check against. If it names only the European standard, they will not check the German add-on rules — and an invoice that was supposed to be an XRechnung arrives as a plain EN 16931 invoice.

🔴 A wrong CustomizationID produces no error. It produces a check against the wrong rule set, and that only surfaces at the recipient.

When you meet UBL

When generating, whenever Peppol BIS is the target — there is no alternative there. For XRechnung, UBL is the more common of the two permitted variants.

When receiving, as unavoidably as CII. Anyone taking invoices from several sources gets both syntaxes, unannounced.

💡 So the same advice applies as for CII: syntax belongs at the outer boundary, not in your data model. Thinking internally in BT fields makes switching between UBL and CII a question of output — not a rebuild of business logic.

Frequently asked questions