Free for Craft Commerce 5
Orders into Lexware Office, as real German invoices
Lexware Office (formerly lexoffice) is where a German shop's books live. Getting Commerce orders into it usually means a Zapier hop that knows nothing about §13b, or somebody keying invoices in by hand. Lexies does it properly — and refuses when doing it properly is not possible.
Rehearse it on a real order
Before you trust the mapping, print it. A dry run resolves the tax treatment, states its reasoning, computes both totals and shows you the exact JSON — and sends nothing.
$ php craft lexies/sync/order 1042 --dry-run
Order 1042
· The store charges tax-inclusive prices, so unit prices are sent gross.
· AT is in the EU and the customer supplied VAT ID ATU12345678,
so the supply is an intra-community one.
tax type: intraCommunitySupply
order total: 238 invoice total: 238
{ "voucherDate": "2026-08-23T00:00:00.000+02:00", … }
Features
An accounting integration is only worth having if you can trust what it filed. Most of Lexies is about earning that.
The tax type, worked out
Kleinunternehmer, domestic VAT, reverse charge for an EU business with a VAT ID, OSS distance sales for an EU consumer, zero-rated export outside the EU — decided per order, with the reasoning recorded on the document.
- The EU country list is read from Lexware, never hardcoded
- intraCommunitySupply is a claim to the Finanzamt — you can see what produced it
Proved, not hoped
Every payload is recomputed the way Lexware will compute it — unit price times quantity rounded per line, tax re-derived per rate — and compared to what the order charged, in integer cents.
- Its own rounding is absorbed into a line, then re-checked
- Anything larger is blocked, with both figures on the document
Never the same voucher twice
A duplicate numbered invoice in German bookkeeping is a correction filing, not an inconvenience. Lexware has no idempotency key and says a timeout may still have created your voucher — so a create whose outcome is unknown stops rather than retrying.
- One order, one voucher, held by a unique index
- Reconcile searches Lexware's voucher list before anything tries again
Customers as real contacts
One customer means one Lexware contact and one customer number, reused across every order. An existing contact is adopted by exact email rather than duplicated, and an edit made in Lexware wins over a stale copy instead of being overwritten.
Paid in Lexware, known in Craft
Lexware is where the bank feed lands, so Lexware is the authority on whether an invoice was settled. Signed webhooks carry that back — verified against their published key, deduplicated, and handled in a queue.
- Writing a Commerce transaction is opt-in, so you never bank a sale twice
- No public endpoint? Poll instead, with no inbound connectivity at all
Refunds become credit notes
A full refund mirrors the invoice line for line. A partial one cannot be attributed to particular products without inventing facts, so it goes out split across the order's own tax rates — the only split that keeps the VAT return right.
Frequently Asked Questions
The questions worth answering before you install it.
Yes. Lexware Office is what lexoffice was renamed to, and it is the same public API at api.lexware.io.
Lite is, and it is not a trial: a German shop selling to German customers can invoice every order with the free edition, tax resolution and reconciliation guard included. Pro is $99 with a $49/year renewal, and adds contacts, credit notes, payment sync, OSS distance sales, customer downloads and the full connection log.
Not one that Lexies sends. Every payload is recomputed the way Lexware will compute it and compared to the order total in integer cents; anything that does not reconcile is blocked rather than sent. That is the part worth paying for.
No. One order maps to one voucher, held by a unique database index, so a replayed queue job or an impatient merchant collides there rather than in Lexware's voucher numbering. The harder case is a request that times out — Lexware's own docs say that may still have created the voucher — and Lexies never retries those. It parks the document and looks Lexware up first.
Yes. An EU business that supplies a VAT ID gets intraCommunitySupply, zero-rated, with the reverse-charge note. An EU consumer gets distanceSales with the destination country's rate when you are registered for One-Stop-Shop. Both need a Lexware contact, which is a Pro feature.
It asks Lexware. Their countries endpoint returns each country's tax classification, and it is the same table their voucher validation uses — so the answer stays right when a country joins or leaves, and it can never disagree with the system it is talking to.
Only if you ask. The default is a draft, because finalising allocates the consecutive voucher number and cannot be undone — a finalised invoice can only be voided.
No. Lexware Office issues vouchers in EUR only. Orders in another currency are refused with an explanation rather than converted at a rate nobody could defend on a tax return.
No. The order-complete handler pushes a queue job and returns. An accounting API being slow, rate limited or down can make an invoice late; it can never stop a customer paying.
Nothing, until you ask. php craft lexies/sync/backfill invoices them oldest first, and --dry-run shows the whole plan without sending anything.
Craft CMS 5.3+, Craft Commerce 5.0+, PHP 8.2+ with ext-openssl.
Start free, upgrade when the EU shows up
Lite invoices a German shop selling to German customers, for nothing. Pro is $99 with a $49/year renewal, and adds contacts — which is what Lexware requires before it will accept an intra-community or third-country invoice at all.