Tutorial: turn supplier PDFs into idempotent Lexware records
A production n8n pattern for parsing German supplier invoices, preserving printed tax buckets, detecting credit notes, avoiding duplicate vouchers, and attaching source evidence.
Open public reference →
This tutorial describes a sanitised n8n workflow for Ko Kitchen accounting operations. The goal was not generic PDF extraction. It was a repeatable purchase-record pipeline that preserves the supplier document, creates the correct Lexware document once, and remains safe when a run stops halfway through.
Define the accounting contract before parsing
The manual process was: find an approved supplier PDF, read the voucher number and dates, enter its VAT split, choose invoice or credit note, create the accounting record, then attach the PDF. The parser therefore had a narrow contract. It either produced a document with a stable external number, voucher date, document type, printed VAT buckets, and source file; or it stopped with a named error. It never filled missing accounting values with defaults.
Process one document at a time
n8n lists approved Google Drive PDFs, then processes one file per iteration. The workflow downloads the binary, extracts text, builds a small parsed-document object, checks Lexware, and only then creates or repairs the accounting record. Serial execution makes a bad PDF, an API error, and a retry bounded to one invoice.
Screenshot: reduced workflow topology
Add a sanitised n8n screenshot here. Keep only these labels: List PDFs → Download PDF → Extract Text → Parse Invoice → Check Existing → Create Voucher or Attach Missing PDF. Remove file IDs, folder IDs, credentials, request URLs, and real values.
Parse invoices as documents, not as strings
First, extract the supplier voucher number. This becomes the duplicate-prevention key. If it is absent, stop: a retry cannot be safe without a stable external reference. Next, prefer the delivery date when the document has one, and use the header timestamp only as an explicit fallback. Voucher dates have accounting meaning; date choice cannot be an accidental regex match.
German amount parsing must accept a period as a thousands separator, a comma as the decimal separator, and a trailing minus sign for a negative value. Round only after the final voucher item values are calculated. This prevents a locale mismatch from turning a valid-looking amount into the wrong accounting value.
Use the final footer
Multi-page supplier invoices repeat footer rows. Earlier rows can be running totals, so the workflow takes the last matching 7% and 19% VAT footer rows. It then creates one Lexware item for each non-zero printed bucket. Mirroring printed gross and tax values is safer than recalculating from line items that can contain their own rounding or deposit rules.
Credit notes use the same parser with a different document decision. A credit-note marker in the text or a negative final amount changes the target from purchase invoice to purchase credit note. Any visible reference to the original document is retained as a remark.
Screenshot: parser assertions
Add a redrawn parser test table here. Use synthetic invoice text and show: delivery-date preference, German amount conversion, last-footer selection, 7% and 19% buckets, and negative-total credit-note detection. Do not show a real invoice.
Put idempotency before the external write
Before any create request, query Lexware by the supplier voucher number. No match means create the voucher and attach the source PDF. A match means do not create another voucher; inspect whether the existing record still needs the source attachment. This permits a safe re-run after the specific failure window between create and upload.
The useful test is not only a clean first run. Test an absent number, a two-page invoice with repeated totals, a credit note, an existing voucher with no attachment, and a re-run after a successful create. The expected result is a named stop or a recoverable no-op, never a duplicate accounting document.
Keep evidence attached to the record
A correct voucher without its source PDF still creates audit and review work. Treat the PDF as part of the record: attach it after a create and repair the attachment when a pre-existing voucher lacks it. The public hamberger-dl CLI covers the adjacent document-download problem; this private workflow begins with already-approved PDFs.
Publication boundary
Do not publish supplier account IDs, Google Drive identifiers, credential names, contact or category IDs, live invoice text, voucher values, raw workflow exports, or complete parser code. The pattern is public; production financial data is not.

