← Back to all articles

Wie man eine konforme Peppol-Rechnung mit n8n und SealDoc generiert

SealDoc Team · · 5 min read

Das Generieren einer konformen Peppol-Rechnung beinhaltet mehr bewegliche Teile als es zunächst aussieht. Sie benötigen ein gültiges CII-XML-Dokument, das richtige EN 16931-Profil, einen PDF/A-3-Container, einen eingebetteten XML-Anhang und idealerweise einen RFC 3161-Zeitstempel, bevor es in Ihr Archiv gelangt. All das von Grund auf in einer eigenen Integration zu implementieren, erfordert wochenlange Arbeit.

Dieses Tutorial zeigt, wie dasselbe Ergebnis in n8n in ca. 30 Minuten zusammengestellt werden kann, mithilfe des Community-Nodes n8n-nodes-sealdoc. Kein eigener Code. Der Workflow umfasst Rechnungsgenerierung, Job-Polling und Ergebnisspeicherung.

Voraussetzungen

Bevor Sie beginnen, benötigen Sie:

  • Eine n8n-Instanz mit Version 1.0 oder höher, entweder selbst gehostet oder n8n Cloud. Der Community-Node funktioniert auf beiden.
  • Ein SealDoc-Konto im Starter-Tarif oder höher. Die Funktionen für Rechnungsgenerierung und Zeitstempelung sind ab Starter verfügbar.
  • Einen SealDoc-API-Schlüssel. Generieren Sie einen im SealDoc-Dashboard unter Einstellungen und dann API-Schlüssel. Kopieren Sie ihn sofort; er wird nur einmal angezeigt.

Installieren Sie den Community-Node auf Ihrer n8n-Instanz:

npm i n8n-nodes-sealdoc

n8n nach der Installation neu starten. Der SealDoc-Node ist jetzt im Node-Panel unter der Kategorie Community verfügbar.

Was der Workflow macht

Dieser Workflow nimmt Rechnungsdaten (Verkäufer, Käufer, Posten, Beträge) und produziert ein vollständig konformes Factur-X-PDF/A-3 mit eingebettetem CII-XML. Die Schritte sind:

  1. Ein Trigger stellt die Rechnungsdaten als JSON bereit (von einem Webhook, einer Datenbankabfrage, einer Formulareingabe oder einer anderen n8n-Quelle).
  2. Der SealDoc Invoice.Generate-Node sendet die strukturierten Daten an die SealDoc-API und gibt eine Job-ID zurück.
  3. Der SealDoc Job.Get-Node pollt, bis der Job abgeschlossen ist, und gibt eine Download-URL für das generierte Dokument zurück.
  4. Ein abschließender Node speichert das Ergebnis an Ihrem bevorzugten Archivierungsort.

Schritt 1: Den Trigger einrichten

Erstellen Sie einen neuen Workflow. Fügen Sie einen Webhook-Trigger-Node hinzu. Setzen Sie die HTTP-Methode auf POST. Dies gibt Ihnen eine URL, die Sie mit Rechnungsdaten von jedem System aus aufrufen können, das HTTP-Anfragen stellen kann.

Zum Testen können Sie auch einen Execute Workflow Trigger oder einen Manual Trigger mit statischen Daten verwenden. Das Wichtige ist, dass der Trigger ein JSON-Objekt mit Ihren Rechnungsfeldern ausgibt. Diese Felder werden im nächsten Schritt referenziert.

Ein minimales Beispiel der Rechnungsdaten, die Ihr Trigger bereitstellen sollte:

{
  "invoiceNumber": "INV-2026-00042",
  "issueDate": "2026-05-06",
  "dueDate": "2026-06-05",
  "seller": {
    "name": "Acme BV",
    "vatNumber": "NL123456789B01",
    "address": "Herengracht 1, 1000 AA Amsterdam, NL",
    "iban": "NL91ABNA0417164300"
  },
  "buyer": {
    "name": "Widget GmbH",
    "vatNumber": "DE987654321",
    "address": "Hauptstrasse 10, 10115 Berlin, DE"
  },
  "lines": [
    {
      "description": "Consulting services May 2026",
      "quantity": 10,
      "unitPrice": 150.00,
      "vatRate": 21
    }
  ],
  "currency": "EUR"
}

Schritt 2: Den Invoice.Generate-Node hinzufügen

Fügen Sie einen SealDoc-Node zur Arbeitsfläche hinzu. Einstellungen:

  • Resource: Invoice
  • Operation: Generate
  • Profile: EN 16931 (EXTENDED verwenden, wenn Ihr Käufer oder Mandat zusätzliche Felder erfordert)
  • Embed timestamp: EIN (dies fügt dem Ausgabedokument einen RFC 3161-Zeitstempel hinzu)
  • Input data: Aus der Trigger-Ausgabe über n8n-Ausdrücke zuordnen, z.B. {{ $json.invoiceNumber }} für die Rechnungsnummer, {{ $json.seller.vatNumber }} für die USt-Nummer des Verkäufers, und so weiter für jedes Feld.

Wählen oder erstellen Sie im Bereich Credentials eine SealDoc-API-Credential. Fügen Sie Ihren API-Schlüssel in das Feld Secret ein.

Klicken Sie auf Execute Node zum Testen. Wenn der API-Schlüssel gültig und die Rechnungsdaten vollständig sind, erhalten Sie eine Antwort wie:

{
  "jobId": "job_9kxQr2mPLv",
  "status": "pending",
  "estimatedSeconds": 4
}

Der Job wurde in die Warteschlange gestellt. Die SealDoc-API verarbeitet ihn asynchron, damit ein langsames PDF-Rendering Ihre Workflow-Ausführung nicht blockiert.

Schritt 3: Den Job.Get-Node mit Polling hinzufügen

Fügen Sie einen zweiten SealDoc-Node hinzu. Einstellungen:

  • Resource: Job
  • Operation: Get
  • Job ID: {{ $node["SealDoc Invoice Generate"].json.jobId }}

Wickeln Sie diesen Node in n8ns Wait-Node mit einem 3-Sekunden-Intervall ein, mit einer Schleife zurück, die prüft, ob status gleich completed oder failed ist. Die meisten Rechnungen werden in unter 5 Sekunden abgeschlossen. Setzen Sie die maximale Iterationsanzahl auf 10, um eine Endlosschleife bei einem echten feststeckenden Job zu vermeiden.

Wenn status completed ist, enthält die Job.Get-Antwort:

  • downloadUrl: eine zeitlich begrenzte URL (10 Minuten gültig), die auf das generierte PDF/A-3-Dokument zeigt.
  • evidencePackUrl: ein ZIP-Archiv mit den ursprünglichen Eingaben, dem Ausgabe-PDF/A-3, dem eingebetteten Factur-X-XML, dem RFC 3161-Zeitstempel-Token und einer Manifest-Hash-Datei. Das ist das, was Sie einem Prüfer übergeben.
  • facturXProfile: das tatsächlich verwendete Profil (bestätigt EN 16931 oder EXTENDED).
  • timestampedAt: der UTC-Zeitstempel des RFC 3161-Tokens, der rechtlich relevante Erstellungszeitpunkt.

Wenn status failed ist, prüfen Sie das Feld failureReason. Häufige Werte sind validation_failed (ein Pflichtfeld fehlte in Ihrer Eingabe), unsupported_currency (SealDoc unterstützt EUR, USD, GBP, CHF, PLN, CZK und eine wachsende Liste) und quota_exceeded (Ihr monatliches Job-Limit ist erreicht).

Schritt 4: Das Ergebnis speichern

Fügen Sie den Speicher-Node hinzu, der zu Ihrem Stack passt. Häufige Optionen:

  • HTTP Request-Node, um die Datei per PUT an Ihr eigenes Dokumentenmanagementsystem oder MinIO-Bucket zu senden.
  • Google Drive- oder Dropbox-Node, wenn Sie Cloud-Speicher für Ihr Archiv verwenden.
  • FTP/SFTP-Node für Vor-Ort-Speicherung.
  • Move Binary Data plus Write Binary File, wenn n8n selbst gehostet ist und Sie direkt in einen Dateisystempfad schreiben möchten.

Die downloadUrl aus der Job.Get-Antwort verwenden, um die Binärdatei abzurufen, und sie dann an Ihren Speicher-Node weitergeben. Speichern Sie auch die evidencePackUrl separat, wenn Ihre Aufbewahrungsrichtlinie dies erfordert, was für Rechnungen über einem bestimmten Wert oder in regulierten Branchen der Fall sein sollte.

Was Sie in der Ausgabe erhalten

Die generierte Datei ist ein PDF/A-3B-Dokument. Das Öffnen in einem beliebigen PDF-Betrachter zeigt eine gerenderte Rechnung. Der eingebettete Anhang factur-x.xml enthält das vollständige CII-XML, lesbar von Buchhaltungssoftware, die den Factur-X- oder ZUGFeRD-Import unterstützt. Das RFC 3161-Zeitstempel-Token ist im Dokumentinformations-Wörterbuch der PDF eingebettet und unabhängig verifizierbar.

Wenn Sie die Ausgabe durch einen Validator laufen lassen (unser kostenloses Validator-Tool akzeptiert die Datei direkt), sehen Sie ein grünes Ergebnis für PDF/A-3B-Konformität, EN 16931-Schema-Gültigkeit und Factur-X-Anhangsvorhandensein.

Nächste Schritte

Dieses Tutorial deckt den grundlegenden Generierungsfluss ab. Die API von SealDoc unterstützt außerdem:

  • Peppol-Lookup: Bevor Sie eine Rechnung generieren, prüfen Sie, ob der Käufer über Peppol erreichbar ist, über die Peppol-Ressource im SealDoc-Node.
  • Nur Validierung: Eine vorhandene Factur-X- oder XRechnung-Datei zur Schema-Validierung einreichen, ohne ein neues Dokument zu generieren.
  • Batch-Generierung: Mehrere Rechnungsnutzlasten in einem einzelnen API-Aufruf für Hochvolumen-Szenarien einreichen.

Die vollständige API-Dokumentation befindet sich auf unserer Entwicklerseite, mit OpenAPI-Spezifikation und kopierfertige curl-Beispiele für jeden Endpunkt.


← Back to all articles