DMS-Integration per API: PDF-Rechnungen automatisch strukturiert archivieren
Wie DMS- und Archiv-Software die Vellonode API nutzt, um eingehende PDF-Rechnungen automatisch zu indexieren und GoBD-konform abzulegen. Mit Code-Beispiel und Architekturüberblick.
Vellonode Team
Redaktion
Das Problem: PDF-Rechnungen im DMS ohne Struktur
Dokumentenmanagementsysteme sind dafür gebaut, Dokumente zu speichern, zu versionieren und wiederzufinden. Aber ein PDF allein enthält keine maschinenlesbaren Metadaten. Wer eine Eingangsrechnung im DMS ablegen will, muss die Rechnungsdaten manuell erfassen: Rechnungsnummer, Lieferant, Betrag, Datum — alles von Hand eintippen, damit das Dokument später auffindbar ist.
Bei kleinen Belegmengen ist das vertretbar. Bei hunderten Eingangsrechnungen pro Monat wird es zum Flaschenhals. Und die manuelle Erfassung bringt Fehlerquellen: vertippte Rechnungsnummern, falsche Beträge, inkonsistente Lieferantennamen.
Die Lösung: PDF hochladen, JSON zurückbekommen
Die Vellonode API extrahiert aus jedem PDF sämtliche Rechnungsdaten als strukturiertes JSON. Dieses JSON kann direkt als Metadaten-Set für das DMS verwendet werden — ohne manuellen Zwischenschritt.
Was die API liefert
Ein einzelner POST-Request mit dem PDF liefert:
- Rechnungsnummer, Datum, Fälligkeitsdatum
- Verkäufer und Käufer mit Name, USt-ID und Adresse
- Alle Positionen mit Beschreibung, Menge, Einzelpreis, Steuersatz
- Summen (Netto, USt, Brutto) und Steuer-Aufschlüsselung
- Validierungsergebnis gegen EN16931
Das JSON hat eine feste Struktur — ideal für die automatische Indexierung.
Architektur: DMS + API
Eingangskanal (E-Mail, Scanner, Upload)
│
▼
PDF im Eingangsordner
│
▼
API-Aufruf: POST /api/v1/invoices/convert?organizationId=IHRE_ORG_ID
│
▼
JSON-Response mit Rechnungsdaten
│
├──▶ DMS: Dokument + Metadaten speichern
├──▶ Index: Volltextsuche aktualisieren
└──▶ Optional: ZUGFeRD-XML archivieren
Integration in den DMS-Workflow
Die meisten DMS-Systeme bieten einen der folgenden Integrationswege:
1. Überwachter Import-Ordner: Das DMS überwacht einen Ordner. Ein Script legt dort das PDF plus eine Metadaten-Datei (XML oder JSON) ab. Das DMS importiert beides automatisch.
2. REST-API des DMS: Viele moderne DMS-Systeme (DocuWare, d.velop, ELO, Amagno) bieten eigene APIs. Das Integrations-Script ruft erst die Vellonode API auf, dann die DMS-API.
3. Webhook/Event-basiert: Das DMS löst bei einem neuen Dokument einen Webhook aus. Ein Microservice fängt den Webhook ab, ruft die Vellonode API auf und schreibt die Metadaten zurück.
Code-Beispiel: Python-Integration
Das folgende Script überwacht einen Eingangsordner, extrahiert Rechnungsdaten per API und legt das Ergebnis strukturiert ab:
import os
import json
import time
import shutil
import requests
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
# organizationId ist ein Pflichtparameter – abrufbar über GET /api/v1/organizations
API_URL = "https://vellonode.de/api/v1/invoices/convert?organizationId=IHRE_ORG_ID"
API_KEY = "vk_live_IhrKeyHier"
INPUT_DIR = Path("./eingang")
ARCHIVE_DIR = Path("./archiv")
class InvoiceHandler(FileSystemEventHandler):
def on_created(self, event):
if not event.is_directory and \
event.src_path.lower().endswith(".pdf"):
time.sleep(1) # Datei vollständig geschrieben
self.process(Path(event.src_path))
def process(self, pdf_path):
print(f"Verarbeite: {pdf_path.name}")
with open(pdf_path, "rb") as f:
response = requests.post(
API_URL,
headers={
"Authorization": f"Bearer {API_KEY}"
},
files={
"file": (
pdf_path.name,
f,
"application/pdf",
)
},
data={"format": "json"},
)
if response.status_code != 200:
print(f" Fehler: {response.status_code}")
return
result = response.json()
data = result["data"]
# Ordnerstruktur: archiv/2026/06/Lieferant/
seller = (data.get("seller") or {}).get("name")
seller_safe = "".join(
c if c.isalnum() or c in " -_" else "_"
for c in (seller or "Unbekannt")
).strip()
invoice_date = data.get("invoiceDate", "")
year = invoice_date[:4] if invoice_date else "0000"
month = invoice_date[5:7] if len(
invoice_date
) >= 7 else "00"
target_dir = ARCHIVE_DIR / year / month / seller_safe
target_dir.mkdir(parents=True, exist_ok=True)
# PDF kopieren
invoice_nr = data.get("invoiceNumber", "unbekannt")
safe_nr = "".join(
c if c.isalnum() or c in "-_" else "_"
for c in invoice_nr
)
target_pdf = target_dir / f"{safe_nr}.pdf"
shutil.copy2(pdf_path, target_pdf)
# Metadaten als JSON daneben
meta_path = target_dir / f"{safe_nr}.meta.json"
metadata = {
"invoiceNumber": invoice_nr,
"invoiceDate": invoice_date,
"seller": data.get("seller"),
"buyer": data.get("buyer"),
"totals": data.get("totals"),
"currency": data.get("currency"),
"lines": len(data.get("lines", [])),
"validation": result.get("validation"),
"sourceFile": pdf_path.name,
"processedAt": time.strftime("%Y-%m-%dT%H:%M:%S"),
}
with open(meta_path, "w", encoding="utf-8") as mf:
json.dump(metadata, mf,
ensure_ascii=False, indent=2)
# Original entfernen
pdf_path.unlink()
gross = (data.get("totals") or {}).get("grossTotal")
print(f" Archiviert: {invoice_nr} "
f"({seller}, {gross} EUR)")
if __name__ == "__main__":
INPUT_DIR.mkdir(exist_ok=True)
ARCHIVE_DIR.mkdir(exist_ok=True)
observer = Observer()
observer.schedule(
InvoiceHandler(), str(INPUT_DIR), recursive=False
)
observer.start()
print(f"Überwache {INPUT_DIR}...")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
Das Script nutzt die watchdog-Bibliothek für die Ordnerüberwachung. Installation: pip install watchdog requests. Für den Produktivbetrieb empfiehlt sich ein systemd-Service oder Docker-Container.
Praxisbeispiel: Mittelständischer Großhandel mit 800 Eingangsrechnungen pro Monat
Ein Elektrogroßhändler mit 12 Standorten erhält monatlich rund 800 Eingangsrechnungen von 200 verschiedenen Lieferanten. Die Rechnungen kommen per E-Mail, über EDI-Schnittstellen und teilweise noch per Post (eingescannt).
Ausgangslage:
- DMS: d.velop documents (on-premise)
- Rechnungen wurden manuell indexiert: Lieferant, Rechnungsnummer, Betrag, Datum
- 2 Mitarbeiter verbrachten zusammen 40 Stunden pro Monat mit der Indexierung
- Suchfunktion im DMS nur über manuell eingegebene Felder
Nach der API-Integration:
- Ein Python-Service überwacht den Import-Ordner des DMS
- Jedes neue PDF wird an die Vellonode API gesendet
- Die extrahierten Metadaten werden als d.velop-Indexdaten zurückgeschrieben
- Zusätzlich werden alle Positionsdetails in einer Elasticsearch-Instanz indexiert
Ergebnis:
- Indexierungszeit: von 40 auf 4 Stunden pro Monat (nur noch Prüfung gelb/rot markierter Felder)
- Neue Suchfähigkeit: Volltextsuche über Positionen, Artikelnummern, Beträge
- Automatische Lieferantenerkennung über USt-ID statt manueller Zuordnung
Metadaten-Mapping für gängige DMS-Systeme
| JSON-Feld | DocuWare | d.velop | ELO | Amagno |
|---|---|---|---|---|
invoiceNumber | RECHNUNGSNR | Belegnummer | Rechnungsnummer | invoice_number |
invoiceDate | RECHNUNGSDATUM | Belegdatum | Rechnungsdatum | invoice_date |
seller.name | LIEFERANT | Absender | Kontakt | sender |
seller.vatId | UST_ID | Steuernummer | USt-IdNr | vat_id |
totals.grossTotal | BETRAG | Bruttobetrag | Betrag | amount |
currency | WAEHRUNG | Währung | Währung | currency |
Die JSON-Feldnamen der API sind stabil — das Mapping muss nur einmal eingerichtet werden.
Neben dem strukturierten JSON kann die API auch ZUGFeRD-XML erzeugen. Für die Langzeitarchivierung nach GoBD ist das ZUGFeRD-PDF (PDF/A-3 mit eingebettetem XML) das ideale Format — maschinenlesbar und gleichzeitig visuell prüfbar.
Nächste Schritte
- Konto erstellen unter vellonode.de/auth/register
- API-Key generieren unter Einstellungen → API
- Testlauf mit 10 echten Eingangsrechnungen
- Metadaten-Mapping für Ihr DMS definieren
- Integration in den produktiven Import-Workflow
Die API-Dokumentation finden Sie unter /api/v1/openapi.