R&D LAB Method In use Built for our own bookkeeping

Belegt

ZUGFeRD e-invoicing, self-hosted

Since 2025 a German invoice is a file a machine has to read. Belegt produces it in-house: the XML first, then the PDF, on our own hardware.

  • PDF/A-3boutput with an embedded factur-x.xml
  • 20rule codes checked offline, in-house
  • 4steps in the wizard before a file exists
  • 0invoice records that leave the house
Belegt invoice list with twelve documents, columns for number, client, project, date, amount and status, plus CSV and DATEV export

Every figure in this article shows invented demo data. The working database was not opened for the capture.

Why this is published

We sell software and automation. Belegt is the evidence for that on an uncomfortable example: a regulated task, a fixed format, real deadlines, our own data. The tool runs in our own operation, not in a demo. Anyone who wants to know how we cut a line-of-business application, where we put rules hard into the code and where we leave the decision to a person, can see it here on our own bookkeeping.

Since 1 January 2025, companies in Germany have had to be able to receive electronic invoices in B2B trade; the duty to send them follows in stages until 2028. A PDF attached to an email no longer satisfies that. What is required is a structured data set to EN 16931, in practice ZUGFeRD or Factur-X. Belegt is our own answer to it, built because we needed it ourselves.

The decision

The XML is the document, the PDF is the view

Anyone building an e-invoice for the first time starts at the PDF. That is the mistake that gets expensive later. A ZUGFeRD document is a PDF/A-3 with a file called factur-x.xml attached to it, and when the two disagree, an accounting system goes by the attachment. So we reversed the order: Belegt builds the data set first, generates the XML from it, and renders the PDF as a view of that.

This one decision drags the rest along behind it. Because the XML is the document, checking has to happen before anything is generated, not after. Because it is the document, it is the thing that gets stored and hashed when the invoice is finalised, with the PDF lying beside it. And because it is the document, styling stops where it would touch machine readability.

The second reason for building it ourselves was less elegant. Invoice data is the densest collection of other people's master data a small company keeps: addresses, tax numbers, bank details, project names. A subscription billed per document takes that collection with it. Belegt puts it in a file on our own hardware; the sensitive fields sit there encrypted with AES-256-GCM, the key outside the source code.

What deliberately did not come out of this is legal advice. The application checks against the business rules of the standard, as far as they can be checked without a network. Legal certification of a document is done by the official KoSIT validator, and nothing here replaces it.

If the PDF and the XML disagree, the XML wins. So that is where you start.

How a document is made

Four steps, and only then a file

  1. 01 Draft Issuer, client, number and period, then the line items. Master data and the service catalogue are already stored. The suggested number is only a preview at this point: it reads the counter without moving it.
  2. 02 Check Before anything is generated, a rule set runs over the data: twenty named rules from EN 16931, from the reverse-charge annex and from the German XRechnung extension. Blocking findings appear as errors with their rule code, advisory ones separately.
  3. 03 Build the XML The checked data set becomes a CrossIndustryInvoice carrying the identifier urn:cen.eu:en16931:2017. In XRechnung mode the KoSIT identifier is added, and the Leitweg-ID moves from an advisory note to a requirement.
  4. 04 PDF/A-3b with attachment The PDF is typeset with embedded fonts, marked as PDF/A-3b, and receives factur-x.xml as an attachment with the relationship Alternative. On finalising, the data set, the XML, the PDF and a SHA-256 of the XML are stored.

The check comes before the file

Review step of the wizard: invoice summary, below it the EN 16931 check listing four blocking rule violations BR-02, BR-07, BR-10 and BR-21, plus an XML self-check
An empty draft, on purpose: the review step names the four rules still missing, each with its code from the standard.

The check runs entirely on the local machine. It knows twenty rule codes, recomputes the totals against the line items, and keeps a strict line between blocking and advisory: a missing IBAN does not stop a B2B document, an incomplete buyer address does.

What it is not is stated in the same view: a pre-flight without Java, not a replacement for the official KoSIT or Mustang validator. Legal certification of a document remains the job of that external run.

Structure

One data set, two readers

A single data set produces both the page a person reads and the record a machine reads. Both are stored together on finalising; the XML is additionally hashed.

What happens after it goes out

The second half of the work on an invoice begins once it has gone out. Belegt keeps receivables in a view of their own: days to the due date, dunning level, and the amount that late-payment interest would add if a reminder went out.

The dunning level does not climb by itself. It is a field on the document that someone sets, and the reminder is a button that someone presses. A tool that chases clients unattended is a risk rather than a relief in an operation with a handful of clients.

Dated drafts sit in the same view, fully prepared. They too do not leave on their date by themselves; they wait to be opened and sent.

Receivables view with four documents, days to due date, reminder amount and one dated draft
Receivables and one scheduled draft, all on invented demo data.

What changed in 2025

PDF by email, until 2024

  • A picture of an invoice. The figures on it are text inside a layout.
  • Bookkeeping retypes them, or lets a recogniser guess.
  • A transposed digit surfaces at reconciliation, at the earliest.
  • Every recipient builds their own rule for your particular layout.

E-invoice to EN 16931, from 2025

  • A structured data set. Every field carries a code from the standard.
  • Bookkeeping imports it; the PDF beside it is for people.
  • Business-rule violations surface before the document is sent.
  • One format for every recipient, with an extension for the public sector.

What is hard-coded

01 The XML is the legal record On finalising, the full data set, the XML and the PDF are stored and the XML is hashed with SHA-256. After that the document is not edited: what follows is a credit note under code 381 or a corrective invoice under code 384.
02 Numbers follow a fixed pattern Prefix, financial year, month, running number. The counter resets monthly and is drawn on save inside a transaction that first reconciles it against the highest number already present. The database allows each number only once per tenant.
03 Tax cases, not free text Reverse charge and the small-business scheme are states on the document that set rate, VAT display and the accompanying sentence together. Under reverse charge, two rules of the standard demand both VAT IDs before anything is generated at all.
04 Styling stops at the brand The interface can be recoloured and run in a light or a dark theme; the invoice PDF cannot. A document that looks different depending on the mood of the day is a problem in an archive.
05 Every write leaves a trace Creating, sending, dunning, exporting and signing in are written to a log whose entries are chained through the hash of the one before. The invoice data itself sits in a file on our own hardware, with the sensitive fields encrypted using AES-256-GCM.

The application, on invented data

Analytics view with figures for billed, outstanding and overdue amounts, plus bars for clients and projects
Analysis over the same records: twelve documents, one revenue picture, no second spreadsheet going stale.
Profile management with one issuer and five clients, each with a city and a VAT ID
Master data in one place. The VAT IDs here are all zeros, because the entire set is invented.
Automation view with empty sections for recurring documents and payment plans, plus a service catalogue of five entries
The service catalogue the line items come from. Recurring documents and payment plans are deliberately empty here.

What it was built for

  • Small service firms that must be able to receive from 2025 and to send by 2028, without paying per document.
  • Operations with few but recurring clients: retainers and project call-offs run through the same catalogue.
  • Cross-border services inside the EU, where the tax case hangs on the client record and not on someone's memory.
  • Anyone who does not want their client and bank data sitting in somebody else's tenant database.
  • As a template: the same construction for another regulated form-filling job inside your own operation.

“What advantages does double-entry bookkeeping bring the merchant! It is among the finest inventions of the human mind.”

Johann Wolfgang von Goethe · Wilhelm Meister's Apprenticeship, 1795

Why this is published

What this means for your project

More from the lab

Do you have a regulated form-filling job that someone is holding together by hand? That is exactly what a pilot is for.

Get in touch

Grace Hopper

“The most damaging phrase in the language is: it's always been done that way.”