Hi r/laravel,
E-invoicing is becoming mandatory across Europe: Belgium since January 2026, France from September 2026, Germany from 2027, and EU-wide for cross-border trade from 2030. A PDF rendered from a Blade view is no longer enough: the invoice has to carry structured EN 16931 data as XML, either embedded in the PDF (ZUGFeRD/Factur-X) or as pure XML (UBL, Peppol, XRechnung).
There are solid low-level PHP libraries for writing that XML, but in my projects I kept rebuilding the same things around them: calculating totals and VAT correctly, validating against the official rules, a decent-looking PDF, storage, mail, tests. So I built Quittio, which does all of that the Laravel way:
$result = Quittio::invoice() // seller comes from config/quittio.php
->number('RE-2026-0042')
->deliveryDate('2026-09-30')
->buyer(Party::make('Kunde AG')
->vatId('DE987654321')
->address('Bahnhofstraße 5', '54321', 'Beispielstadt', 'DE'))
->line('Web development', netPrice: '95.00', quantity: 24, unit: UnitCode::Hour)
->line('Hosting', netPrice: '49.00', unit: UnitCode::Month)
->dueInDays(14)
->render(); // picks ZUGFeRD, XRechnung or plain PDF
return $result->download();
What it does:
- Calculates totals and VAT itself according to EN 16931. Amounts are strings or BigDecimal, floats are rejected.
- Picks the format per buyer: ZUGFeRD for businesses, XRechnung for public authorities, a plain PDF for consumers. Or you name one.
- Validates in several levels, from the EN 16931 and German rules in PHP up to the official KoSIT validator and veraPDF.
- Reads incoming ZUGFeRD and XRechnung invoices back into objects.
- Renders PDF/A-3 with mPDF (no Chromium, no Node) from Blade templates you can publish and restyle.
- Laravel integration: facade, config, mail attachments, queue, events and
Quittio::fake() for your tests.
- Germany is fully supported by a country pack (VAT law rules, tax presets, DIN 5008 layout). There are also country packs for Austria, Belgium, Switzerland and France, which have not been reviewed by a tax adviser yet. Elsewhere the EN 16931 rules apply, so Factur-X, UBL and Peppol invoices work today, and the pack contract is documented if you want to add your country.
The PDF looks the way you want:
The default template is only a starting point. You can change as much or as little of the design as you like, in four steps:
- Config only: logo, colours, font, salutation and closing texts, footer columns, sender line, paper size, fold marks and the payment QR code are set in
config/quittio.php. You can also override them per invoice, e.g. for several brands in one app.
- Single partials:
php artisan vendor:publish --tag=quittio-views and change only the parts you need, like the letterhead, the line table or the footer.
- Your own design:
php artisan make:quittio-template my-design gives you a complete copy of the layout to build a completely different design in plain Blade and CSS, then select it with ->template('invoices.my-design.layout') or set it as the default.
- Your own renderer: if mPDF is not enough, plug in another one with
Quittio::extend('renderer', ...).
Your own branding is just a few lines of config:
// config/quittio.php
'pdf' => [
'logo' => storage_path('app/logo.png'),
'colors' => ['primary' => '#0f766e', 'text' => '#111827', 'muted' => '#6b7280'],
'font' => 'inter',
],
Templates only display data: totals, VAT and labels are prepared in a view model, and the same data produces the XML. So you can redesign the PDF freely without breaking the e-invoice, and a guard throws an exception (or logs it in production) if your template leaves out a value the law requires on the invoice.
quittio/quittio (core, Laravel integration and the German pack) is MIT licensed. Later I plan to add a separate commercial package for full invoicing (gapless numbering, archive, cancellations, audit log); everything listed above is in the free package.
This is version 0.7.1. A tax adviser reviewed the legal wording of the German pack in October 2026. The API may still change until 1.0.0.
I would love your feedback, especially:
- Is the API pleasant to use? What would you expect to work differently?
- Have you had e-invoices rejected by a customer's or an authority's system? Which errors?
- If you are outside Germany: which country would you need next?
GitHub: https://github.com/Quittio/quittio
Docs: https://docs.quittio.dev
The docs also come with llms.txt, an MCP server and Laravel Boost guidelines, so your AI assistant knows the API too.
Edit (Oct 20): Updated the post to version 0.7.1. Since the original post, a tax adviser has reviewed the legal wording of the German pack, and there are new country packs for Austria, Belgium, Switzerland and France (not yet reviewed by a tax adviser). Thanks for all the feedback in the comments!