faktorei

EN 16931 · Peppol BIS · XRechnung · PINT A-NZ · Factur-X

Rendering infrastructure for structured e-invoices.

Open-source XSL-FO stylesheets and a self-hosted container that turn structured invoice XML — Peppol BIS, XRechnung, PINT A-NZ, CII — into archive-grade, human-readable PDF.

docker run -p 8080:8080 ghcr.io/faktorei/render:2025.11

Every feature, no signup, your infrastructure — watermarked output, 500 documents/day. What a license removes →

See the benchmark Read the stylesheets

An EN 16931 invoice with a document-level discount and a freight charge, rendered by Faktorei to PDF.
open the PDF/A → brought-forward pagination PDF/A-3b, fonts embedded validated against official CEN + Peppol rules

One pipeline, every syntax

Normalize once, render once.

Every document normalizes to the EN 16931 semantic model before anything is drawn, so one renderer serves UBL and CII alike and national profiles are configuration deltas, not forks. The normalizers are held to a strict contract in CI: a UBL invoice and its CII twin must produce byte-identical semantic XML — and they render pixel-identically. What changes between Peppol, XRechnung, and a plain EN 16931 invoice is a parameter, never the rendering logic.

There are two national profiles today — XRechnung (Germany) and PINT A-NZ (Australia and New Zealand) — and they share every line of rendering logic. Two is the number that matters: one profile is a special case, two is a pattern. The A-NZ work is also where the fixture corpus stopped being European. Japanese yen (a currency with no minor unit), Australian dollars, and GST rather than VAT are fixtures now, checked on every commit.

Peppol BIS · EUR

Germany to the Netherlands, two VAT rates. source XML →

Totals block: Total net 3,838.80, Total VAT 651.03, Amount due EUR 4,489.83 — two decimal places.
PINT A-NZ · AUD

Australian domestic. The tax is GST, not VAT. source XML →

Totals block: Total net 3,124.00, Total GST 312.40, Amount due AUD 3,436.40 — the tax labelled GST.
Peppol BIS · JPY

Whole yen. No minor unit, so no decimals. source XML →

Totals block: Total net 20,000, Total VAT 2,000, Amount due JPY 22,000 — no decimal places.

Labels ship in English, German, French and Dutch. That is not a convenience: the Loi Toubon requires an invoice between French parties to be in French, and Belgium fixes the language by the seller's region — Dutch in Flanders, French in Wallonia, German in Ostbelgien — where the wrong one can cost the invoice its validity. The language is a parameter, like the profile.

One renderer, one theme, one code path. The profile is a parameter — and the number of decimal places comes from the document's currency, not its language. Each image is a blessed baseline — the same file the pixel gate compares against on every commit — cropped to the totals block, the only part that carries the difference. Each links to the source XML that produced it.

Pagination the way ledgers did it

Long invoices that still read like documents.

Table headers repeat on every page. A running subtotal is carried forward across page breaks — printed at the top of each continuation page, the way a counting-house ledger did it — so a reader never loses the thread on a hundred-line invoice. The totals block is never orphaned from its lines, and page numbers and document identifiers sit in a quiet footer strip. It is designed to look correct in a tax auditor's hands.

Getting that right meant working around a real bug in Apache FOP: the footer that lied.

Page two of a multi-page invoice, showing the repeated table header and the brought-forward subtotal row at the top.
Page 2 — the repeated header and the brought forward row. open the full PDF/A →

Open core, honestly drawn

What renders your invoice is open. What you pay for is not having to operate it.

Stylesheets — Apache-2.0

  • The normalizers, the renderer, the themes, the i18n labels
  • The full test corpus and blessed visual baselines
  • The validation machinery (official CEN + Peppol + KoSIT + PINT A-NZ, pinned)

github.com/faktorei/stylesheets →

Container — licensed

  • Deterministic PDF/A-3b with embedded fonts
  • Factur-X / ZUGFeRD hybrid packaging
  • Batch — resumable when driven by a manifest — an HTTP service, Prometheus metrics
  • Spec-cycle SLA — updates within 3 weeks of each release

Pricing →


An expired license degrades gracefully — Faktorei never turns off your production rendering.

Built on the spec treadmill

The specification moves twice a year. So do we.

EN 16931, Peppol BIS, and XRechnung ship changes on a May/November cadence, with hotfixes in between. The national profiles do not all keep that calendar — PINT A-NZ versions on its own schedule, which is why we pin it by content hash rather than by release tag. Faktorei tracks all five pinned official artefact sets automatically (specwatch) and commits to shipping the updated stylesheets and validation within three weeks of each release, on whichever cadence it arrives — so the image you run always validates against the current, hotfixed rules. This is the treadmill the annual license buys you off of.

Render your own invoice against it in the next five minutes.

docker run -p 8080:8080 ghcr.io/faktorei/render:2025.11

Or read the source →