XRechnung for SaaS invoices: the fields your billing data must supply
Your first XRechnung usually arrives as a contract clause. A university, a state agency or a city administration buys your software and tells you that invoices are only accepted as XRechnung with a Leitweg-ID. From that point a nice PDF no longer does the job. Your billing system has to supply fields it has never stored before.
This article lists those fields, shows how typical SaaS lines (seats, prorated upgrades, usage) fit the EN 16931 data model, and says where the data comes from. How to check the result before sending is covered in validating XRechnung against EN 16931.
When a SaaS invoice has to be an XRechnung
Public contracting authorities in the EU must accept and process electronic invoices that comply with EN 16931. That is set out in Directive 2014/55/EU. Germany implements it with XRechnung, its national profile of the standard. The federal government, the states and municipalities each have their own rules on top, but the result for you as a supplier is the same: the buyer asks for an XRechnung and gives you the Leitweg-ID to address it to.
Between businesses in Germany, XRechnung is one of several permitted e-invoice formats. Since 2025 every domestic business has to be able to receive e-invoices, and from 2028 issuing them becomes mandatory. The transition periods and what they mean for choosing software are in choosing e-invoicing software for SaaS. For the data model the trigger hardly matters: once you produce complete EN 16931 data, you can output XRechnung, ZUGFeRD or Peppol BIS from it.
Fields a self-service checkout never collects
Every billing system has the basics: invoice number, date, addresses, VAT ID, amounts. XRechnung adds fields, some always mandatory and some only when the customer asks for them. The labels in brackets are EN 16931 business terms (BT) and groups (BG), which is the vocabulary your engineers will use.
| Field | What goes in | Where it comes from |
|---|---|---|
| Buyer reference (BT-10) | for public buyers, the Leitweg-ID | the buyer, stored on the customer account |
| Purchase order reference (BT-13) | order or call-off number, if the customer requires one | purchase order, tender documents |
| Contract reference (BT-12) | your contract or order number | CRM or contract database |
| Seller contact (BG-6) | name, phone and email of a contact person | your company master data |
| Electronic addresses (BT-34, BT-49) | technical addresses of seller and buyer | master data; on Peppol, the participant ID |
| Invoicing period (BG-14) | start and end of the billed period | billing run |
| Line period (BG-26) | a line's own period, e.g. for prorated upgrades | subscription events |
| Payment instructions (BG-16) | payment means code, IBAN or mandate details | the customer's payment method |
The service period isn't an XRechnung invention. German VAT law requires the date of supply on every invoice (§ 14(4) no. 6 UStG, in German). For subscriptions that is the billed period, not the invoice date. On a PDF it often lives as free text in the line description. In an XRechnung it needs proper date fields.
A March run as an XRechnung: seats, add-on seats, API calls
An example with invented figures: a customer has 40 seats at €25 per month. On 16 March they add 10 more seats. They also make 80,000 API calls at €2.00 per 1,000 calls. The invoice date is 1 April, the invoicing period (BG-14) is 1 to 31 March.
| Line | Quantity (BT-129) | Unit (BT-130) | Price (BT-146) | Base quantity (BT-149) | Period (BG-26) | Net (BT-131) |
|---|---|---|---|---|---|---|
| Business seats | 40 | C62 | 25.00 | 1 | 01.03.–31.03. | 1,000.00 |
| Add-on seats, prorated (16/31) | 10 | C62 | 12.9032 | 1 | 16.03.–31.03. | 129.03 |
| API calls | 80,000 | C62 | 2.00 | 1,000 | 01.03.–31.03. | 160.00 |
Net total €1,289.03, VAT at 19% = €244.92, invoice total €1,533.95.
Three things are hidden in this example.
The line amount is quantity times price per base quantity. For an API price of "€2.00 per 1,000", the price field holds 2.00 and the base quantity 1,000. Writing €0.002 per call gives the right total, but the customer can't match the invoice against the contract.
The prorated line needs its own period. Without BG-26 the recipient sees 10 seats at €12.90 and assumes a pricing error. The unit price may have more than two decimals; line amounts and totals may not. Decide whether your system prorates the price or the quantity, and keep that identical across all output formats.
C62 is the UN/ECE code for the unit "one" and works for seats and calls alike. The line name says what is being counted.
Usage: aggregate, but keep the trail
Nobody wants 80,000 invoice lines. Aggregate usage into one line per price tier and period, but keep a record in billing of which events went into which line. If the customer asks, send a usage statement as an attachment. The XML stays small.
With tiered pricing, each tier becomes its own line with its own price. If your system collapses all tiers into one line with a blended price, the amount is right but the price matches nothing in the contract. If usage arrives late, bill it in the next period as a separate line carrying the original period. The invoice already issued stays as it is. How usage is prepared before it reaches the invoice is covered on the usage-based billing page.
Discounts, prepaid credit and corrections
EN 16931 has discounts on two levels. A discount on one line is a line allowance (BG-27) and reduces the line amount. A discount on the whole invoice is a document-level allowance (BG-20) and needs its own VAT category. A discount that only exists as a negative text line fits neither.
Prepaid credit isn't a discount. It reduces the amount due, not the price. In an XRechnung it appears as the paid amount (BT-113), which is deducted after VAT; the VAT breakdown is unchanged. If VAT was already accounted for on the prepayment, the final invoice needs additional details. Settle that case once with your tax adviser.
Corrections after sending are made with a credit note (invoice type code 381) or with a cancellation and reissue. In both cases the new document references the original invoice (BT-25). Your data model needs a relationship between documents, not an edit button.
The Leitweg-ID and PO number belong on the customer account
The Leitweg-ID is assigned by the office that receives the invoice, and its format is specified as part of XRechnung (German). One customer can have several, for example when two institutes of the same university order separately. That is why it hangs off the contract or order, not just the customer record. A sketch:
customer
e_invoice_profile
format: xrechnung | zugferd | pdf
syntax: ubl | cii
electronic_address: { scheme, id }
po_number_required: true | false
valid_from, valid_to
contract
buyer_reference: "<Leitweg-ID of the receiving office>"
po_number: "<purchase order number>"
The validity dates matter. If the customer changes its Leitweg-ID, you must still be able to see where an invoice that has already been issued was addressed. If the profile is versioned, you can later reproduce any invoice from exactly the data it was created with.
What to settle before the first XRechnung
- The Leitweg-ID, PO number and delivery channel are confirmed in writing by the customer and stored on the contract.
- Your seller contact with name, phone and email is on file.
- Every line has a period, and prorated lines have their own.
- Usage prices with a base quantity are modelled as price plus base quantity, not as a tiny unit price.
- Discounts are line or document allowances, and prepaid credit is a paid amount.
- Corrections reference the original invoice, which stays unchanged.
Once all six are in place, the XML export is the smallest part of the job. Kontier generates XRechnung from the same versioned pricing, usage and tax data as the PDF and the ledger entry.
Not tax or legal advice. This post describes the law and common practice in general terms. For your own case, ask your tax adviser. As of: