Overview
Icon for XRechnung & ZUGFeRD

XRechnung & ZUGFeRD

German XRechnung and ZUGFeRD e-invoices

Copy to clipboard@normwerk/einvoice-medusa

A thin Medusa v2 plugin for German e-invoicing (XRechnung 3.0 / ZUGFeRD, EN 16931): subscribes to Copy to clipboardorder.fulfillment_created, Copy to clipboardorder.fulfillment_canceled, Copy to clipboardpayment.refunded and Copy to clipboardorder.canceled — an invoice per fulfillment, a credit note per refund or cancellation — maps the order to Copy to clipboard@normwerk/einvoice-commerce's invoice model, and stores the result — idempotently, with no duplicate documents on event redelivery. No tax logic and no XML live in this package; that's Copy to clipboard@normwerk/einvoice-commerce/Copy to clipboard@normwerk/einvoice-cii's job, kept platform-agnostic.

The seller is in Germany. What each buyer receives — the full list, with the territories refused, is in Copy to clipboarddocs/supported-countries.md:

Seller — tax rules Buyer Document Delivery Since 🇩🇪 Germany 🇩🇪 Business or consumer in Germany ZUGFeRD / Factur-X, Copy to clipboardEN 16931 profile — or XRechnung 3.0, if you prefer it File: XML, or PDF/A-3b 0.1.0 🇩🇪 Germany 🇩🇪 Public-sector buyer in Germany, with a Leitweg-ID XRechnung 3.0 File: XML, or PDF/A-3b 0.1.0 🇩🇪 Germany 🇪🇺 Any other EU member state, except Italy and Poland; Iceland, Liechtenstein and Norway (EEA) ZUGFeRD / Factur-X, Copy to clipboardEN 16931 profile File: XML, or PDF/A-3b 0.1.0 🇩🇪 Germany 🇨🇭 🇬🇧 Switzerland and the UK ZUGFeRD / Factur-X, Copy to clipboardEN 16931 profile File: XML, or PDF/A-3b 0.1.0

Not supported: 🇮🇹 Italy (SDI), 🇵🇱 Poland (KSeF) — clearance platforms with an XML of their own, which no EN 16931 document can serve; out of scope. A buyer anywhere else, and a seller outside Germany, are refused too.

A PDF/A-3 hybrid from any PDF renderer you supply (including a bundled one, Copy to clipboard@normwerk/einvoice-pdfa's Copy to clipboardrenderInvoicePdf), or XML only. The plugin numbers and issues the invoices itself: next to another plugin that issues invoices, the buyer gets two invoices for one supply — turn invoicing off in the other plugin. Documents are stored in Medusa's own File Module (private), with an admin "E-Invoices" widget on the order page and a Store API endpoint for a customer to fetch their own e-invoice. Each issued or refused document is announced on Medusa's event bus (Copy to clipboardeinvoice.document_issued, Copy to clipboardeinvoice.issuance_blocked; payload types from Copy to clipboard@normwerk/einvoice-medusa/events), and an order's documents are readable with the order (Copy to clipboardeinvoice_documents) — so a shop's own code can mail the invoice to the buyer or hand it to accounting.

Compatibility

Supported: Medusa 2.12–2.15 and 2.18 or later 2.x — the releases the end-to-end suite passes on (a real store, from checkout to a validated invoice, credit note and refund), each minor line run at its latest patch. The peer dependencies declare exactly that range, and on any other release the plugin refuses to start (Copy to clipboardUnsupportedMedusaVersionError) rather than run where it has not been shown to issue correct invoices. Need another release? A pull request is welcome, or write to hello@normwerk.dev about adapting it.

Medusa End-to-end suite Supported Note 2.21.2 41/41 yes Also the version the plugin is developed and unit-tested against 2.21.1 41/41 yes 2.21.0 41/41 yes The suite's default 2.20.1 41/41 yes 2.19.0 41/41 yes 2.18.0 41/41 yes 2.16.0, 2.17.2 — no The plugin refuses to start. Before it did, the suite passed 10 of its then 22 checks there: Medusa charged no VAT on the products in the test store, only on shipping, so every domestic order was refused. Cross-border orders passed 2.15.5 41/41 yes 2.14.2 41/41 yes npm installs Medusa 2.14.2 itself only with Copy to clipboard--legacy-peer-deps, plugin or not: Copy to clipboard@medusajs/icons@2.14.2 requires React 19, Medusa's own dashboard 2.14.2 React 18 2.13.6 41/41 yes 2.12.6 41/41 yes below 2.12 — no Not run: the test store does not start on these releases yet

Invoices and credit notes are issued for a seller in Germany only; the plugin refuses to start with any other seller country. Buyers can be in Germany (businesses, consumers, public-sector buyers), elsewhere in the EU/EEA except Italy and Poland (their clearance platforms take no EN 16931 document), Switzerland or the UK.

Versioning

Semantic versioning covers the plugin's documented interface only: its options, the events Copy to clipboardeinvoice.document_issued and Copy to clipboardeinvoice.issuance_blocked with their types in Copy to clipboard@normwerk/einvoice-medusa/events, the documents read with an order (Copy to clipboardeinvoice_documents), the Admin and Store API routes, the "E-Invoices" admin widget, the plugin's database tables, the field mapping in the mapping reference, and the dry run's script and arguments (dry run); its report carries a format version of its own. Every other file in the package can be imported — Medusa loads subscribers and routes by their path — but is internal: paths such as Copy to clipboardinvoices/* or Copy to clipboardmapping/* change in any release.

Install

npm install @normwerk/einvoice-medusa @normwerk/einvoice-model @normwerk/einvoice-commerce @normwerk/einvoice-cii

Full setup — configuration, migrations, optional PDF modes — is the quickstart: about 30 minutes from a fresh Copy to clipboardcreate-medusa-app project to a KoSIT-validated invoice on your first fulfilled order.

Dry run: try it on your orders first

Before you turn the plugin on, run it over a period of your past orders on a staging copy — it issues nothing, and reports for every fulfillment whether it would issue the invoice, issue it with a notice, or refuse it and why:

npx medusa exec ./node_modules/@normwerk/einvoice-medusa/.medusa/server/src/scripts/einvoice-dry-run.js from=2026-09-01 to=2026-09-30

The report names no customer. Copy to clipboardnpx @normwerk/einvoice-conformance dry-run einvoice-dry-run validates the invoices' XML with the official validators and writes it as Markdown. How to run it and how to read it: dry run.

Documentation

Part of normwerk/einvoice. See that repository for:

License

MIT — see Copy to clipboardLICENSE.

You may also like

Browse all integrations

Build your own

Develop your own custom integration

Build your own integration with our API to speed up your processes. Make your integration available via npm for it to be shared in our Library with the broader Medusa community.

gift card interface

Ready to build your custom commerce setup?