Lexies for Craft CMS

Configuration

All settings live at Settings → Plugins → Lexies. None of them is required, so a fresh install can save the screen before the API key exists.

When to invoice

SettingWhat it does
TriggerWhen the order is completed (default), When the order reaches a status (Pro), or Only when I ask
StatusesWith the status trigger, the handles that raise an invoice — the first time the order reaches any of them
Only invoice paid ordersOff by default. Leave it off if the invoice is the request for payment
Finalise invoicesOff by default. On, invoices arrive open with a voucher number and cannot be edited or deleted, only voided
StoresWhich Commerce stores Lexies invoices for. None selected means all of them

Invoicing never happens inside the checkout request. The order-complete handler pushes a queue job and returns; a Lexware outage can make an invoice late, but it can never stop a customer paying.

Tax

Tax type is Work it out per order by default. That resolves each order from three real inputs:

SituationTax type
Your organisation is a Kleinunternehmer (§19 UStG)vatfree
Customer in Germanynet or gross, matching how your store enters prices
Customer in the EU with a VAT IDintraCommunitySupply — reverse charge
Customer in the EU without a VAT ID, OSS onnet/gross with taxSubType: distanceSales
Customer outside the EUthirdPartyCountryDelivery, or …Service for digital goods

Whether a country counts as EU comes from Lexware's own countries endpoint, not a list baked into the plugin. It is the same table their voucher validation uses, so it stays correct when a country joins or leaves.

Every decision is recorded with its reasoning on the document. Open any document under Lexies → Documents to see why it was taxed the way it was — intraCommunitySupply on an invoice is a claim to the Finanzamt, and you should be able to see what produced it.

You can pin a single tax type instead, if you would rather decide yourself.

The other tax settings

  • VAT-free note — printed on zero-rated invoices. Empty uses Lexware's own wording.
  • EU distance sales (OSS) — only turn this on if you are registered for One-Stop-Shop and your Lexware distance sales principle is set to DESTINATION. The connection test reports that.
  • I sell electronic services — changes both the distance-sales subtype and the tax type used outside the EU.
  • Order-level discountsSpread across line items (default) keeps every tax rate exact. Send as a total discount is tidier on the printed invoice but lets Lexware decide how the discount lands on each rate: fine at one rate, and a blocked invoice at two.
  • Reconciliation tolerance — how far the invoice may sit from the order before Lexies refuses to send it, in cents. Zero is correct. See Usage.

Contacts (Pro)

Sync contacts creates a real Lexware contact per customer and reuses it, rather than printing the address onto each invoice. One customer means one contact and one customer number, held by a unique key: the Craft user id where there is one, the lowercased email where there is not.

Before creating anything, Lexies looks for a contact Lexware already holds under that email and adopts it — a shop that has been invoicing by hand for a year does not want a parallel set of customers. The match is exact, because Lexware's email filter matches substrings.

Registered customers only books guests against Lexware's collective customer instead.

Leaving contacts off means intra-community and third-country orders are blocked, because Lexware will not accept those tax types without a referenced contact.

Payments and refunds (Pro)

SettingWhat it does
Listen for Lexware webhooksLexware calls this site when a payment or voucher status changes
Verify webhook signaturesOn. Checks the RSA-SHA512 signature against Lexware's published key
Record payments in CommerceOff. On, a paid invoice adds a Commerce transaction
Payment gatewayWhich gateway that transaction is attributed to. Without one, nothing is recorded
Status when paidMove the order to this status once Lexware reports it paid
Credit note on refundRaise a Lexware credit note when a refund is captured in Commerce

Record payments in Commerce is off by default on purpose. It creates money in Commerce's ledger, and a shop that already takes card at checkout would end up with the same sale paid twice. Turn it on when the invoice is how you get paid — bank transfer, on account — not as a matter of course.

Subscribing

Press Subscribe on the settings screen. Lexware sends a HEAD request to your callback URL first to check the certificate, so the URL has to be publicly reachable over valid HTTPS before it will accept the subscription.

Revoking a Lexware API key deletes every subscription made with it. After rotating a key, run php craft lexies/webhooks/sync again — that is the whole recovery procedure.

If you would rather not expose a public endpoint, leave webhooks off and poll instead:

php craft lexies/payments/poll

The document

SettingNotes
Languagede (default) or en. Drives Lexware's own default text on the printed document
TitleObject template. Lexware caps this at 25 characters
Introduction / RemarkObject templates, rendered against the order. 2000 characters each
Shipping conditionsNot cosmetic: Lexware uses the shipping date to decide which VAT rates are legal on the voucher
Payment term (days)Empty uses the term configured in Lexware
Shipping as a line itemOn. Shipping is always its own line in Lexware's model
Default unit nameUsed when a variant has no unit of its own. Stück by default
Include SKUAdds Art.-Nr. … to the line description
Print layout IDEmpty uses your Lexware default layout

The three text fields are object templates, so they can quote the order:

Bestellung {{ object.reference ?? object.shortNumber }}

Front end (Pro)

Customer invoice downloads serves the Lexware PDF at /lexies/invoice/{order number}. It authorises exactly the way Commerce's own order-details page does: a logged-in customer must own the order, and a guest order is proved by its unguessable 32-character order number. Link to it with craft.lexies.invoiceUrl(order), which returns null when there is nothing to download.

Connection and logging

SettingDefaultNotes
Minimum request interval550 msLexware allows two requests a second across your whole key
Retries3Reads, and writes Lexware definitively rejected. A create that timed out is never retried
Timeout35 sLexware's own gateway times out at 30
LoggingOn
Keep request and response bodiesOn (Pro)They contain customer addresses and order contents
Keep logs for30 daysPruned by lexies/log/prune. Zero keeps everything

The request interval is enforced across the whole install behind a mutex, so several queue workers share one budget rather than each politely staying under the limit and collectively tripling it.

Permissions

  • View Lexware documents — the Documents screen and the panel on the order edit screen
  • Create, finalise and re-check documents — nested under it; the buttons that act
  • View the Lexware connection log