Mandanten-Belege automatisch konvertieren: API-Lösung für Steuerberater
Wie Steuerkanzleien PDF-Belege ihrer Mandanten per API automatisch in DATEV-kompatible Formate und ZUGFeRD-Rechnungen konvertieren. Mit Praxisbeispiel und Implementierungsleitfaden.
Vellonode Team
Redaktion
Die Belegflut in der Steuerkanzlei
Steuerberater kennen das Problem: Mandanten liefern Belege in allen erdenklichen Formaten. Manche schicken ordentliche PDF-Rechnungen per E-Mail, andere fotografieren Kassenzettel mit dem Handy, wieder andere reichen einen USB-Stick mit 200 eingescannten Seiten ein. Am Monatsende türmt sich ein Berg aus PDFs, der manuell gesichtet, kategorisiert und in DATEV übertragen werden muss.
Bei einer typischen Kanzlei mit 80–120 Mandanten und durchschnittlich 30–50 Belegen pro Mandant pro Monat summiert sich das auf mehrere tausend Einzelbelege. Pro Beleg rechnen erfahrene Buchhalter mit 2–4 Minuten für die manuelle Erfassung — das sind hunderte Stunden pro Monat.
Warum die bisherigen Lösungen nicht reichen
DATEV Unternehmen online bietet zwar eine Belegverarbeitung, aber die eingebaute OCR liefert bei uneinheitlichen Belegen durchwachsene Ergebnisse. Besonders problematisch sind eingescannte Belege mit schlechter Qualität, handschriftliche Ergänzungen und Rechnungen in ungewöhnlichen Layouts.
Mandanten-Apps wie DATEV Meine Belege setzen voraus, dass der Mandant mitmacht — und zwar konsequent. In der Praxis nutzen das 20–30% der Mandanten zuverlässig. Der Rest liefert weiter per E-Mail oder Papier.
Der API-basierte Ansatz: Belege rein, strukturierte Daten raus
Die Vellonode API nimmt ein PDF entgegen und liefert:
- Strukturierte Rechnungsdaten als JSON (Rechnungsnummer, Datum, Beträge, Positionen, Steuersätze, Käufer/Verkäufer)
- ZUGFeRD 2.4 XML (EN16931-validiert)
- Validierungsergebnis (sofort sichtbar, ob alle Pflichtfelder vorhanden sind)
Diese Daten können direkt in den DATEV-Import-Workflow fließen — ohne manuelle Zwischenschritte.
Der Workflow für die Kanzlei
Mandant sendet Belege (E-Mail, Upload, Cloud)
│
▼
PDF-Belege sammeln
│
▼
API-Aufruf pro Beleg
POST /api/v1/invoices/convert?organizationId=IHRE_ORG_ID
│
▼
JSON-Daten + ZUGFeRD-XML
│
▼
Automatische Zuordnung
(Mandant → Konto → DATEV)
│
▼
DATEV-Import oder manuelle Prüfung
Implementierung: Batch-Verarbeitung mit Python
Das folgende Script verarbeitet einen Ordner voller PDF-Belege und erzeugt für jeden Beleg eine JSON-Datei mit den extrahierten Daten:
import os
import requests
import json
from pathlib import Path
# 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("./mandant_belege")
OUTPUT_DIR = Path("./verarbeitet")
def process_directory(input_dir, output_dir):
output_dir.mkdir(exist_ok=True)
pdf_files = list(input_dir.glob("*.pdf"))
print(f"{len(pdf_files)} PDFs gefunden")
results = []
for i, pdf_path in enumerate(pdf_files, 1):
print(f"[{i}/{len(pdf_files)}] {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": "zugferd,json"},
)
if response.status_code == 200:
result = response.json()
data = result["data"]
# JSON speichern
json_path = output_dir / f"{pdf_path.stem}.json"
with open(json_path, "w", encoding="utf-8") as jf:
json.dump(result, jf,
ensure_ascii=False, indent=2)
results.append({
"datei": pdf_path.name,
"rechnungsnr": data.get("invoiceNumber"),
"lieferant": (data.get("seller") or {})
.get("name"),
"betrag": (data.get("totals") or {})
.get("grossTotal"),
"valid": result["validation"]["valid"],
})
print(f" OK: {data.get('invoiceNumber')} - "
f"{data.get('totals', {}).get('grossTotal')} EUR")
elif response.status_code == 429:
print(" Rate-Limit - warte...")
import time
retry = int(
response.headers.get("Retry-After", "10")
)
time.sleep(retry)
else:
print(f" Fehler: {response.status_code}")
results.append({
"datei": pdf_path.name,
"fehler": response.status_code,
})
# Übersicht als CSV
csv_path = output_dir / "uebersicht.csv"
with open(csv_path, "w", encoding="utf-8") as csvf:
csvf.write(
"Datei;Rechnungsnr;Lieferant;Betrag;Valid\n"
)
for r in results:
if "fehler" in r:
csvf.write(f"{r['datei']};;;;"
f"FEHLER {r['fehler']}\n")
else:
csvf.write(
f"{r['datei']};{r['rechnungsnr']};"
f"{r['lieferant']};{r['betrag']};"
f"{'Ja' if r['valid'] else 'Nein'}\n"
)
print(f"\nFertig. Übersicht: {csv_path}")
if __name__ == "__main__":
process_directory(INPUT_DIR, OUTPUT_DIR)
Bei großen Belegmengen empfiehlt sich eine parallele Verarbeitung mit concurrent.futures.ThreadPoolExecutor. Das Rate-Limit der API liegt bei 30 Requests pro Minute — mit 3–5 parallelen Threads nutzen Sie das optimal aus, ohne das Limit zu überschreiten.
Praxisbeispiel: Kanzlei mit 95 Mandanten
Eine mittelständische Steuerkanzlei in Süddeutschland betreut 95 Mandanten, überwiegend Handwerksbetriebe und kleine Dienstleister. Das monatliche Belegvolumen liegt bei 2.500–3.000 Eingangsrechnungen.
Ausgangslage:
- 2 Vollzeit-Buchhalterinnen nur für die Belegerfassung
- Durchschnittlich 3 Minuten pro Beleg (Sichten, Erfassen, Kontieren)
- Fehlerquote: 2–3% — auffallend bei der Umsatzsteuervoranmeldung
Nach der API-Integration:
- Ein Python-Script verarbeitet die Belege über Nacht in Batches
- Am Morgen liegt eine CSV-Übersicht mit allen extrahierten Daten vor
- Die Buchhalterinnen prüfen nur noch Belege, bei denen die Validierung Fehler meldet (ca. 15–20%)
- Die restlichen 80% werden direkt in DATEV importiert
Ergebnis nach 3 Monaten:
- Zeitaufwand für Belegerfassung: von 120 auf 30 Stunden pro Monat
- Fehlerquote: unter 0,5%
- Eine Buchhalterin konnte auf wertschöpfendere Tätigkeiten umgeschichtet werden (Mandantenberatung, Jahresabschlüsse)
Von JSON zu DATEV: Die Brücke bauen
Die API liefert strukturiertes JSON. Für den DATEV-Import brauchen Sie DATEV-Buchungssätze. Die Zuordnung folgt einem einfachen Schema:
| JSON-Feld | DATEV-Feld | Logik |
|---|---|---|
data.totals.grossTotal | Umsatz | Bruttobetrag |
data.totals.vatAmount | Steuerbetrag | USt-Betrag |
data.lines[].vatRate | BU-Schlüssel | 19% → BU 9, 7% → BU 8 |
data.seller.name | Belegfeld 1 | Lieferantenname |
data.invoiceNumber | Belegfeld 2 | Rechnungsnummer |
data.invoiceDate | Belegdatum | Rechnungsdatum |
Die Erlös-/Aufwandskonten (z.B. 3400 für Wareneingang 19% im SKR03) können Sie über eine Zuordnungstabelle pro Mandant oder über den Lieferantennamen automatisch vergeben.
Die Vellonode-App bietet auch einen direkten DATEV-Export (Schnittstelle online v060) mit automatischer Kontenzuordnung. Wenn Sie die Web-Oberfläche bevorzugen statt der API, können Sie Belege auch dort hochladen und den DATEV-Export per Klick herunterladen.
Mandanten einbinden: Der Beleg-Upload-Workflow
Die eleganteste Variante: Mandanten laden ihre Belege selbst hoch. Dafür gibt es mehrere Ansätze:
1. Gemeinsames E-Mail-Postfach: Der Mandant schickt Rechnungen an eine dedizierte Adresse (z.B. [email protected]). Ein automatisierter Workflow verarbeitet die Anhänge per API.
2. Cloud-Ordner: Ein geteilter Ordner (Nextcloud, Google Drive, Dropbox) wird überwacht. Neue PDFs werden automatisch verarbeitet.
3. Vellonode-Account pro Mandant: Jeder Mandant erhält einen eigenen Zugang. Die Kanzlei sieht alle Organisationen in der Support-Ansicht und kann Daten mandantenübergreifend exportieren.
Nächste Schritte
- Konto erstellen unter vellonode.de/auth/register
- API-Key generieren unter Einstellungen → API
- Testlauf mit 10 Belegen eines Mandanten
- Zuordnungstabelle für DATEV-Konten pro Mandant aufbauen
- Batch-Script für den Produktivbetrieb einrichten
Die API-Dokumentation finden Sie unter /api/v1/openapi.