Een conforme Peppol-factuur genereren met n8n en SealDoc
Een conforme Peppol-factuur genereren heeft meer bewegende delen dan het lijkt. Je hebt een geldig CII-XML-document nodig, het juiste EN 16931-profiel, een PDF/A-3-container, een ingebedde XML-bijlage en idealiter een RFC 3161-tijdstempel voordat het in je archief gaat. Dit allemaal zelf implementeren in een aangepaste integratie is weken werk.
Deze tutorial laat zien hoe je hetzelfde resultaat in n8n in ongeveer 30 minuten in elkaar zet met de community-node n8n-nodes-sealdoc. Geen aangepaste code. De workflow bestrijkt factuurgenewratie, jobpolling en resultaatopslag.
Vereisten
Voordat je begint, heb je nodig:
- Een n8n-instantie met versie 1.0 of later, zelfgehost of n8n Cloud. De community-node werkt op beide.
- Een SealDoc-account op het Starter-plan of hoger. De functies voor factuurgenewratie en tijdstempeling zijn beschikbaar vanaf Starter.
- Een SealDoc API-sleutel. Genereer er een in het SealDoc-dashboard onder Instellingen, dan API-sleutels. Kopieer hem direct; we tonen hem slechts eenmalig.
Installeer de community-node op je n8n-instantie:
npm i n8n-nodes-sealdoc
Herstart n8n na installatie. Je ziet nu de SealDoc-node beschikbaar in het nodepaneel onder de Community-categorie.
Wat de workflow doet
Deze workflow neemt factuurgegevens (verkoper, koper, regelitems, bedragen) en produceert een volledig conforme Factur-X PDF/A-3 met ingebedde CII-XML. De stappen zijn:
- Een trigger levert de factuurgegevens als JSON (vanuit een webhook, een databasequery, een formulierinzending of een andere n8n-bron).
- De node SealDoc Invoice.Generate stuurt de gestructureerde gegevens naar de SealDoc-API en geeft een job-ID terug.
- De node SealDoc Job.Get pollt totdat de job voltooid is en geeft een download-URL terug voor het gegenereerde document.
- Een laatste node slaat het resultaat op op de archieflocatie van je keuze.
Stap 1: de trigger instellen
Maak een nieuwe workflow aan. Voeg een Webhook-triggernode toe. Stel de HTTP-methode in op POST. Dit geeft je een URL die je kunt aanroepen met factuurgegevens vanuit elk systeem dat een HTTP-verzoek kan maken.
Voor testen kun je ook een Execute Workflow Trigger of een Manual Trigger met statische gegevens gebruiken. Het belangrijkste is dat de trigger een JSON-object uitvoert met je factuurvelden. We verwijzen naar die velden in de volgende stap.
Een minimaal voorbeeld van de factuurgegevens die je trigger moet leveren:
{
"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": "Adviesservices mei 2026",
"quantity": 10,
"unitPrice": 150.00,
"vatRate": 21
}
],
"currency": "EUR"
}
Stap 2: de Invoice.Generate-node toevoegen
Voeg een SealDoc-node toe aan het canvas. Stel in:
- Resource: Invoice
- Operation: Generate
- Profile: EN 16931 (gebruik EXTENDED als je koper of mandaat extra velden vereist)
- Embed timestamp: AAN (dit koppelt een RFC 3161-tijdstempel aan het uitvoerdocument)
- Input data: wijs toe vanuit de triggeruitvoer met n8n-expressies, bijv.
{{ $json.invoiceNumber }}voor het factuurnummer,{{ $json.seller.vatNumber }}voor het btw-nummer van de verkoper, enzovoort voor elk veld.
Selecteer of maak in het gedeelte Credentials een SealDoc-API-credential. Plak je API-sleutel in het veld Geheim.
Klik op Execute Node om te testen. Als de API-sleutel geldig is en de factuurgegevens volledig zijn, ontvang je een reactie zoals:
{
"jobId": "job_9kxQr2mPLv",
"status": "pending",
"estimatedSeconds": 4
}
De job is in de wachtrij geplaatst. De SealDoc-API verwerkt hem asynchroon zodat een trage pdf-weergave je workflowuitvoering niet blokkeert.
Stap 3: de Job.Get-node met polling toevoegen
Voeg een tweede SealDoc-node toe. Stel in:
- Resource: Job
- Operation: Get
- Job ID:
{{ $node["SealDoc Invoice Generate"].json.jobId }}
Verpak deze node in een n8n-Wait-node ingesteld op een interval van 3 seconden, met een lus die controleert of status gelijk is aan completed of failed. De meeste facturen worden in minder dan 5 seconden voltooid. Stel het maximale iteratieaantal in op 10 om een oneindige lus bij een echt vastgelopen job te voorkomen.
Wanneer status completed is, bevat de Job.Get-reactie:
downloadUrl: een tijdgebonden URL (10 minuten geldig) die verwijst naar het gegenereerde PDF/A-3-document.evidencePackUrl: een ZIP-archief met de originele invoer, de uitvoer-PDF/A-3, de ingebedde Factur-X-XML, het RFC 3161-tijdstempeltoken en een manifesthash-bestand. Dit is wat je aan een auditor overhandigt.facturXProfile: het werkelijk gebruikte profiel (bevestigt EN 16931 of EXTENDED).timestampedAt: de UTC-tijdstempel van het RFC 3161-token, wat de juridisch significante aanmaagtijd is.
Als status failed is, controleer het veld failureReason. Veelgemaakte waarden zijn validation_failed (een verplicht veld ontbrak in je invoer), unsupported_currency (SealDoc ondersteunt EUR, USD, GBP, CHF, PLN, CZK en een groeiende lijst) en quota_exceeded (je maandelijkse joblimiet is bereikt).
Stap 4: het resultaat opslaan
Voeg welke opslagnode ook bij je stack past toe. Veelgemaakte opties:
- HTTP Request-node om het bestand via PUT te sturen naar je eigen documentbeheersysteem of MinIO-bucket.
- Google Drive of Dropbox-node als je cloudopslag voor je archief gebruikt.
- FTP/SFTP-node voor on-premiseopslag.
- Move Binary Data plus Write Binary File als n8n zelfgehost is en je rechtstreeks naar een bestandssysteempad wilt schrijven.
Gebruik de downloadUrl uit de Job.Get-reactie om het binaire bestand op te halen en geef het door aan je opslagnode. Sla ook de evidencePackUrl afzonderlijk op als je bewaarbeleid dit vereist, wat het zou moeten voor facturen boven een bepaalde waarde of in gereguleerde sectoren.
Wat je in de uitvoer krijgt
Het gegenereerde bestand is een PDF/A-3B-document. Het openen in een pdf-viewer toont een weergegeven factuur. De ingebedde bijlage factur-x.xml bevat de volledige CII-XML, leesbaar door boekhoudsoftware die Factur-X- of ZUGFeRD-import ondersteunt. Het RFC 3161-tijdstempel is ingebed in het documentinformatiewoordenboek van de pdf en is onafhankelijk verifieerbaar.
Als je de uitvoer door een validator haalt (onze gratis Validator-tool accepteert het bestand rechtstreeks), zie je een groen resultaat voor PDF/A-3B-conformiteit, EN 16931-schemageldigheid en aanwezigheid van Factur-X-bijlage.
Volgende stappen
Deze tutorial behandelt de kerngenewratieflow. De API van SealDoc ondersteunt ook:
- Peppol-opzoeking: controleer voordat je een factuur genereert of de koper bereikbaar is op Peppol via de Peppol-resource in de SealDoc-node.
- Alleen validatie: dien een bestaand Factur-X- of XRechnung-bestand in voor schemavalidatie zonder een nieuw document te genereren.
- Batchgenewratie: dien meerdere factuurpayloads in een enkele API-aanroep in voor scenario’s met hoog volume.
Volledige API-documentatie staat op onze developerspagina, met OpenAPI-specificatie en kopieerbare curl-voorbeelden voor elk endpoint.