
LedgerLou Kreditoren
Das Kreditoren-Modul bildet den gesamten Eingangsrechnungsprozess ab: Belege per E-Mail empfangen, per OCR extrahieren, gegen UStG §14 prüfen, Lieferanten zuordnen, buchen und offene Posten bis zur Zahlung nachverfolgen.
API ReferenceWorkflow
POST /v1/ocr/extract hochgeladen werden. Im E-Mail-Eingang werden PDF- und Bild-Anhänge automatisch erkannt.POST /v1/vendors anlegen.post_booking, dann Rechnung per POST /v1/invoices mit Positionen, Vendor-ID, Intent-ID und Document-ID anlegen. Der Status wechselt von draft zu open.GET /v1/invoices/open-items zeigt alle unbezahlten Rechnungen gruppiert nach Kreditor. Fällige und überfällige Positionen sind sofort sichtbar.candidate_kind=‘open_liability’ abgestimmt. Dabei wird der offene Posten reduziert und der Status automatisch auf partially_paid oder paid gesetzt.E-Mail-Eingang (Inbox)
Jeder Mandant erhält eine eigene Inbox-Adresse (z.B. lou-orbits-neptune@ledgerlou.de), an die Lieferanten oder das interne Team Belege weiterleiten kann. Die Adresse ist per GET /v1/inbox/address abrufbar und wird beim ersten Aufruf automatisch zugewiesen.
Was beim Empfang passiert:
- Anhänge filtern — Nur PDF- und Bild-Anhänge (JPEG, PNG) werden verarbeitet. Andere Dateitypen werden ignoriert. Pro E-Mail maximal 20 Anhänge, max. 10 MB pro Datei.
- Dokument speichern — Der Anhang wird per SHA-256-Content-Hash dedupliziert und auf der Festplatte gespeichert. Duplikate werden automatisch erkannt und übersprungen.
- OCR-Extraktion — Das Dokument wird per Mistral-OCR in Markdown konvertiert, dann von einem LLM in strukturierte Felder geparst (siehe nächster Abschnitt).
- Lieferanten-Zuordnung — Die extrahierten Daten (USt-IdNr., IBAN, Name) werden gegen die bestehenden Kreditoren des Mandanten abgeglichen.
- Rechnungsprüfung — Der Compliance-Checker prüft die UStG §14 Pflichtangaben und klassifiziert den Dokumenttyp.
- Inbox-Eintrag — Alle Ergebnisse werden als Inbox-Eintrag mit Status
pendinggespeichert.
Inbox-Status:
| Status | Bedeutung |
|---|---|
pending | Beleg empfangen, wartet auf Verarbeitung durch User oder Agent |
processing | Wird gerade verarbeitet |
confirmed | Rechnung erstellt und gebucht |
rejected | Beleg abgelehnt (ungültig, doppelt oder kein Rechnungsdokument) |
OCR-Extraktion
Die OCR-Extraktion läuft in zwei Stufen: Zunächst wird das Dokument per Mistral-OCR in Markdown-Text umgewandelt. Dann extrahiert ein LLM die folgenden strukturierten Felder:
Dokumentklassifikation:
| Feld | Beschreibung |
|---|---|
document_type | Dokumenttyp: invoice, credit_note, order_confirmation, delivery_note, quote, reminder, receipt, other |
Lieferantendaten:
| Feld | Beschreibung |
|---|---|
vendor_name | Name des Lieferanten / Rechnungsstellers |
vendor_address | Vollständige Adresse des Lieferanten |
vendor_vat_id | USt-IdNr. (z.B. DE123456789) |
vendor_tax_id | Steuernummer (z.B. 27/123/45678) |
vendor_iban | IBAN des Lieferanten |
Empfängerdaten:
| Feld | Beschreibung |
|---|---|
buyer_name | Name des Leistungsempfängers |
buyer_address | Adresse des Leistungsempfängers |
Rechnungsdaten:
| Feld | Beschreibung |
|---|---|
invoice_number | Rechnungsnummer |
invoice_date | Rechnungsdatum (YYYY-MM-DD) |
delivery_date | Liefer-/Leistungsdatum (YYYY-MM-DD) |
due_date | Fälligkeitsdatum (YYYY-MM-DD) |
total_net | Nettobetrag |
total_tax | Umsatzsteuerbetrag |
total_gross | Bruttobetrag |
currency | Währung (Standard: EUR) |
Positionen:
| Feld | Beschreibung |
|---|---|
line_items[].description | Beschreibung der Position |
line_items[].quantity | Menge |
line_items[].unit_price | Einzelpreis netto |
line_items[].tax_rate | Steuersatz als Dezimalzahl (z.B. 0.19) |
line_items[].line_total | Positionsbetrag brutto |
Sonstiges:
| Feld | Beschreibung |
|---|---|
payment_terms | Zahlungsbedingungen |
reference_text | Verwendungszweck / Referenz für die Überweisung |
Felder, die im Dokument nicht erkennbar sind, werden als null zurückgegeben. Steuersätze, die das LLM als Prozentwerte liefert (z.B. 19 statt 0.19), werden automatisch normalisiert.
Rechnungsprüfung (UStG §14)
Nach der OCR-Extraktion prüft LedgerLou automatisch, ob das Dokument die formalen Pflichtangaben nach UStG §14 enthält. Diese Angaben sind Voraussetzung für den Vorsteuerabzug.
Was geprüft wird:
| # | Regel | Bezeichnung |
|---|---|---|
| 1 | supplier_name | Name des Leistenden |
| 2 | supplier_address | Anschrift des Leistenden |
| 3 | buyer_name | Name des Leistungsempfängers |
| 4 | buyer_address | Anschrift des Leistungsempfängers |
| 5 | supplier_tax_id | Steuernummer oder USt-IdNr. |
| 6 | invoice_date | Rechnungsdatum |
| 7 | invoice_number | Rechnungsnummer |
| 8 | line_items | Menge und Art der Leistung |
| 9 | delivery_date | Zeitpunkt der Lieferung |
| 10 | net_amount | Nettobetrag |
| 11 | tax_rate_and_amount | Steuersatz und Steuerbetrag |
| 12 | gross_amount | Bruttobetrag |
Dokumenttyp-Erkennung: Nicht-Rechnungsdokumente (Angebote, Lieferscheine, Bestellbestätigungen etc.) werden als solche erkannt. Alle Prüfungen werden dann als not_applicable markiert, damit diese Dokumente nicht versehentlich als formal korrekte Rechnungen behandelt werden.
Leistungsdatum: Wenn kein explizites Leistungsdatum vorhanden ist, wird das Rechnungsdatum als Leistungsdatum angenommen (gängige BMF-Praxis). Der Checker markiert dies mit einem entsprechenden Hinweis.
Ergebnis im Dashboard: Die Spalte “Pflichtangaben” in der Inbox-Tabelle zeigt auf einen Blick:
- Grün
12/12— alle Pflichtangaben vorhanden - Gelb
10/12— Pflichtangaben fehlen - Rot mit Dokumenttyp (z.B. “Angebot”) — kein Rechnungsdokument
Hinweis: Die Rechnungsprüfung deckt die wesentlichen formalen Pflichtangaben nach UStG §14 ab und soll frühzeitig auf fehlende Felder aufmerksam machen. Sie ersetzt keine steuerliche Beratung und erhebt keinen Anspruch auf Vollständigkeit. Sonderfälle wie innergemeinschaftliche Lieferungen, Reverse-Charge-Sachverhalte (§13b UStG), Differenzbesteuerung oder branchenspezifische Zusatzanforderungen werden derzeit nicht gesondert geprüft. Im Zweifelsfall sollte die Rechnung durch einen Steuerberater beurteilt werden.
Dokumenttyp-Erkennung
Das OCR-System klassifiziert jedes eingehende Dokument in einen der folgenden Typen:
| Typ | Beschreibung |
|---|---|
invoice | Rechnung |
credit_note | Gutschrift |
order_confirmation | Bestellbestätigung |
delivery_note | Lieferschein |
quote | Angebot |
reminder | Mahnung |
receipt | Quittung |
other | Sonstiges |
Nur invoice und credit_note werden als Rechnungsdokumente behandelt und gegen die Pflichtangaben geprüft. Für alle anderen Dokumenttypen werden alle Prüfungen als not_applicable markiert.
JSON-Schema (compliance_check)
Das Ergebnis der Prüfung wird als compliance_check JSONB-Feld im Inbox-Eintrag gespeichert und ist über GET /v1/inbox, GET /v1/inbox/:id sowie die MCP-Tools list_inbox_documents und get_inbox_document abrufbar.
{
"document_type": "invoice",
"is_invoice": true,
"compliant": true,
"passed": 12,
"total": 12,
"checks": [
{
"rule": "supplier_name",
"label": "Name des Leistenden",
"status": "pass"
},
{
"rule": "delivery_date",
"label": "Zeitpunkt der Lieferung",
"status": "pass",
"detail": "Rechnungsdatum als Leistungsdatum angenommen (BMF-Praxis)"
}
]
}
Jede Prüfung hat einen von drei Status-Werten:
pass— Pflichtangabe vorhandenfail— Pflichtangabe fehltnot_applicable— Prüfung nicht anwendbar (Nicht-Rechnungsdokument)
Beispiel: Rechnung mit fehlenden Angaben
{
"document_type": "invoice",
"is_invoice": true,
"compliant": false,
"passed": 10,
"total": 12,
"checks": [
{ "rule": "supplier_name", "label": "Name des Leistenden", "status": "pass" },
{ "rule": "supplier_address", "label": "Anschrift des Leistenden", "status": "pass" },
{ "rule": "buyer_name", "label": "Name des Leistungsempfängers", "status": "fail" },
{ "rule": "buyer_address", "label": "Anschrift des Leistungsempfängers", "status": "fail" },
{ "rule": "supplier_tax_id", "label": "Steuernummer oder USt-IdNr.", "status": "pass", "detail": "USt-IdNr. vorhanden" },
{ "rule": "invoice_date", "label": "Rechnungsdatum", "status": "pass" },
{ "rule": "invoice_number", "label": "Rechnungsnummer", "status": "pass" },
{ "rule": "line_items", "label": "Menge und Art der Leistung", "status": "pass" },
{ "rule": "delivery_date", "label": "Zeitpunkt der Lieferung", "status": "pass", "detail": "Rechnungsdatum als Leistungsdatum angenommen (BMF-Praxis)" },
{ "rule": "net_amount", "label": "Nettobetrag", "status": "pass" },
{ "rule": "tax_rate_and_amount", "label": "Steuersatz und Steuerbetrag", "status": "pass" },
{ "rule": "gross_amount", "label": "Bruttobetrag", "status": "pass" }
]
}
Beispiel: Nicht-Rechnungsdokument (Angebot)
{
"document_type": "quote",
"is_invoice": false,
"compliant": false,
"passed": 0,
"total": 0,
"checks": [
{ "rule": "supplier_name", "label": "Name des Leistenden", "status": "not_applicable", "detail": "Kein Rechnungsdokument" },
{ "rule": "supplier_address", "label": "Anschrift des Leistenden", "status": "not_applicable", "detail": "Kein Rechnungsdokument" }
]
}
Lieferanten-Zuordnung
Beim Eingang eines Belegs per E-Mail versucht LedgerLou automatisch, den Lieferanten anhand der OCR-Daten einem bestehenden Kreditor zuzuordnen. Die Zuordnung erfolgt in drei Stufen:
Stufe 1 — USt-IdNr. (höchste Priorität)
Wenn die OCR eine USt-IdNr. extrahiert hat, wird nach einem Kreditor mit identischer USt-IdNr. gesucht. Treffer gelten als sicher (confidence: 1.0).
Stufe 2 — IBAN
Falls keine USt-IdNr. gefunden wurde oder kein Treffer vorliegt, wird die extrahierte IBAN gegen die IBAN-Felder der bestehenden Kreditoren abgeglichen.
Stufe 3 — Name (Fuzzy-Match)
Wenn weder USt-IdNr. noch IBAN zu einem Treffer führen, wird der extrahierte Lieferantenname gegen die bestehenden Kreditoren verglichen. Ein Treffer wird nur vorgeschlagen, wenn die Ähnlichkeit über einem Schwellenwert liegt.
Das Ergebnis wird als vendor_match im Inbox-Eintrag gespeichert:
{
"status": "matched",
"vendor_id": "9fa85f64-...",
"vendor_name": "Hetzner Online GmbH",
"confidence": 1.0,
"match_method": "vat_id"
}
Bei status: "not_found" wurde kein passender Kreditor gefunden — in diesem Fall muss vor der Buchung zuerst ein neuer Kreditor angelegt werden.
Duplikat-Erkennung
Das Kreditoren-Modul verhindert doppelte Einträge auf mehreren Ebenen:
Lieferanten
Beim Anlegen eines Kreditors per POST /v1/vendors werden geprüft:
- Name (case-insensitive, Unicode-normalisiert) — identischer Name wird abgelehnt
- USt-IdNr. — identische USt-IdNr. wird abgelehnt
- Steuernummer — identische Steuernummer wird abgelehnt
Die Fehlerantwort enthält die ID des bestehenden Kreditors, sodass ein Agent oder Nutzer direkt darauf verweisen kann.
Rechnungen
Beim Anlegen einer Eingangsrechnung per POST /v1/invoices wird die Kombination aus Kreditor-ID und Rechnungsnummer auf Eindeutigkeit geprüft. Eine doppelte Rechnungsnummer beim selben Kreditor wird abgelehnt.
Inbox-Dokumente
Beim E-Mail-Eingang wird der Content-Hash (SHA-256) jedes Dokuments berechnet. Wird dasselbe Dokument erneut empfangen (z.B. durch mehrfaches Weiterleiten), wird der Duplikat-Eintrag still übersprungen (ON CONFLICT DO NOTHING).
Status-Lebenszyklus (Rechnungen)
| Status | Bedeutung |
|---|---|
draft | Rechnung erfasst, aber noch nicht gebucht (kein Intent) |
open | Mit Journal verknüpft, vollständig offen |
partially_paid | Teilzahlung eingegangen |
paid | Vollständig bezahlt |
overdue | Offene Rechnung mit überschrittenem Fälligkeitsdatum |