@pixelfarben/n8n-nodes-lexware-office
v0.3.0
Published
n8n Community Node for Lexware Office API - Manage contacts, invoices, articles, vouchers and more.
Maintainers
Readme
n8n-nodes-lexware-office
n8n Community Node fuer die Lexware Office API - Verwalte Kontakte, Rechnungen, Artikel, Belege und mehr direkt aus n8n-Workflows heraus.
Package: @pixelfarben/n8n-nodes-lexware-office
Version: 0.2.2
Lizenz: MIT
Autor: Andreas Henkel
Inhaltsverzeichnis
- Projektstruktur
- Architektur
- Ressourcen und Operationen
- API-Routing
- Credentials und Lizenzierung
- Workflows
- Technische Patterns und Konventionen
- Bekannte Besonderheiten der Lexware API
- Entwicklung
- Weiterentwicklung - Offene Aufgaben
Projektstruktur
lexware n8n node/
├── .npmrc # npm Registry-Konfiguration
├── .prettierrc.js # Code-Formatierung (Tabs, Single Quotes)
├── package.json # n8n-Node-Package-Konfiguration
├── tsconfig.json # TypeScript-Konfiguration (ES2019, CommonJS)
├── LICENSE.md # MIT-Lizenz
├── README.md # Diese Datei
│
├── credentials/
│ └── LexwareOfficeApi.credentials.ts # Credential-Definition (License Key + API Key)
│
├── icons/
│ └── lexware.svg # Node-Icon fuer n8n UI
│
├── nodes/
│ └── LexwareOffice/
│ ├── LexwareOffice.node.ts # HAUPTDATEI: Node-Logik, Routing, Execute
│ └── resources/ # Eine Datei pro API-Ressource
│ ├── article/index.ts
│ ├── contact/index.ts
│ ├── country/index.ts
│ ├── creditNote/index.ts
│ ├── deliveryNote/index.ts
│ ├── eventSubscription/index.ts
│ ├── invoice/index.ts
│ ├── orderConfirmation/index.ts
│ ├── postingCategory/index.ts
│ ├── profile/index.ts
│ ├── quotation/index.ts
│ ├── voucher/index.ts
│ └── voucherlist/index.ts
│
├── workflows/ # 24 importierbare n8n-Workflow-JSON-Dateien
│ ├── 01-belegmanagement/ # 8 Workflows (inkl. KI-Varianten)
│ ├── 02-rechnungswesen/ # 4 Workflows
│ ├── 03-mahnwesen/ # 3 Workflows
│ ├── 04-kontakte/ # 3 Workflows
│ ├── 05-reporting/ # 4 Workflows
│ └── 06-automatisierung/ # 2 Workflows
│
└── dist/ # Build-Output (nicht im Git)Architektur
Node-Aufbau (Programmatic Style)
Die Node nutzt den programmatic style von n8n (nicht declarative). Die gesamte Logik befindet sich in LexwareOffice.node.ts:
LexwareOffice.node.ts
│
├── verifyLicense() # Lizenspruefung gegen license.webugo.de (1h Cache)
├── getApiRoute() # Mappt resource + operation → HTTP method + URL
├── buildQueryParams() # Baut Query-Parameter aus Node-Parametern
├── buildBody() # Baut Request-Body aus Node-Parametern
│
└── class LexwareOffice
├── description # Node-Metadata, Properties (alle Resource-Descriptions importiert)
└── execute() # Hauptlogik: License Check → Pro Item → Route → Request → ResponseResource-Dateien
Jede Resource-Datei (resources/*/index.ts) exportiert ein INodeProperties[]-Array mit:
- Operation-Auswahl (z.B. Create, Get, Get Many, Update, Delete)
- Parameter-Definitionen (IDs, Filter, Body-JSON, Paginierung)
displayOptionsmit{ show: { resource: ['resourceName'] } }zur bedingten Anzeige
Ablauf einer Execution
1. execute() wird aufgerufen
2. Lizenz wird geprueft (Cache: 1h TTL, Fallback bei Server-Ausfall)
3. Fuer jedes Input-Item:
a. resource + operation auslesen
b. getApiRoute() → { method, url, isFile? }
c. buildQueryParams() → Query-String
d. buildBody() → JSON-Body (nur bei create/update)
e. httpRequestWithAuthentication() → Lexware API
f. Response verarbeiten:
- Array → einzelne Items
- Objekt → ein Item
- File → Binary-Data (PDF)Ressourcen und Operationen
| Ressource | Operationen | API-Endpunkt | Besonderheiten |
|-----------|-------------|--------------|----------------|
| Contact | create, get, getAll, update | /v1/contacts | Filter: email, name, number, customer, vendor. Paginierung (page, size). getAll gibt content-Array zurueck |
| Invoice | create, get, downloadFile | /v1/invoices | ?finalize=true moeglich. precedingSalesVoucherId fuer Folgbelege |
| Credit Note | create, get, downloadFile | /v1/credit-notes | Wie Invoice |
| Quotation | create, get, downloadFile | /v1/quotations | Wie Invoice |
| Order Confirmation | create, get, downloadFile | /v1/order-confirmations | Wie Invoice |
| Delivery Note | create, get, downloadFile | /v1/delivery-notes | Wie Invoice |
| Article | create, get, getAll, update, delete | /v1/articles | Filter: articleNumber, gtin, type. Paginierung |
| Voucher | create, get, update | /v1/vouchers | Body als JSON-String (voucherBody). categoryId referenziert Posting Categories |
| Voucherlist | getAll | /v1/voucherlist | Umfangreiche Filter: voucherType, voucherStatus, contactId, Datumsbereich. Gibt content-Array zurueck |
| Event Subscription | create, get, getAll, delete | /v1/event-subscriptions | Body: eventType + callbackUrl |
| Posting Category | getAll | /v1/posting-categories | Gibt Array von Buchungskategorien zurueck (id, name, type, groupName, contactRequired, splitAllowed) |
| Profile | get | /v1/profile | Gibt Organisationsprofil zurueck (taxType, smallBusiness, features) |
| Country | getAll | /v1/countries | Statische Laenderliste |
API-Routing
Die Funktion getApiRoute() in LexwareOffice.node.ts (ab Zeile 70) mappt jede Kombination aus Resource und Operation auf die korrekte API-URL:
contact/create → POST /v1/contacts
contact/get → GET /v1/contacts/{contactId}
contact/getAll → GET /v1/contacts
contact/update → PUT /v1/contacts/{contactId}
invoice/create → POST /v1/invoices
invoice/get → GET /v1/invoices/{invoiceId}
invoice/downloadFile → GET /v1/invoices/{invoiceId}/file (isFile: true)
article/delete → DELETE /v1/articles/{articleId}
voucherlist/getAll → GET /v1/voucherlist
postingCategory/getAll → GET /v1/posting-categories
profile/get → GET /v1/profile
country/getAll → GET /v1/countriesNeue Resource hinzufuegen:
resources/newResource/index.tserstellen (exportiertnewResourceDescription)- In
LexwareOffice.node.ts:- Import hinzufuegen
- Resource-Option zum
options-Array hinzufuegen (alphabetisch!) ...newResourceDescriptionzupropertieshinzufuegencase 'newResource':ingetApiRoute()hinzufuegen- Optional:
buildQueryParams()undbuildBody()erweitern
Credentials und Lizenzierung
Credential-Felder (LexwareOfficeApi.credentials.ts)
| Feld | Typ | Beschreibung |
|------|-----|-------------|
| licenseKey | password | Webugo-Lizenzschluessel (Pflicht) |
| apiKey | password | Lexware Office API Bearer Token (Pflicht) |
Authentifizierung
- API-Auth: Bearer Token im
Authorization-Header - Lizenz-Check: GET gegen
https://license.webugo.de/api/n8n/verify/{licenseKey}- In-Memory-Cache mit 1h TTL
- Bei Server-Ausfall: Fallback auf abgelaufenen Cache
- Ohne gueltige Lizenz:
NodeApiErrorwird geworfen
- Credential-Test: GET
/v1/profile(prueft ob API-Key gueltig ist)
API-Basis-URL
Aktuell: https://api.lexoffice.io (hardcoded in requestDefaults und execute())
ACHTUNG: Lexware hat auf https://api.lexware.io umgestellt (Mai 2025). Die alte URL funktioniert noch bis Dezember 2025. Migration auf neue URL steht noch aus.
Workflows
Uebersicht (24 Workflows)
01 - Belegmanagement
| Datei | Name | KI | Beschreibung |
|-------|------|:--:|-------------|
| wf01a-*-openai.json | KI-Belegkategorisierung (OpenAI) | GPT-4o-mini | Belege automatisch kategorisieren mit echten Lexware-Buchungskategorien |
| wf01b-*-gemini.json | KI-Belegkategorisierung (Gemini) | Gemini 2.0 Flash | Identisch, nur anderer KI-Provider |
| wf01c-*-anthropic.json | KI-Belegkategorisierung (Anthropic) | Claude Sonnet | Identisch, nur anderer KI-Provider |
| wf02a-*-openai.json | Eingangsrechnungen aus E-Mail (OpenAI) | GPT-4o-mini | Rechnungsdaten aus E-Mails extrahieren, Kontakt suchen/erstellen |
| wf02b-*-gemini.json | Eingangsrechnungen aus E-Mail (Gemini) | Gemini 2.0 Flash | Identisch, nur anderer KI-Provider |
| wf02c-*-anthropic.json | Eingangsrechnungen aus E-Mail (Anthropic) | Claude Sonnet | Identisch, nur anderer KI-Provider |
| wf03-*.json | Belegarchivierung in Google Drive | - | Belege automatisch in Google Drive archivieren |
| wf04-*.json | Belegzuordnung zu Kontakten | - | Belege automatisch Kontakten zuordnen |
02 - Rechnungswesen
| Datei | Name | Beschreibung |
|-------|------|-------------|
| wf05-*.json | Angebot -> Rechnung Pipeline | Webhook-getrieben: Angebot → Auftragsbestaetigung → Rechnung |
| wf06-*.json | Wiederkehrende Rechnungen | Zeitgesteuert: Monatliche Rechnungen aus Vorlage |
| wf07-*.json | Sammelrechnung Lieferscheine | Lieferscheine gruppieren und als Sammelrechnung |
| wf08-*.json | Rechnung PDF per E-Mail | PDF generieren und per Gmail versenden |
03 - Mahnwesen
| Datei | Name | Beschreibung |
|-------|------|-------------|
| wf09-*.json | 3-Stufen Mahnwesen | Ueberfaellige Rechnungen in 3 Stufen mahnen |
| wf10-*.json | Ueberfaellige Rechnungen Dashboard | Taegliches Dashboard per Slack |
| wf11-*.json | Zahlungseingang bestaetigen | Webhook bei Zahlung: Bestaetigung per E-Mail |
04 - Kontakte
| Datei | Name | Beschreibung |
|-------|------|-------------|
| wf12-*.json | Kontakte aus Webformular | Webhook: Kontakt anlegen wenn nicht vorhanden |
| wf13-*.json | Duplikate erkennen | Taeglich pruefen auf doppelte Kontakte |
| wf14-*.json | CRM-Sync Google Sheets | Kontakte nach Google Sheets synchronisieren |
05 - Reporting
| Datei | Name | Beschreibung |
|-------|------|-------------|
| wf15-*.json | Monatlicher Umsatzbericht | Umsatz aggregiert per Slack/E-Mail |
| wf16-*.json | Top-10 Kunden Umsatz | Ranking der umsatzstaerksten Kunden |
| wf17-*.json | USt-VA Vorbereitung | Vorsteuerdaten fuer Umsatzsteuervoranmeldung |
| wf18-*.json | DATEV-Export | CSV-Export im DATEV-nahen Format |
06 - Automatisierung
| Datei | Name | Beschreibung |
|-------|------|-------------|
| wf19-*.json | Artikelpreise aus Google Sheet | Preise aus Sheet lesen und Artikel aktualisieren |
| wf20-*.json | Echtzeit-Benachrichtigungen | Slack-Hub fuer Lexware-Events |
Workflow-Architektur (KI-Workflows WF01)
Schedule Trigger (alle 30 Min)
│
▼
Lexware Buchungskategorien (postingCategory/getAll)
│ Laedt die echten Buchungskategorien aus dem Lexware-Konto
▼
Kategorien zusammenfassen (Code)
│ Komprimiert alle Kategorie-Items in ein Array
▼
Lexware Belege abrufen (voucherlist/getAll, Status: unchecked)
│
▼
Belege extrahieren (Code)
│ Extrahiert content-Array in einzelne Items
▼
Belege einzeln verarbeiten (SplitInBatches)
│
├──▶ Beleg-Details abrufen (voucher/get)
│ │
│ ▼
│ Kategorien & Prompt (Code)
│ │ Baut System-Prompt mit echten Kategorien
│ │ + User-Prompt mit Belegdaten
│ ▼
│ KI Kategorisierung (OpenAI / Gemini / Anthropic)
│ │
│ ▼
│ KI-Antwort verarbeiten (Code)
│ │ Parst JSON aus KI-Antwort
│ ▼
│ Beleg aktualisieren (voucher/update)
│ │
└──◀──┘ (Loop)Wichtige Code-Patterns in Workflows
content-Array extrahieren (PFLICHT bei getAll-Operationen)
Die Lexware API gibt bei voucherlist/getAll und contact/getAll ein Objekt mit content-Array zurueck:
{ "content": [{ "id": "...", ... }, { "id": "...", ... }], "totalPages": 1, "totalElements": 3 }Die n8n-Node gibt dieses Objekt als ein einziges Item weiter. Daher muss immer ein Code-Node nachgeschaltet werden:
// Belege extrahieren
const rawData = $input.first().json;
const items = rawData.content || [];
return items.map(v => ({ json: v }));Ohne diesen Schritt sind Felder wie $json.id undefined.
Kontakt extrahieren (bei contact/getAll)
// Kontakt extrahieren - gibt erstes Ergebnis oder _contactExists: false
const rawData = $input.first().json;
const contacts = rawData.content || [];
if (contacts.length > 0) {
return [{ json: { _contactExists: true, ...contacts[0] } }];
} else {
return [{ json: { _contactExists: false } }];
}KI-Antwort parsen (fuer alle drei KI-Provider)
let responseText = item.text || item.content || item.message || '';
if (typeof responseText === 'object') responseText = JSON.stringify(responseText);
const jsonMatch = responseText.match(/\{[\s\S]*\}/);
if (!jsonMatch) throw new Error('Kein JSON in KI-Antwort gefunden');
const ai = JSON.parse(jsonMatch[0]);Referenz auf fruehere Nodes im Loop
// Daten von einem Node AUSSERHALB des Loops referenzieren
const categories = $('Kategorien zusammenfassen').first().json.categories;KI-Provider Native n8n Nodes
| Provider | n8n Node Type | Model | Credential |
|----------|--------------|-------|------------|
| OpenAI | @n8n/n8n-nodes-langchain.openAi | gpt-4o-mini | openAiApi |
| Google Gemini | @n8n/n8n-nodes-langchain.googleGemini | models/gemini-2.0-flash | googlePalmApi |
| Anthropic | @n8n/n8n-nodes-langchain.anthropic | claude-sonnet-4-20250514 | anthropicApi |
Alle verwenden: resource: "text", operation: "message", simplifyOutput: true, jsonOutput: true, temperature: 0.2
Bekannte Besonderheiten der Lexware API
content-Array bei Listenabfragen
voucherlist/getAll, contact/getAll und article/getAll geben kein Array zurueck, sondern ein Paginierungs-Objekt mit einem content-Array. Die Node gibt dieses als einzelnes Item weiter. In Workflows muss das content-Array immer manuell extrahiert werden (siehe oben).
Posting Categories
GET /v1/posting-categories gibt ein flaches Array (kein Paginierungs-Objekt) zurueck. Jede Kategorie hat:
{
"id": "uuid",
"name": "Buerobedarf",
"type": "expense",
"contactRequired": false,
"splitAllowed": true,
"groupName": "Sonstige betriebliche Aufwendungen"
}Diese Kategorien sind kontoabhaengig und spiegeln den im Lexware-Konto konfigurierten Kontenrahmen (SKR03 oder SKR04) wider.
Profile-Endpoint
GET /v1/profile gibt u.a. zurueck:
taxType: Besteuerungsart (z.B. Regelbesteuerung)smallBusiness: Kleinunternehmerregelung (ja/nein)features: Aktivierte Features im Konto
API-Rate-Limits
- 2 Requests pro Sekunde (Token-Bucket-Algorithmus)
- HTTP 429 bei Ueberschreitung
- In Workflows mit
SplitInBatchessind Pausen ggf. noetig
API-URL Migration
- Alt:
https://api.lexoffice.io(funktioniert bis Dezember 2025) - Neu:
https://api.lexware.io(produktiv seit Mai 2025) - Im Node-Code ist aktuell noch die alte URL hardcoded (
requestDefaultsundexecute())
Voucher voucherType-Werte
Fuer voucherlist/getAll muss voucherType explizit gesetzt werden (nicht leer lassen!):
salesinvoice,salescreditnote,purchaseinvoice,purchasecreditnoteinvoice,creditnote,orderconfirmation,quotation,deliverynote- Leeres Array
[]fuehrt zu "voucherType ist nicht definiert"-Fehler
Entwicklung
Voraussetzungen
- Node.js >= 22
- npm
Setup
git clone https://github.com/andreashenkel/n8n-nodes-lexware-office.git
cd n8n-nodes-lexware-office
npm installLokale Entwicklung
npm run dev # Startet n8n mit geladener Node + Hot-ReloadBuild
npm run build # Kompiliert TypeScript nach dist/Linting
npm run lint
npm run lint:fixCode-Style
- Tabs fuer Einrueckung
- Single Quotes
- Trailing Commas
- Print Width: 100
- LF Line Endings
Weiterentwicklung - Offene Aufgaben
Prioritaet Hoch
- [ ] API-URL auf
https://api.lexware.iomigrieren - Alte URL laeuft Dezember 2025 aus. BetrifftrequestDefaults.baseURLund die hardcoded URL inexecute()(Zeile ~538) - [ ] Fehlende API-Endpunkte implementieren:
Payment(GET /v1/payments/{id}) - Zahlungsinformationen abrufenPayment Conditions(GET /v1/payment-conditions) - ZahlungsbedingungenDunning(Mahnungen) - create, get, downloadFileDown Payment Invoice- get, downloadFileFiles- upload, downloadRecurring Templates- get, getAllPrint Layouts- getAll
Prioritaet Mittel
- [ ] WF02 (Eingangsrechnungen) mit Posting Categories erweitern - Wie WF01 echte Kategorien laden und der KI zur Verfuegung stellen
- [ ] Automatische Paginierung - Aktuell muss der Nutzer manuell
pageundsizesetzen. Eine Auto-Pagination waere komfortabler - [ ] Voucher-Update mit categoryId - Im Beleg-Update die von der KI vorgeschlagene
categoryIddirekt setzen (aktuell wird nur der Original-Beleg zurueckgeschrieben) - [ ] Rate-Limiting / Retry-Logik - Automatisches Retry bei HTTP 429
Prioritaet Niedrig
- [ ] Weitere KI-Workflows - WF03/WF04 koennten ebenfalls KI-Varianten bekommen
- [ ] Tests - Unit-Tests fuer getApiRoute(), buildQueryParams(), buildBody()
- [ ] Error-Handling verbessern - Spezifischere Fehlermeldungen bei API-Fehlern
- [ ] Webhook-Trigger-Node - Eigene Trigger-Node fuer Lexware Event Subscriptions
