What this template emits
A single invoice goes through two legs at once.
Leg 1, UBL 2.1 XML. The structured leg. It carries the CustomizationID urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0 and the ProfileID urn:fdc:peppol.eu:2017:poacc:billing:01:1.0. That combination is what the Belgian tax authority and every other Peppol BIS Billing 3.0 endpoint validates against. The fields rolled into the XML cover the EN 16931 mandatory set: supplier and customer Peppol Participant IDs, VAT registration IDs, the postal addresses, the line-item invoiced quantities and unit prices, the VAT subtotals broken out by tax category, the legal monetary totals, and the payment means (IBAN + BIC for SEPA credit transfer).
Leg 2, print-ready PDF. The same data renders as a normal PDF invoice your customer can read. The visual layout is built in HTML and CSS so you can rebrand it in the designer. The rendering pipeline is Chromium, which means Arabic, Hindi, Hebrew, Thai, and CJK render the same way they do in your browser. No font packages to install, no DOMPDF fallback.
Why the Belgian mandate matters first
Belgium published the Royal Decree mandating Peppol BIS Billing 3.0 for all B2B transactions between Belgian VAT-registered entities, effective 2026-01-01. There is a three-month tolerance window during which non-conformant invoices are accepted while the receiver complains, but from 2026-04-01 onward a non-conformant invoice can be legally rejected.
Belgium chose Peppol BIS Billing 3.0 because the network is already live across the Nordics, the Netherlands, Italy, and parts of Germany. The same schema works against the German ZUGFeRD 2.1 / Factur-X profile (same EN 16931 base) and the Italian SDI (with a different syntax binding). Building the Peppol BIS Billing 3.0 emitter once gets you ready for the wider EU ViDA rollout.
What the validator checks
The official Peppol Schematron checks rules grouped under CEN/EN 16931 (BR-* business rules, BR-CL-* code-list rules) and Peppol-specific extensions (PEPPOL-EN16931-*). Common rejections this template avoids:
- Missing or invalid
CustomizationID(the most common rejection when teams hand-roll the XML). - VAT category code that does not match the percentage (
Swith 0% fails; useZfor zero-rated,Efor exempt). - Line totals that do not sum to the document totals within 0.02 currency units of rounding tolerance.
- Endpoint IDs without a scheme prefix (
0208:0123456789for the Belgian Crossroads Bank for Enterprises; the leading0208:is required).
The emitter computes the rolled-up totals from the line items, so the rounding-tolerance class of failures is impossible by construction. The other rules are enforced at the Go API surface so an invalid invoice never reaches the XML encoder.
How to use it
- Sign up for a free LightningPDF account (100 PDFs/month, no card).
- Click Customize in LightningPDF to fork the template into the designer.
- Replace the supplier block with your company details (Peppol Participant ID, VAT registration, legal entity name, postal address).
- POST your invoice JSON to
/api/v1/pdf/download?format=peppol-bis-3. The response is the PDF; the matching UBL XML is available at/api/v1/einvoice/peppol/<id>.xml. - Send the PDF to the customer over your usual channel; send the XML to the Peppol Access Point.
Frequently asked questions
Is this PDF/A-3 conformant?
The PDF leg is rendered through the same Chromium engine that ships the rest of LightningPDF's PDFs. On the Pro tier, the engine is configured for PDF/A-3 conformance: embedded ICC profile, font subsetting, XMP metadata identifying the conformance level, and the UBL XML attached with AFRelationship="Alternative". On the Free and Starter tiers the PDF prints as a normal PDF and the XML is delivered as a separate file. Both are still validator-passing on the structured leg, but the Free/Starter PDFs are not certified as PDF/A-3.
Validation status
On 2026-06-03 our sample invoice (pkg/einvoice/SamplePeppolInvoice) was run through the official OpenPEPPOL Schematron compiled with Saxon-HE 12.7. Both rule packs returned clean:
- CEN EN 16931 ruleset: 0 errors, 0 warnings
- Peppol BIS Billing 3.0 ruleset: 0 errors, 0 warnings
The raw SVRL outputs live under test-results/validators/peppol/reports/ in the repository. Reproduce with bash scripts/run_peppol_validator.sh <invoice>.
Do you publish the validator reports?
Yes. The Peppol Schematron output against this template's sample invoice is published at lightningpdf.dev/proof, refreshed on each release.
Can I extend this template to ZUGFeRD or Factur-X?
The German ZUGFeRD 2.1 BASIC profile and the French Factur-X 1.0 BASIC profile are both CEN/EN 16931 compliant subsets of UBL or CII syntax. The same line-item model the Peppol emitter consumes drives a separate CII-syntax emitter; both target the same EN 16931 semantics. The other Phase 1 templates (ZATCA, India GST, Japan qualified invoice) reuse the line-item model with format-specific emitters.
What if my buyer is not Peppol-registered yet?
You can still send the PDF leg over email; that is a normal invoice. Belgian mandate compliance specifically requires the structured XML leg over Peppol, so a non-registered buyer is the buyer's compliance problem, not yours. Many Belgian Access Point providers offer a free receiving-only registration that takes under an hour.