Dokumentation & API
Eine schlanke REST-API für EN-16931-E-Rechnungen: erzeugen, prüfen, einbetten, auslesen. JSON rein, Ergebnis raus. Dieselbe Engine wie die Web-Oberfläche.
Standards & Konformität
| Standard | ZUGFeRD 2.x / Factur-X 1.0, wählbar über invoice.profile (Standard: en16931/Comfort) |
| Syntax | UN/CEFACT CII (Cross Industry Invoice, D16B) |
| Container | PDF/A-3 mit eingebettetem factur-x.xml (AFRelationship: Alternative); nur bei Profil xrechnung reines XML statt PDF |
| Geprüft mit | offizieller KoSIT-Validator, akzeptiert EN 16931 & XRechnung (CII + UBL) |
| Dokumentarten | Rechnung (380), Teilrechnung (326), Anzahlungsrechnung (386), Gutschrift (381), Korrektur-/Stornorechnung (384), Selbstfakturierte Rechnung (Gutschriftverfahren) (389), Abschlagsrechnung Bauleistung (875), Teilschlussrechnung Bauleistung (876), Schlussrechnung Bauleistung (877) |
Jede erzeugte Rechnung ist damit zugleich gültige ZUGFeRD-, Factur-X- und EN-16931-Datei.
invoice.profile | Wann verwenden |
|---|---|
en16931 (Standard) | Comfort: passt für praktisch jede B2B-Rechnung, wird von so gut wie jeder Software akzeptiert |
xrechnung | Pflicht bei Rechnungen an deutsche Behörden (B2G): reines XML statt PDF, zusätzlich invoice.buyer_reference, seller.email/phone, buyer.email und invoice.payment.iban erforderlich |
basic | schlankere Variante von Comfort mit Positionszeilen, aber ohne die optionalen Zusatzfelder |
basicwl | wie basic, aber ohne Positionszeilen im XML: für Pauschal-/Abo-Rechnungen |
minimum | reine Buchungsnachricht (keine Positionszeilen, keine Kontaktdaten); viele Systeme/Behörden akzeptieren das nicht als vollwertige Rechnung |
extended | größter Funktionsumfang: u. a. lines[].surcharge (Positionszuschlag) und invoice.extra_charge_* (dokumentweiter Zuschlag, z. B. Versand) |
Schnellstart
https://sichere-erechnung.decurl -X POST https://sichere-erechnung.de/v1/generate \ -H "Authorization: Bearer IHR_API_KEY" \ -H "Content-Type: application/json" \ --data-binary @rechnung.json -o rechnung.pdf
Authentifizierung
Jeder Aufruf braucht Ihren API-Key im Header, als Bearer-Token oder X-API-Key:
Authorization: Bearer IHR_API_KEY
Keys verwalten Sie im Dashboard (Erstellen/Widerrufen). Der Schlüssel wird nur als Hash gespeichert und ist nur einmalig bei der Erstellung sichtbar.
Mehrere Firmen (X-Company)
Führen Sie mehrere Absenderfirmen in einer Firmengruppe, gehört jeder API-Key einer Firma: ohne weitere Angabe entsteht alles in dieser Firma (Nummernkreis, Absender, Archiv, Forderungen). Eine andere Firma der Gruppe sprechen Sie mit der Kopfzeile X-Company an, als Wert das Kürzel, die Konto-ID oder die USt-IdNr. der Firma. Bei einem JSON-Body geht auch das Feld company auf oberster Ebene; bei /v1/automap nur neben data, weil ein JSON-Body ohne data dort selbst der Rohtext ist. Bei XML- und Datei-Uploads gilt nur die Kopfzeile.
X-Company: LTD
- Eine andere Firma als die des Schlüssels braucht das Gruppenrecht (beim Erstellen des Keys im Dashboard ankreuzen), sonst
403. Die eigene Firma darf jeder Key nennen. - Unbekannt, mehrdeutig, stillgelegt oder eine Firma einer anderen Gruppe:
422, die Anfrage läuft nie still in einer anderen Firma. Kopfzeile und Feld zugleich, aber auf verschiedene Firmen: ebenfalls422. - Abgerechnet wird über das Guthaben der Firmengruppe, das Rate-Limit gilt je Key, ein
Idempotency-Keyje angesprochener Firma. Der Key einer stillgelegten Firma antwortet mit403. - Welche Firmen ein Key ansprechen darf, liefert
GET /v1/companies(kostenlos, auch mit nur lesendem Key): je Firmaid,code,name,countryundvat_id; ohne Gruppenrecht nur die eigene. - Die USt-IdNr. bzw. Steuernummer im
sellermuss zur angesprochenen Firma passen. Gehört sie einer anderen Firma der Gruppe, antwortet die API mit422und nennt diese Firma, statt die Rechnung still in der falschen Firma zu erzeugen.
Firmenverwaltung in der Weboberfläche
Unter Firmen legen Inhaber und Team-Admins weitere Firmen an (Kürzel, Name, Land, Gesellschaftsform; bei Sitz außerhalb Deutschlands ist die Gesellschaftsform ein freies Feld), legen sie still oder aktivieren sie wieder. Jede Firma hat eigene Stammdaten, Nummernkreis, Kunden, Katalog, Archiv, Mahnwesen und Postfach; Anmeldung, Team, Tarif, Credits und KI-Schalter gelten für die ganze Gruppe. Ab zwei Firmen wechseln Sie oben in der Leiste die aktive Firma; die Konzernsicht zeigt offene Forderungen je Firma und Währung und liefert den Gesamtexport mit einem Ordner je Firma. Im Datei-Import wählt die Spalte absender die Firma je Rechnung, eingehende Rechnungen aus dem Postfach landen in der adressierten Firma.
Preis: Die erste Firma ist inklusive. Jede weitere kostet 390 Credits im Monat vom gemeinsamen Guthaben der Gruppe, gebucht zu Monatsbeginn und beim Anlegen bzw. Reaktivieren. Reicht das Guthaben nicht, bleibt die Firma aktiv und alle Belege erreichbar, es lassen sich aber keine neuen Rechnungen aus ihr erzeugen (422 mit Hinweis), bis Credits aufgeladen sind. Stillgelegte Firmen kosten ab dem Folgemonat nichts.
Freischaltung: Weitere Firmen schalten wir je Konto frei. Schreiben Sie uns an office@fhcp.de.
Endpunkte
| Methode | Pfad | Funktion |
|---|---|---|
POST | /v1/cii | JSON-Rechnung → EN-16931 CII-XML (für eigene PDF-Layouts) |
POST | /v1/generate | JSON-Rechnung → fertiges ZUGFeRD-PDF/A-3 (PDF + XML), inkl. Zahlungs-QR (GiroCode) bei EUR + IBAN und „Jetzt zahlen"-Zahlseite: die öffentliche Zahl-URL steht auf der Rechnung und kommt im Header X-Pay-Url (pro Profil abschaltbar). Die Rechnung erscheint zusätzlich in Ihrer Rechnungs-Historie/Offenen Posten (Mahnwesen nutzbar). Optional invoice.payee.name für einen abweichenden Zahlungsempfänger (BG-10, z. B. Abtretung/Factoring). Mit "seal": true zusätzlich Echtheits-Siegel: QR im PDF, verify_url im Header X-Seal-Verify-Url. Auch mit XML statt JSON: Content-Type: application/xml und eine fertige EN-16931-Rechnung im Body, als CII (ZUGFeRD/Factur-X/XRechnung) oder als XRechnung-UBL (Invoice und CreditNote; aus UBL wird bei uns CII), Optionen dann als ?seal=1&template=1; was beim Einlesen nicht übernommen werden konnte, steht im Header X-Import-Warnings. Fremd-XML ohne EN-16931-Syntax wird mit 422 abgelehnt, dafür gibt es /v1/import?ai=1 |
POST | /v1/embed | Eigenes Rechnungs-PDF (PDF/A-1b) + JSON → Factur-X-PDF/A-3, Layout bleibt. Statt invoice auch invoice_xml (EN-16931-XML als Text, CII oder UBL) oder multipart-Feld xml (Datei). Optional "seal": true → verify_url im Header (ohne Layout-Änderung) |
POST | /v1/import | Import aus Excel, CSV, ODS oder XML (CII oder XRechnung-UBL): multipart-Feld file (Endung im Dateinamen) oder die Datei als roher Body. ?mode=preview (Standard, kostenlos): erkannte Rechnungen als JSON mit Summen und Fehlern je Rechnung, nichts wird erzeugt. Tabellen enthalten eine Zeile je Position (Spalten siehe Import), eine einzelne Excel-Rechnung wird als Ganzes gelesen; ist die Struktur nicht erkennbar (oder ein XML weder CII noch UBL, Antwort dann mit kind: fremd), antwortet die Vorschau mit needs_ai: true und den fehlenden Feldern, mit ?ai=1 übernimmt die KI die Zuordnung (KI-Import-Tarif, bei Fremd-XML Beta). ?mode=generate: je Rechnung ein ZUGFeRD-PDF/A-3 zum Generate-Tarif; bei Excel oder LibreOffice (.xlsx, .xls, .ods) zusätzlich ein Umwandlungs-Aufschlag je Datei (2 Credits, auch mit Tarif, bei CSV und XML entfällt er). Optional ?template=1 (eigene Word-Vorlage, Aufschlag wie beim Erzeugen) und ?seal=1 (Echtheitssiegel je Rechnung mit IBAN, Freikontingent des Tarifs zählt). Die Vorschau nennt alles vorab in costs (base, convert, tpl, seal, total); Rechnungen ohne Vorlage oder Siegel meldet der Header X-Import-Notes. Antwort als ZIP, bei genau einer Rechnung direkt das PDF (Header X-Invoice-Number). Validierungsfehler → 422 mit Liste, es wird nichts erzeugt. Große Dateien laufen im Hintergrund: 202 mit job_id |
GET | /v1/import/{id} | Stand eines Hintergrundlaufs: status (queued, running, done, failed), total/done/failed, Fehlerliste. Kostenlos, auch mit nur-lesendem Key |
GET | /v1/import/{id}/zip | Ergebnis-ZIP eines fertigen Laufs, 7 Tage aufbewahrt. Kostenlos |
POST | /v1/automap | KI-Rechnungserstellung aus Freitext: unstrukturierte Daten (Text/E-Mail/Excel-Zeile) roh im Body oder {"data": "…"} → erkanntes Rechnungs-JSON im vollen Rechnungsschema (Referenzen, Leitweg-ID, Leistungszeitraum, Skonto, Nachlass/Zuschlag, Zahlungsempfänger, Lieferanschrift, Positionsdetails), hart gegen EN 16931 geprüft und ergänzt um Absender (Ihr Profil), bekannte Empfänger (Kundenstamm) und Preise (Katalog, Positionen mit exakt passendem Namen). Standard: JSON zurück (mapped + normalized). Mit ?generate=1 bzw. {"generate": true} kommt in einem Call direkt das fertige ZUGFeRD-PDF zurück (optional "seal"/"template" wie bei /v1/generate). Mit ?catalog=1 bzw. {"catalog": true} sieht die KI Ihren gesamten Katalog bereits beim Erkennen und trifft auch bei abweichendem Wortlaut (z. B. „Beratung" für „Erstberatung") den richtigen Katalogpreis, statt nur bei exaktem Namen nachträglich abgeglichen zu werden, kostet dafür das 3-fache. Kostet den KI-Import-Tarif, mit generate zusätzlich den Generate-Tarif, mit catalog statt des KI-Import-Tarifs dessen 3-faches. Nur mit Kunden-API-Key (nutzt Profil/Kundenstamm/Katalog) |
POST | /v1/validate | XML oder PDF → KoSIT-Prüfergebnis (konform ja/nein + Meldungen). Auch eine nicht konforme Rechnung liefert 200: das Urteil steht in valid, die Verstöße in messages. Werten Sie also valid aus, nicht den Statuscode. Gültig ist, was der Validator zur Annahme empfiehlt; Warnungen und Informationen stehen getrennt in hints. 503 nur, wenn der Validator gerade nicht läuft (dann kostenlos) |
POST | /v1/check | XML oder PDF → Eingangsprüfung: KoSIT + IBAN-Betrugsabgleich (Lieferanten-Historie, Bankwechsel, IBAN-Land, Muldenkonten-Erkennung über Lieferanten hinweg, Ihre Sperrliste) + Dublette + Sicht-/Datenebene-Konsistenz (sichtbare PDF-IBAN vs. XML) + externe Quellen (USt-IdNr. des Ausstellers via EU-VIES, Empfängerbank via Bundesbank-Bankleitzahlen, EU-Sanktionsliste, Anschrift) + Zahlbetrag (BT-115, invoice.prepaid_total und invoice.due_payable, siehe Anzahlung) → Risk-Report (grün/gelb/rot), in der Prüf-Historie gespeichert |
POST | /v1/seal | Rechnung (JSON wie /generate ODER Kernfelder) → Echtheits-Siegel (Ed25519), gibt verify_url zurück |
POST | /v1/extract | ZUGFeRD-PDF → eingebettetes XML + Kernfelder |
POST | /v1/validate/fraud | XML oder PDF → KoSIT-Prüfung plus IBAN-Betrugsabgleich gegen Ihre Lieferanten-Historie (Risiko unknown/low/high). Kleinere Variante von /v1/check ohne Dublettenprüfung und ohne Speicherung in der Prüf-Historie |
POST | /v1/diff | Zwei Rechnungen vergleichen (multipart original + corrected) → Positions-/Kopf-Diff als JSON, mit ?format=html als einbettbarer Git-Diff (rot/grün) |
GET | /v1/receivables | Offene Posten als JSON (Beträge in Cent). Query: status=open|overdue|paid|all, since=<ISO-Datum>, page, per_page; mit number=<Rechnungsnr> ein Einzelposten inkl. payments[]. Je Eintrag Zahlbetrag, Forderung nach Verrechnung, offener und überzahlter Betrag, closed_reason und die Verknüpfungen zu Anzahlungs-, Schluss- und Stornorechnungen (siehe Anzahlung). Leere Liste = HTTP 200. Kostenlos |
POST | /v1/receivables/payment | Zahlungseingang buchen (Teil-, Voll- oder Überzahlung): {"number": "R-1", "amount_cents": 11900, "value_date": "2026-09-24", "note": "Kontoauszug 42"}. Ohne value_date gilt heute, ein Datum in der Zukunft oder ein amount_cents, das keine ganze Zahl ist, ergibt 422. Eine Überzahlung wird gebucht und als overpaid_cents gemeldet; Storno- und Korrekturbelege nehmen keine Zahlung an (409). Kostenlos |
POST | /v1/receivables/paid | Offenen Rest als Ausgleich buchen: {"number": "R-1", "value_date": "2026-09-24"}. Nichts offen: 409. Kostenlos |
POST | /v1/receivables/refund | Erstattung einer Überzahlung buchen: {"number": "R-1", "amount_cents": 1000, "value_date": "2026-09-24", "note": "zurücküberwiesen"}, höchstens bis overpaid_cents, sonst 409. Kostenlos |
GET | /v1/partners | Geschäftspartner-Stammdaten als JSON (Kunden, Lieferanten, Interessenten -- die Rollen sind mehrwertig, ein Partner kann mehrere tragen). Query: q=<Suche über Name/E-Mail/USt-IdNr.>, role=customer|supplier|prospect, country=<ISO-2>, archived=1, page, per_page (max. 500); mit no=<Partnernummer> genau ein Partner (auch ein archivierter -- sonst würde Ihr System die Nummer für frei halten). Leere Liste = HTTP 200. Kostenlos |
POST | /v1/partners | Partner anlegen oder ändern, Schlüssel ist Ihre eigene partner_no (nicht unsere interne ID), verglichen ohne Unterscheidung von Groß- und Kleinschreibung und ohne Leerzeichen am Rand (k-1001 ändert K-1001, gespeichert bleibt die erste Schreibweise), dieselbe Regel wie beim CSV-Import und bei kundennummer im Rechnungsimport: {"partner_no": "K-1001", "name": "Muster GmbH", "city": "Berlin", "country": "DE", "vat_id": "DE123456789", "is_customer": true}. Weitere Felder: street, zip, tax_number, email, phone, is_supplier, is_prospect, legal_status (business|consumer|public), sepa_mandate, sepa_iban sowie die Rechnungsvorgaben payment_terms_days, skonto_days, skonto_percent, tax_scheme_override, currency, invoice_profile, leitweg_id, billing_street/zip/city/country/email, credit_limit_cents, delivery_terms (Lieferbedingungen, z. B. Incoterms) sowie das Mahnwesen je Partner: dunning_mode (auto|manual|off), dunning_tone (freundlich|neutral|bestimmt), dunning_fees ({"2": 250, "3": 250}, Cent je Mahnstufe), dunning_pauschale, dunning_damages, dunning_stage_days ({"1": 3, "2": 10, "3": 21}, Tage nach Fälligkeit), dunning_deadline_days, dunning_texts ({"1": "…"}), dunning_texts_en (englische Fassung für Rechnungen in Englisch, leer = englischer Standardtext); null bedeutet „wie Konto", die Antwort zeigt sie unter dunning, ungültige Werte geben 422. Weggelassene Felder bleiben unverändert (ein Speichern aus Ihrem Stammdaten-Modul setzt also keine Rolle zurück). 201 beim Anlegen, 200 beim Ändern. Tragen mehrere Partner dieselbe Nummer (etwa in der Oberfläche doppelt vergeben), antworten Abruf mit no=, Ändern und Archivieren mit 409, nennen die Partner in error.details und ändern nichts, bis Sie einem eine andere Nummer geben oder die Dubletten zusammenführen. Kostenlos |
POST | /v1/partners/archive | Partner archivieren: {"no": "K-1001"}. Gelöscht wird nie -- an Partnern hängen Belege (GoBD). Kostenlos |
GET | /v1/companies | Firmen Ihrer Firmengruppe als JSON: {"companies": [{"id", "code", "name", "country", "vat_id"}], "group_scope": true}. Ohne Gruppenrecht nur die Firma des Schlüssels (siehe Mehrere Firmen). Kostenlos, auch mit nur-lesendem Key |
POST | /v1/embed/token | White-Label: kurzlebiges Embed-Token minten (Formular im eigenen Design per iframe, Endkunde ohne Konto) → token + embed_url. Kostenlos |
GET | /v1 | Maschinenlesbare Endpunkt-Übersicht inkl. aktueller Credit-Kosten (kein Key nötig) |
POST | /v1/dunning | Mahnschreiben-PDF zu einer eigenen Rechnung (Forderungsmanagement): {"number": "R-1", "level": 1..3 optional} → PDF mit Forderungsaufstellung (Verzugszinsen §§ 286/288 BGB, 40-€-Pauschale, Mahnkosten), Mahnstufe wird protokolliert. Tonalität, Gebühren und Fristen kommen aus den effektiven Einstellungen (Konto, Geschäftspartner, Rechnung, siehe Mahnwesen); steht das Mahnwesen dort auf off, antwortet der Aufruf mit 422. Header X-Dunning-Level / X-Dunning-Total-Cents |
GET | /verify/{token} | Öffentliche Verifikation eines Siegels (ohne Key, ohne Credit) |
GET | /health | Bereitschaft (ohne Key, ohne Credit) |
Beispiel-Eingabe (gilt für /v1/cii und /v1/generate):
{
"invoice": { "number": "2026-0001", "issue_date": "2026-06-29",
"currency": "EUR", "payment": { "iban": "DE02..." } },
"seller": { "name": "Ihre GmbH", "street": "Weg 1", "zip": "10115",
"city": "Berlin", "country": "DE", "vat_id": "DE123456789" },
"buyer": { "name": "Kunde AG", "street": "Allee 2", "zip": "80331",
"city": "München", "country": "DE", "vat_id": "DE987654321",
"contact_name": "Erika Muster" },
"lines": [ { "name": "Beratung", "qty": 10, "unit": "Stunden",
"unit_price": 120.00, "vat_rate": 19 } ]
}?validate=1 prüft vor der Auslieferung zusätzlich gegen KoSIT. Pflichtfelder folgen EN 16931 (vollständige Anschrift von Verkäufer und Käufer, USt-IdNr. oder Steuernummer, mind. eine Position).
Idempotenz (empfohlen bei Retries): POST /v1/generate akzeptiert den Header Idempotency-Key: <Ihre ID>. Ein Wiederholungsaufruf mit demselben Schlüssel und demselben Body liefert die gespeicherte Antwort erneut (Header X-Idempotent-Replay: true), ohne die Rechnung ein zweites Mal anzulegen oder Credits erneut zu ziehen. 24 Stunden gültig; derselbe Schlüssel mit abweichendem Body → 409.
Eigene Beschriftungen der Word-Vorlage: "invoice": {"label_overrides": {"de": {"label_payment_terms": "Zahlungsbedingungen"}, "en": {"label_payment_terms": "Terms of payment"}}} ersetzt die Texte der ${label_*}-Platzhalter in der Sprache des Belegs (höchstens 80 Zeichen, ohne Angabe gelten die im Profil hinterlegten eigenen Texte, sonst der Standard). Wirkt nur in der Word-Vorlage, nicht im Standard-Layout und nicht im XML. ${label_item_discount} steht nur bei Positionen mit Rabatt; ${item_discount_text} nennt den Rabatt mit Beschriftung und ohne Vorzeichen („Rabatt 10,00 %“). ${label_item_code} beschriftet ${item_code} (Standard „Artikelnummer“), ${label_order_confirmation} ist die kurze Beschriftung zu ${seller_order_ref} (Standard „Bestätigung“).
Weitere Optionen für /v1/generate: "seal": true (Echtheits-Siegel, siehe unten) und "template": true (Rendering mit Ihrer im Profil hinterlegten Word-Vorlage/Corporate Design, Aufschlag laut Preisliste unten). Antwort-Header: X-Credits-Cost (verbrauchte Credits), X-Pay-Url (öffentliche „Jetzt zahlen"-Seite), X-Seal-Verify-Url (bei seal), X-Invoice-Template: used (Vorlage verwendet) bzw. X-Template-Warning mit dem Grund, wenn das PDF im Standard-Layout entstand. Eine Gutschrift und ein Beleg mit negativem Betrag laufen nur durch eine Vorlage mit dem Platzhalter ${payment_text} (alle ab dem 24.09.2026 erzeugten Vorlagen), sonst im Standard-Layout, der Aufschlag wird dann erstattet. Ebenso brauchen Anzahlungsrechnungen ${service_text}, Belege mit bereits bezahltem Betrag ${due_total} und Belege mit Vermerk ${advance_note} (siehe Anzahlung). Fremdwährungs-Rechnungen brauchen ${tax_total_tax_currency} (Umsatzsteuer in EUR), dazu gibt es ${tax_currency}, ${exchange_rate_text} (Kurs mit Quelle und Datum) und den Block ${fx_block}…${/fx_block}, der bei EUR entfällt.
Rechnungen mit Skonto brauchen ${skonto_text}, ${payment_terms} oder ${payment_text}: fehlt ${skonto_text}, steht der Skonto-Satz in einer eigenen Zeile unter ${payment_terms}, sonst vor ${payment_text}; fehlen alle drei, entsteht die Rechnung im Standard-Layout (Skonto ist Pflichtangabe nach § 14 Abs. 4 Nr. 7 UStG). ${item_net} ist der Positionsbetrag nach Rabatt und Zuschlag der Position, dazu gibt es ${item_gross} und ${item_discount}.
KI-Rechnung aus Freitext (ein Call, Freitext → fertiges PDF; nutzt Ihr Profil, Kundenstamm und Katalog):
curl -X POST "https://sichere-erechnung.de/v1/automap?generate=1" \
-H "Authorization: Bearer IHR_API_KEY" -H "Content-Type: application/json" \
-d '{"data": "Rechnung 2026-0007 an Muster AG, München: 10 Std Beratung a 120 EUR, 19% USt", "seal": true}' \
-o rechnung.pdf
# Ohne generate: nur das erkannte JSON zurück (mapped + normalized), zum Vorbefüllen eigener Masken:
curl -X POST "https://sichere-erechnung.de/v1/automap" -H "Authorization: Bearer IHR_API_KEY" \
-d 'Kunde Muster AG, München; 10 Std Beratung je 120 EUR; RgNr 2026-0007'Erkennt die KI zu wenig für eine valide Rechnung, kommt bei generate kein PDF, sondern 422 mit den fehlenden Feldern (dann nur der KI-Import-Tarif, kein Generate-Tarif).
Weitere Felder & Stornorechnung
seller.tax_number | Steuernummer als Alternative zur seller.vat_id (USt-IdNr.) |
buyer.vat_id | USt-IdNr. des Käufers (BT-48): bei invoice.tax_scheme: reverse_charge oder innergemeinschaftlich erforderlich (siehe unten) |
invoice.due_date | Fälligkeitsdatum (BT-9); ohne Angabe steht auf der Rechnung „zahlbar sofort ohne Abzug" |
invoice.delivery_date | Leistungsdatum (BT-72); Standard = issue_date, wird bei gesetztem period_start/period_end nicht angezeigt. Bei Anzahlungs- und Abschlagsrechnungen (386, 875) steht kein Leistungsdatum im XML, sondern der voraussichtliche Zeitpunkt (invoice.expected_delivery_from, siehe Anzahlung) |
buyer.iban / buyer.bic | Bankverbindung des Kunden. Bei einer Gutschrift (invoice.type_code 381) ist das das Erstattungskonto (BT-84); eine mitgeschickte invoice.payment.iban wird bei 381 nicht verwendet. Ohne Kunden-IBAN erhält die Gutschrift den Zahlungscode 97 (Verrechnung) mit Hinweistext, keinen GiroCode und keinen Zahllink. Gutschriften erscheinen nicht in offenen Posten, Forderungs-API, Cockpit und Mahnwesen; Umsatzsummen ziehen sie ab. Im Import: Spalte kunde_iban, leer = aus der Partnerakte. |
invoice.buyer_reference | Leitweg-ID (BT-10): bei Profil xrechnung erforderlich, sonst optional |
lines[].net | expliziter Netto-Zeilenbetrag statt unit_price×qty (überschreibt die Berechnung, z. B. bei krummen Pauschalen) |
lines[].surcharge | Positionszuschlag (BG-28, absoluter Betrag), Gegenstück zu discount; nur sinnvoll bei Profil extended |
invoice.extra_charge_amount / _reason / _vat_rate | dokumentweiter Zuschlag (BG-21, z. B. Versandkosten) mit eigenem Steuersatz, unabhängig von den Positionen; _reason ist Pflicht sobald _amount > 0; nur sinnvoll bei Profil extended |
seller.rechtsform | Gesellschaftsform (z. B. „GmbH"), wird an den Firmennamen angehängt statt ihn zu ersetzen |
seller.register_court / register_number | Registergericht + Registernummer (BT-30, z. B. „HRB 12345"), Pflichtangabe auf Geschäftsbriefen für GmbH/UG/AG/e. K. u. a. (§ 35a GmbHG, § 37a HGB, § 80 AktG) |
seller.managing_directors | Geschäftsführung/Vorstand als Freitext (BT-33, zusammen mit dem Registergericht) |
seller.trading_name | Handelsname, falls abweichend von der Firma (BT-28) |
seller.website / seller.logo | optionales Branding fürs PDF-Layout; logo nur als eingebettetes Bild (data:image/png;base64,…, ebenso jpeg, gif, webp), ein Dateipfad wird verworfen |
invoice.header_text | Einleitungstext (BT-22) |
invoice.footer | Fußzeile (z. B. Geschäftsführer/HRB/Steuerhinweise) |
invoice.reference | Vertrags-/Kundenreferenz (BT-12) |
invoice.payment_terms | Zahlungsbedingungen als Text (BT-20, höchstens 2.000 Zeichen): stehen vorn in der Zahlungsbedingung des XML, Skonto-Angaben folgen unverändert; ohne Fälligkeit ersetzen sie den Standardsatz „Zahlbar sofort“. Ohne Angabe gelten die Zahlungsbedingungen aus Ihrem Profil in der Belegsprache (invoice.language, englischer Text bei en, sonst der deutsche). Erscheinen im Standard-Layout und in der Word-Vorlage als ${payment_terms} |
invoice.skonto_pdf_hide | true: Skonto (skonto_days/skonto_percent) steht nur strukturiert im XML (BT-20), das PDF (Standard-Layout und Word-Vorlage) hängt keinen eigenen Skonto-Satz an; für Zahlungsbedingungen, die das Skonto schon nennen. Ohne Angabe gilt die Einstellung im Profil. Nennt invoice.payment_terms den Skonto-Satz nicht erkennbar, kommt ein Hinweis (Skonto ist Pflichtangabe, § 14 Abs. 4 Nr. 7 UStG) |
invoice.delivery_terms | Lieferbedingungen, z. B. Incoterms "FCA Clausthal-Zellerfeld (Incoterms 2020)" (höchstens 300 Zeichen). EN 16931 hat dafür kein eigenes Feld: im XML als Notiz (BT-22) mit Betreff AAR (Lieferbedingungen), im PDF im Kopf und in der Word-Vorlage als ${delivery_terms}. Vorgabe je Geschäftspartner über delivery_terms in /v1/partners (wirkt in der Rechnungsmaske und im Import) |
invoice.our_reference | „Unser Zeichen“, z. B. das Kürzel des Sachbearbeiters (höchstens 60 Zeichen); nur im PDF und in der Word-Vorlage (${our_reference}), nicht im XML |
invoice.payment.{iban,bic,bank} | Bankverbindung; bic (BT-86, 8 oder 11 Zeichen) wird ins XML geschrieben und, wenn die IBAN die Ihres Profils ist, aus dem Profil ergänzt |
invoice.payment.bank_account | Optional: eine Ihrer im Profil hinterlegten Bankverbindungen der Firma, als ID oder Bezeichnung (z. B. "USD-Konto"). Füllt leere Felder bank, iban und bic; mitgeschickte Werte gewinnen. Unbekannte Verbindung: 422 |
invoice.payment.reference | Verwendungszweck (BT-83); ohne Angabe die Rechnungsnummer, damit Zahlungseingang und Rechnung auch beim Bankabgleich zusammenfinden |
invoice.allowance (alter Name: skonto) | Nachlass: unbedingter, dokumentweiter Abzug auf die gesamte Rechnung (mindert Rechnungsbetrag und Steuerbasis sofort). invoice.skonto wird als veralteter Alias weiter angenommen (unverändertes Verhalten); das ist kein echtes Skonto, sondern dieser Nachlass, der Name war bis 17.09.2026 irreführend. |
invoice.allowance_percent / allowance_reason | Nachlass in Prozent auf die Summe der Positionen netto (statt allowance, nicht beides). Der Betrag wird kaufmännisch auf Cent gerundet und steht im XML mit Prozentsatz (BT-94) und Basis (BT-93); allowance_reason ist der Grund (BT-97, ohne Angabe „Nachlass“, bei Belegsprache en „Allowance“). Bei mehreren Steuersätzen wird jeder Nachlass anteilig verteilt. In der Word-Vorlage: ${discount_amount}, ${discount_reason} und ${discount_percent} (Prozentsatz, leer bei einem Betrag). |
invoice.allowance2 / allowance2_percent / allowance2_reason | Zweiter Nachlass auf derselben Rechnung, als Betrag oder Prozentsatz, mit eigenem Grund; im XML ein eigener Abschlag (BG-20), auf dem Beleg eine eigene Zeile. In der Word-Vorlage: ${discount2_amount}, ${discount2_reason} und ${discount2_percent}, leer ohne zweiten Nachlass. |
invoice.skonto_days / skonto_percent (optional zweite Stufe: skonto2_days/skonto2_percent) | Echtes Skonto (BT-20): bedingter Zahlungsanreiz: die Rechnung bleibt auf dem vollen Betrag stehen, die Summen ändern sich NICHT. Setzt invoice.due_date voraus. Tage 1–90, Prozent 0,01–20. Erscheint als Text bei den Zahlungsbedingungen plus der XRechnung-Syntax #SKONTO#TAGE=n#PROZENT=n.nn# (BR-DE-18, gilt für alle Profile) und auf dem PDF als eigener Hinweis mit Datum und Betrag. |
invoice.tax_currency / exchange_rate | Fremdwährung (§ 14 Abs. 4 Nr. 8 UStG): rechnet ein Aussteller mit Sitz in Deutschland in einer anderen Währung als tax_currency ab (Standard EUR), muss die Umsatzsteuer zusätzlich in tax_currency ausgewiesen werden (BT-6/BT-111). Dafür braucht es exchange_rate (1 invoice.currency = x tax_currency). Fehlt er bei Steuerwährung EUR, setzt die API den amtlichen EZB-Kurs zum Leistungsdatum (sonst Ende des Leistungszeitraums, sonst Rechnungsdatum) nach der Kursart im Profil ein, Tageskurs oder Monatsdurchschnitt (= Umsatzsteuer-Umrechnungskurs des BMF nach § 16 Abs. 6 UStG), und meldet das in X-Invoice-Hints. Ein mitgeschickter Kurs hat immer Vorrang. Ist kein Kurs ermittelbar (Währung ohne EZB-Notierung, Quelle nicht erreichbar), antwortet die API mit 422 und bittet um den Kurs. |
invoice.exchange_rate_source / exchange_rate_date | Herkunft des Kurses für den Nachweis (GoBD), optional: ezb (EZB-Referenzkurs eines Tages), ezb_monat (Monatsdurchschnitt der EZB-Referenzkurse, entspricht dem Umsatzsteuer-Umrechnungskurs des BMF) oder manuell, dazu das Kursdatum (JJJJ-MM-TT, beim Monatsdurchschnitt der Monatserste). Bei automatisch gesetztem Kurs gefüllt; steht auf dem PDF in der Kurszeile, nicht im XML. |
invoice.project_ref / project_name | Projektnummer (BT-11) und optionaler Projektname; nur bei en16931/xrechnung/extended im XML |
invoice.seller_order_ref | Ihre Auftrags-/Auftragsbestätigungsnummer (BT-14); Gegenstück zur Bestellnummer des Käufers order_ref; nur ab en16931 |
seller.street2 / buyer.street2 | Adresszusatz (BT-36/BT-51, z. B. Gebäude, Postfach) |
seller.state / buyer.state | Bundesland/Region (BT-39/BT-54) |
lines[].item_id / lines[].buyer_item_id | Artikelnummer des Verkäufers (BT-155) bzw. des Käufers (BT-156); nur ab en16931 |
lines[].gtin | GTIN/EAN (BT-157, 8/12/13/14 Ziffern, Prüfziffer wird geprüft), im XML als GlobalID schemeID="0160" |
lines[].list_price / lines[].price_discount | Listenpreis (BT-148) und Preisnachlass je Einheit (BT-147). unit_price muss dann gleich Listenpreis − Nachlass sein oder darf weggelassen werden (wird berechnet); ein Widerspruch wird als 422 abgelehnt, weil EN 16931 diese Rechnung nicht selbst prüft |
lines[].price_base_qty | Preisbasismenge (BT-149), z. B. 100 für „Preis je 100 Stück"; Zeilenbetrag = Menge × Preis ÷ Basismenge |
lines[].origin_country | Ursprungsland der Ware (BT-159, ISO-Code); nur ab en16931 |
lines[].note | Anmerkung zur Position (BT-127), erscheint auch auf dem PDF |
lines[].unit | Mengeneinheit (BT-130) als UN/ECE-Rec.-20-Code oder deutsches Wort; unten die Liste der bekannten Codes |
lines[].discount / lines[].discount_percent | Rabatt je Position (absoluter Betrag bzw. Prozent; EN-16931-Positionsabschlag) |
invoice.tax_scheme | standard · kleinunternehmer (§19) · reverse_charge (§13b, USt-IdNr. Käufer nötig) · innergemeinschaftlich (USt-IdNr. Käufer nötig) · steuerfrei (§4, Grund in invoice.tax_exemption_reason) · ausfuhr (Kategorie G, § 4 Nr. 1a UStG, Ausfuhr in ein Drittland, USt-IdNr. Verkäufer nötig) · nullsatz (Kategorie Z, 0 % USt, USt-IdNr. oder Steuernummer Verkäufer nötig) · nicht_steuerbar (Kategorie O, Leistungsort im Ausland § 3a UStG, nicht mit Profil xrechnung kombinierbar, BR-DE-14 vs. BR-O-05, s. Fehlercode-Hinweis unten).Wichtig: Bei jeder Regelung außer standard wird lines[].vat_rate (und invoice.extra_charge_vat_rate) ignoriert und auf 0 gesetzt, in XML, PDF und Summen. Ein mitgeschickter Satz wie 19 ändert daran nichts und führt nicht zu einem Fehler.Weglassen erlaubt: Ohne invoice.tax_scheme gilt die im Profil hinterlegte Voreinstellung Ihres Kontos (Standard, wenn dort nichts gesetzt ist). Als Kleinunternehmer stellen Sie die Regelung also einmal im Profil ein, statt sie bei jedem Aufruf mitzusenden; ein mitgesendeter Wert, auch "standard", gewinnt immer.Auslandsrechnungen (seit 01.10.2026): Ein Verkäufer in Deutschland mit standard und mindestens einer Position mit 0 % an einen Käufer in einem anderen Land wird mit 422 abgelehnt, weil sonst stillschweigend die Kategorie Z (Nullsatz) entstünde. Bitte innergemeinschaftlich, reverse_charge, ausfuhr oder nicht_steuerbar senden; einen echten Nullsatz nullsatz ausdrücklich. |
invoice.period_start/period_end | Leistungszeitraum von/bis (BG-14), erscheint statt des Leistungsdatums; bei 386 und 875 wird er zum voraussichtlichen Leistungszeitraum |
invoice.order_ref / delivery_note / accounting_ref | Bestellnummer des Käufers (BT-13) · Lieferschein (BT-16) · Kontierung/Kostenstelle (BT-19) |
invoice.prepaid / rounding | bereits bezahlter Betrag ohne Anzahlungsrechnung (BT-113) und Rundung (BT-114), der Zahlbetrag (BT-115) reduziert sich entsprechend. Anzahlungsrechnungen ziehen Sie mit invoice.deductions ab (Schlussrechnung) |
invoice.extra_bank | Optional: weitere Bankverbindung {"iban", "bic", "bank", "label"}, zum Beispiel ein Konto für Kunden im Ausland. Ohne Angabe setzt sie die Firma selbst ein, wenn eine ihrer Bankverbindungen für das Land des Kunden hinterlegt ist (Profil, „Zusätzlich anzeigen bei Kunden in"). Sie erscheint im PDF, im XML als zweite Überweisungsverbindung (BG-17, EN 16931 erlaubt 0..n: eine weitere ram:SpecifiedTradeSettlementPaymentMeans nach der Hauptverbindung mit demselben TypeCode 58, IBAN BT-84, ab EN 16931 auch Kontoname BT-85 aus label und BIC BT-86; BASIC und BASIC WL nur mit IBAN, MINIMUM ohne Zahlungsangaben), auf der Zahlseite mit eigenem GiroCode und im Echtheits-Siegel. Nicht bei Gutschrift und Lastschrift. Ungültige IBAN: 422. Beim Einlesen eines XML wird die zweite Überweisungsverbindung zu invoice.extra_bank |
invoice.payment.method | transfer (Default) oder direct_debit (SEPA-Lastschrift; dann payment.iban = zu belastendes Kundenkonto, plus payment.mandate BT-89 und payment.creditor_id BT-90) |
invoice.attachments[] | rechnungsbegründende Anlagen (BG-24): {name, mime: "application/pdf", data: base64}, max. 5, je 1 MB, Aufschlag je Anlage (Standard 1 Credit) |
invoice.payee.name | abweichender Zahlungsempfänger (BG-10, z. B. Abtretung/Factoring) |
buyer.contact_name · buyer.email · buyer.phone | Ansprechpartner des Käufers (BG-9): Name (BT-56, erscheint als „z. Hd." auf der Rechnung), E-Mail (BT-58), Telefon (BT-57) |
buyer.partner_no | Ihre Kundennummer für diesen Kunden (z. B. "K-1001", höchstens 64 Zeichen). Im XML als Kennung des Käufers BT-46 (ram:BuyerTradeParty/ram:ID, nicht bei MINIMUM), im PDF im Kopf („Kundennummer"), in der Word-Vorlage als ${customer_no}. Die Rechnungsmaske belegt sie aus dem Geschäftspartner vor; die Nachbearbeitung ordnet die Rechnung damit dem Geschäftspartner zu. Im Import: Spalte kundennummer |
seller.contact_name · seller.email · seller.phone | Ansprechpartner des Verkäufers (BG-6): Name (BT-41), E-Mail (BT-43), Telefon (BT-42) |
invoice.type_code | 380 Rechnung · 326 Teilrechnung (ausgeführte Teilleistung) · 386 Anzahlungsrechnung · 381 Gutschrift · 384 Stornorechnung · 389 Gutschriftverfahren · 875 Abschlagsrechnung Bauleistung · 876 Teilschlussrechnung Bauleistung · 877 Schlussrechnung Bauleistung. Bei XRechnung wird eine 386 als 380 mit dem Vermerk „Anzahlungsrechnung:“ geschrieben (BR-DE-17 ist nur eine Warnung), und eine 384 verlangt invoice.reference_invoice (BR-DE-26, § 31 Abs. 5 Satz 2 UStDV); in den anderen Profilen gibt es dazu nur einen Hinweis. Anzahlung, Teil- und Schlussrechnung: siehe unten. |
invoice.language | Belegsprache: de (Standard) oder en. Sie gilt für das PDF, die Word-Vorlage und die festen Texte im XML. Bei en stehen auf Englisch: die Sätze der Zahlungsbedingung samt Skonto-Satz (BT-20), der Grund der Steuerbefreiung (BT-120), die Gründe für Rabatt, Zuschlag und Nachlass (BT-139, BT-144, BT-97), die Vermerke zu Anzahlung, Restrechnung, weiteren Bezügen und Echtheits-Siegel (BT-22), die Pflichtangaben des Verkäufers (BT-33), der Satz der Gutschrift (BT-82) und die Abzugszeilen früherer Anzahlungen. Codes (z. B. VATEX, #SKONTO#-Zeilen, Einheiten), Namen und Ihre eigenen Texte (Kopf- und Fußtext, Positionsbezeichnungen, Lieferbedingungen, eigener Befreiungs- oder Nachlassgrund, eigene Zahlungsbedingungen) bleiben unverändert. Ohne Angabe oder bei de ist alles deutsch wie bisher, auch das XML. Ein anderer Wert wird mit 422 abgelehnt. Bei Geschäftspartnern lässt sich die Sprache als invoice_language hinterlegen (/v1/partners), im Rechnungsimport als Spalte sprache. |
invoice.reference_invoice | Bezug auf die Originalrechnung (BT-25) als Text, als Liste oder als Objekt {number, issue_date}; weitere Bezüge in invoice.references[], Datum in invoice.reference_issue_date (BT-26) |
Stornorechnung erzeugen Sie rein über die API: type_code: "384", reference_invoice auf die Originalnummer setzen und die Positionsmengen/-beträge negativ angeben. Genau das negierte Brutto eines eigenen Belegs gilt als Storno und schließt ihn in den Offenen Posten; der Storno einer Schlussrechnung hebt ihre Anrechnungen auf (Anzahlung):
{
"invoice": { "number": "STORNO-2026-0001", "issue_date": "2026-07-01",
"type_code": "384", "reference_invoice": "2026-0001" },
"seller": { … }, "buyer": { … },
"lines": [ { "name": "Beratung", "qty": -10, "unit": "HUR",
"unit_price": 120.00, "vat_rate": 19 } ]
}Mengeneinheiten (BT-130)
Codes nach UN/ECE Recommendation 20 (BR-CL-23). Sie können den Code oder das deutsche Wort senden; unbekannte Codes reichen wir unverändert durch.
| Code | Bedeutung |
|---|---|
C62 | Einheiten |
H87 | Stück |
EA | Stück (each) |
PCE | Stück (piece) |
NAR | Anzahl Artikel |
PR | Paar |
SET | Set |
LS | Pauschale |
P1 | Prozent |
E48 | Leistungseinheit (service unit) |
E49 | Arbeitstag |
NPR | Anzahl Paare |
MIN | Minuten |
HUR | Stunden |
DAY | Tage |
WEE | Wochen |
MON | Monate |
ANN | Jahre |
SEC | Sekunden |
QAN | Quartale |
MGM | Milligramm |
GRM | Gramm |
KGM | Kilogramm |
TNE | Tonnen |
MLT | Milliliter |
LTR | Liter |
HLT | Hektoliter |
MTQ | Kubikmeter |
CMQ | Kubikzentimeter |
MMT | Millimeter |
CMT | Zentimeter |
MTR | Meter |
KMT | Kilometer |
MTK | Quadratmeter |
CMK | Quadratzentimeter |
MMK | Quadratmillimeter |
HAR | Hektar |
KWH | Kilowattstunden |
MWH | Megawattstunden |
KWT | Kilowatt |
WHR | Wattstunden |
XPK | Paket |
XPP | Stück unverpackt |
XBX | Box |
XCT | Karton |
XPA | Päckchen |
XBG | Beutel |
XRO | Rolle |
XBO | Flasche |
XCA | Dose |
XTU | Tube |
XPX | Palette |
XCS | Kiste |
XCR | Kasten |
XSA | Sack |
XCY | Zylinder |
XBJ | Eimer |
KMH | Kilometer pro Stunde |
D64 | Kalendertage |
DZN | Dutzend |
KT | Bausatz (kit) |
Echtheits-Siegel & öffentliche Verifikation
Ein Echtheits-Siegel bindet die Kernfelder (Aussteller, Nummer, Datum, Betrag, IBAN) kryptografisch an eine Ed25519-Signatur. Ihr Kunde scannt den QR-Code bzw. öffnet den Link und sieht sofort: echt, unverändert, richtige IBAN. Das schützt Ihre Kunden vor gefälschten „Rechnungen von Ihnen" mit fremder Bankverbindung.
- Beim Erzeugen:
/v1/generatemit"seal": true→ der QR wird direkt ins ZUGFeRD-PDF eingebettet, dieverify_urlkommt im HeaderX-Seal-Verify-Url(+2 Credits, Kunden-Key, IBAN erforderlich). - Eigenes PDF:
/v1/embedmit"seal": true→ Siegel wird erzeugt,verify_urlim Header; das Kundenlayout bleibt unverändert (QR selbst platzieren). - Nur Siegel:
/v1/seal(JSON wie /generate oder Kernfelder) → gibtverify_urlund Token zurück, ohne PDF. Bei Kernfeldern optionaltype_code(Belegart, z. B.381für eine Gutschrift): die Prüfseite nennt dann die Belegart und bei einer Gutschrift die IBAN als Erstattungskonto des Kunden, ohne Angabe spricht sie neutral von einem Beleg. - Mehrere Bankverbindungen: Trägt die Rechnung eine weitere Bankverbindung (
invoice.extra_bank), bestätigt das Siegel alle IBANs, die Prüfseite zeigt sie unter „Bestätigte Bankverbindungen" mit Bezeichnung und Bankland./v1/sealantwortet zusätzlich mitfields.extra_ibans([{"iban", "label"}], leer ohne); bei Kernfeldern optionalextra_ibansals Liste von IBANs oder{"iban", "label"}. Die bisherigen Felder und alle älteren Siegel bleiben unverändert gültig. - Prüfen:
GET /verify/{token}, öffentlich, ohne Key, ohne Credit. Status:valid,revoked,tampered,notfound. - Aussteller, USt-IdNr. und IBAN sind die Ihrer Firma:
/v1/sealübernimmt sie aus Ihrem Profil und den Bankverbindungen. Fehlende Angaben werden ergänzt, abweichende mit422abgelehnt (bei einer Gutschrift oder Lastschrift ist die IBAN das Konto des Kunden und wird nicht geprüft). Die Währung ist ein dreistelliger Code, z. B.EUR. Das eingebettete White-Label-Formular nimmt Bankverbindung und Absender immer aus dem Profil des Token-Inhabers, nie aus der Anfrage. - White-Label: Die Verify-Seite trägt Logo und Namen des Ausstellers (aus dessen Profil).
- Widerruf: Nach Storno/Korrektur im Dashboard widerrufen, die Verify-Seite zeigt dann „widerrufen".
curl -X POST https://sichere-erechnung.de/v1/generate \
-H "Authorization: Bearer IHR_API_KEY" -H "Content-Type: application/json" \
-d '{"seal":true,"invoice":{…},"seller":{…},"buyer":{…},"lines":[…]}'
# Antwort: ZUGFeRD-PDF mit QR · Header: X-Seal-Verify-Url: https://sichere-erechnung.de/verify/AbC123…In Ihre Software einbinden
Jede Sprache mit HTTP genügt, Buchhaltung, ERP, Online-Shop oder eigenes Tool. Zwei Beispiele:
$ch = curl_init("https://sichere-erechnung.de/v1/cii");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer $key", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode($rechnung),
CURLOPT_RETURNTRANSFER => true,
]);
$xml = curl_exec($ch); // fertiges EN-16931-CII-XMLimport requests
r = requests.post("https://sichere-erechnung.de/v1/generate",
headers={"Authorization": f"Bearer {key}"},
json=rechnung)
open("rechnung.pdf", "wb").write(r.content)Typischer Ablauf in einer Buchhaltung/ERP: bei „Rechnung finalisieren" die Rechnungsdaten an /v1/generate senden und das zurückgelieferte ZUGFeRD-PDF speichern/versenden. Eingehende Lieferantenrechnungen vor der Verbuchung über /v1/validate prüfen.
Abrechnung & Limits
- Credits je Aufruf:
/v1/cii,/v1/generate,/v1/embed,/v1/validate,/v1/extract,/v1/diff,/v1/dunning= 1;/v1/check(Eingangsprüfung) = 2;/v1/seal(Echtheits-Siegel) = 2;/v1/validate/fraud= 3;/v1/automap(KI-Import) = 10. - Aufschläge bei
/v1/generate:"template": true(eigene Word-Vorlage) +2, je eingebetteter Anlage +1,"seal": true+2. - Aufschlag bei
/v1/automap:"catalog": true(Katalog bereits in der KI-Erkennung statt nur in der Nachbearbeitung) → 30 statt 10 Credits (3-fach, mehr Token je Aufruf). - Kostenlos (aber Key + Rate-Limit):
/v1/receivables,/v1/receivables/payment,/v1/receivables/paid,/v1/receivables/refund,/v1/partners,/v1/partners/archive,/v1/companies,/v1/embed/token,GET /v1. Ohne Key kostenlos:/verify/{token}und/health. - Guthaben leer →
402 Payment Required(Credits im Shop nachkaufen). - Rate-Limit: 60 Anfragen/Minute pro Key; bei Überschreitung
429mitRetry-After. Jede Antwort trägtX-RateLimit-Remaining. - Sie zahlen nur für ein ausgeliefertes Ergebnis: Wird ein Aufruf abgelehnt, ob durch einen Serverfehler (
5xx) oder weil die Daten nicht EN-16931-konform sind (422), erstatten wir die verbrauchten Credits automatisch, inklusive etwaiger Aufschläge. Ablehnungen wegen fehlendem Guthaben, Rate-Limit oder doppelter Rechnungsnummer kosten ohnehin nichts. Umgekehrt gilt: Ein Prüfergebnis „nicht konform" ist ein Ergebnis und wird berechnet, dafür haben Sie die Prüfung schließlich beauftragt (sie kommt als200mitvalid: false).
Fehlercodes
| Code | Bedeutung |
|---|---|
401 | Kein/ungültiger API-Key |
402 | Kein Guthaben, Credits nachkaufen |
403 | E-Mail noch nicht bestätigt, nur-lesender Key für einen schreibenden Aufruf, X-Company ohne Gruppenrecht oder Firma stillgelegt |
422 | Eingabe unbrauchbar bzw. daraus lässt sich keine konforme Rechnung erzeugen (Details in der Antwort). Nicht der Fall „geprüft, Ergebnis negativ", der kommt als 200 mit valid: false |
429 | Rate-Limit erreicht |
Schutz & Korrekturen
Eingangsprüfung (POST /v1/check, 2 Credits): die umfassende Prüfung einer eingegangenen Rechnung (PDF oder XML) in einem Aufruf, KoSIT-Validierung + IBAN-Betrugsabgleich (Lieferanten-Historie) + Dublettencheck. Antwort ist ein einheitlicher Risk-Report mit risk: green|yellow|red und einer Liste von findings (je type, level: red|yellow|info|green, message; info ist ein Hinweis ohne Risiko-Wirkung). Zusätzlich zu KoSIT, IBAN-Historie, Sperrliste, IBAN-Tresor, Factoring-Erkennung, Muldenkonto, IBAN-Land und Dublette erkennt die Prüfung Betrugsmuster aus Ihren eigenen Daten, ohne externe Abfragen: Zahlungsdruck (pressure, rot: neue oder geänderte IBAN + Fälligkeit ≤ 7 Tage + erste Rechnung des Lieferanten bzw. erste seit 90 Tagen), Betragsplausibilität (amount: ≥ 3-facher Median der letzten 12 Monate gelb, glatte Tausenderbeträge ab 5.000 € info, Beträge innerhalb 2 % unter den üblichen Freigabegrenzen 1.000/5.000/10.000/25.000 € gelb), Doppelrechnung mit neuer Nummer (duplicate_new_number, gelb: gleicher Lieferant, Betrag und IBAN innerhalb 30 Tagen, aber andere Rechnungsnummer; die nummerngleiche Dublette meldet weiterhin duplicate; beide können gleichzeitig auftreten und meinen dann zwei verschiedene Vorrechnungen), PDF-Forensik (consistency, rot: sichtbare IBAN, Betrag, Rechnungsnummer, Fälligkeit oder Aussteller widersprechen dem XML; pdf_meta: Erzeuger ist Textverarbeitung/Online-Editor info, nachträglich bearbeitet gelb, Erstelldatum > 30 Tage vom Rechnungsdatum entfernt gelb) und bei Eingang über das Postfach die Absender-Prüfung (sender: Lookalike-Domain zu einer bekannten Domain des Lieferanten rot, neue Domain gelb, Reply-To ≠ From gelb, SPF/DKIM-Fehlschlag gelb; die erste Domain je Lieferant wird als Referenz gespeichert). Mehrere Firmen: Die Prüfung kennt alle Firmen Ihrer Gruppe. Ist die Rechnung an eine andere Ihrer Firmen adressiert, enthält der Report company: {"status": "sister", "name"} und den Befund recipient (gelb, hier nicht zahlbar); prüfen Sie sie dann mit der Kopfzeile X-Company in dieser Firma. Passt der Empfänger zu mehreren Ihrer Firmen, meldet der Report company: {"status": "open", "candidates": [{"name"}]} und den Befund empfaenger_firma (gelb); die Rechnung ist bis zur Zuordnung nicht zahlbar. Ein API-Key mit Gruppenrecht erhält zu jeder Firma zusätzlich id und code (Kürzel). Die Sperrliste gilt für alle Firmen der Gruppe. Konten ohne weitere Firmen erhalten kein Feld company. Jede Prüfung wird in der Prüf-Historie gespeichert (in der Weboberfläche unter Geprüfte Rechnungen einsehbar). Geprüfte Rechnungen lassen sich dort zur Zahlung vormerken und als SEPA-Sammelüberweisung (pain.001) exportieren, die Datei laden Sie in Ihrem Online-Banking hoch (kein Geldfluss über uns, die Empfänger-IBANs sind bereits geprüft). Über den IBAN-Tresor geben Sie vertrauenswürdige Lieferanten-Bankverbindungen frei oder sperren sie, eine gesperrte IBAN löst bei jeder Prüfung eine rote Warnung aus. Es wird keine Klar-IBAN gespeichert (HMAC-Hash).
Externe Quellen in der Eingangsprüfung (kostenlos, ohne Anmeldung, jeweils als eigener findings-Eintrag): vies: USt-IdNr. des Ausstellers gegen EU-VIES (ungültig = rot; liefert VIES den Firmennamen, wird er mit der Rechnung abgeglichen, Abweichung = gelb; DE liefert keinen Namen). bank: bei deutschen IBANs die Bankleitzahl gegen die Bankleitzahlendatei der Deutschen Bundesbank (BLZ existiert nicht = rot; Institut mit Sofort-Kontoeröffnung wie N26/Solaris/Revolut = gelb mit Begründung). sanctions: Ausstellername gegen die konsolidierte EU-Finanzsanktionsliste (exakter Treffer = rot, enger Treffer = gelb; keine Treffer auf Namen unter 5 Zeichen). address: Anschrift des Ausstellers (DE/AT) über unseren Adressdienst (nicht auffindbar oder PLZ/Ort passen nicht = gelb). Ist eine Quelle gerade nicht erreichbar, kommt level: info („Prüfung nicht möglich"); die Prüfung bricht nie ab und info beeinflusst das Gesamtrisiko nicht. VIES-Antworten werden 24 h gecacht, Bundesbank- und Sanktionsliste hält der Worker aktuell.
Team & Vier-Augen-Freigabe: Unter Team laden Sie weitere Nutzer in Ihr Konto ein (Rollen Admin/Member; gemeinsames Guthaben, gemeinsame Daten und Prüf-Historie). Sobald mindestens zwei Personen im Team sind, greift im IBAN-Tresor automatisch das Vier-Augen-Prinzip: eine Freigabe wird angefordert und muss von einer zweiten Person bestätigt werden. Abrechnung, API-Keys und Konto-Löschung bleiben Inhabern und Admins vorbehalten.
USt-IdNr-Überwachung & Alarme: Unter USt-IdNr-Prüfung überwachen wir hinterlegte USt-IdNrn Ihrer Kunden regelmäßig automatisch über EU-VIES und melden per Alarm (Dashboard + E-Mail), sobald eine zuvor gültige Nummer ungültig wird, wichtig für Reverse-Charge und Steuerfreiheit.
Postfach-Anbindung (automatische Eingangsprüfung): Im Profil (Abschnitt Postfach) verbinden Sie ein E-Mail-Postfach per IMAP (nur Lesezugriff, Passwort verschlüsselt). Wir holen daraus Eingangsrechnungen automatisch, prüfen sie wie oben einschließlich des Mail-Absenders (Domain-Historie je Lieferant, Lookalike-Domains, Reply-To, SPF/DKIM aus den Kopfzeilen, ohne Netzabfrage) und warnen bei Auffälligkeit per Alarm, ohne manuelles Hochladen.
IBAN-Betrugsschutz (POST /v1/validate/fraud, 3 Credits): prüft eine eingegangene Rechnung gegen KoSIT und gleicht die Kontoverbindung des Ausstellers mit Ihrer Lieferanten-Historie ab. Antwort enthält fraud_risk: high|low|unknown + Warnmeldung. Es wird keine Klar-IBAN gespeichert (HMAC-Hash). Erkennt: abweichende IBAN, ungültige Prüfziffer, IBAN-Land ≠ Firmensitz.
Mehrere IBANs in einer Eingangsrechnung (weitere Überweisungsverbindungen, BG-17): Jede weitere IBAN wird wie die erste gegen Sperrliste, IBAN-Tresor, Historie des Lieferanten und Muldenkonten geprüft. Eine bekannte weitere IBAN ist kein Befund, eine bisher unbekannte erscheint als gelber Hinweis (kein Betrugsverdacht), eine gesperrte oder ungültige als rot. In der Antwort stehen sie unter fraud.extra_ibans (iban maskiert, status, risk, message), das Urteil der ersten IBAN unter fraud.iban_risk. Rechnungen mit einer IBAN werden wie bisher bewertet.
Rechnungs-Diff (POST /v1/diff): Felder original + corrected (PDF/XML) hochladen → strukturierter Positions-Diff als JSON oder, mit ?format=html, als einbettbare Git-Diff-Ansicht (grün = neu/teurer, rot/durchgestrichen = alt/entfernt), auch im White-Label-iframe nutzbar.
Forderungsmanagement: Mahnwesen je Partner und je Rechnung
Das Mahnwesen kennt drei Ebenen, jede erbt von der darüber: Konto (Einstellungen unter Offene Posten), Geschäftspartner (Karte „Mahnwesen" in der Partnerakte, per API die Felder dunning_* an POST /v1/partners) und Rechnung („Mahnwesen anpassen" an der offenen Rechnung). Acht Felder je Ebene: Modus (auto = der Dienst mahnt, manual = nur von Hand, off = nie, auch Knopf und API lehnen ab), Tonalität, Mahntexte je Stufe, Mahnkosten der 1. und letzten Mahnung, 40-€-Pauschale, Verzugsschaden, Stufen-Fristen (Tage nach Fälligkeit für Zahlungserinnerung, 1. und 2. Mahnung, Standard 3/10/21) und Zahlungsfrist im Schreiben (Standard 10 Tage). Ein leeres Feld bedeutet „wie übergeordnet"; die Oberfläche zeigt neben jedem Feld, welche Ebene den Wert liefert. Der automatische Lauf beachtet die Ebenen ebenso: ein Partner auf auto wird gemahnt, auch wenn das Konto auf manuell steht, und umgekehrt.
Import aus Excel, CSV und XML
Drei Wege, eine Erzeugungsstrecke: Unter Aus Datei erstellen laden Sie eine Datei hoch und sehen zuerst eine Vorschau (Rechnungen, Positionen, Summen, Fehler mit Blatt und Zeile), erst danach wird erzeugt. Dieselben Dateien nimmt POST /v1/import entgegen. Gelesen werden Excel (.xlsx, .xls), LibreOffice (.ods), CSV (Trennzeichen Semikolon, Komma oder Tab) und EN-16931-XML (ZUGFeRD/Factur-X-CII sowie XRechnung in beiden Syntaxen, CII und UBL). Excel-Dateien werden in einem abgeschotteten Container gelesen, Formeln kommen berechnet, Makros werden nie ausgeführt.
Viele Rechnungen aus einer Tabelle: eine Zeile je Position, Zeilen mit derselben Rechnungsnummer bilden eine Rechnung. Kopffelder (Empfänger, Zahlung, Lieferanschrift) dürfen in jeder Zeile stehen, die erste Zeile je Rechnung zählt. Die Kopfzeile darf auch unterhalb von Titelzeilen liegen. Pflicht sind rechnungsnummer, kunde, position und einzelpreis (oder netto). Der Absender kommt immer aus Ihrem Profil. Vorlage mit allen Spalten herunterladen.
Eine Excel-Rechnung als Ganzes: Rechnungen, die Sie bisher in Excel geschrieben haben (Briefkopf, Empfängerblock, Positionstabelle), werden erkannt und in die Rechnungsmaske übernommen. Ist das Layout nicht eindeutig, bietet die Oberfläche die KI-Zuordnung an (Opt-in, Kosten wie der KI-Import).
XML: eine vorhandene E-Rechnung (etwa aus einem anderen Tool) wird vollständig ins Rechnungsschema zurückgelesen, einschließlich Storno-Bezug, Leitweg-ID, Zahlungsbedingungen, Skonto, Lieferanschrift und Anlagen. Was keinen Platz hat, wird als Hinweis gemeldet. Aus UBL wird dabei CII, für XRechnung-Empfänger zulässig. Beta Fremd-XML (z. B. ein ERP-Export ohne EN-16931-Syntax) lesen wir nicht deterministisch; auf Wunsch ordnet die KI die Felder zu (Opt-in mit Kosten wie der KI-Import, Ergebnis in der Maske prüfen).
Alle Spalten des Tabellenimports (102)
Groß-/Kleinschreibung, Umlaute und Satzzeichen im Spaltennamen spielen keine Rolle („Rechnungs-Nr." wird erkannt). Zahlen deutsch (1.234,56) oder englisch (1234.56), Daten als TT.MM.JJJJ oder JJJJ-MM-TT. einzelpreis oder netto, eines von beiden ist Pflicht.
| Spalte | auch erkannt als |
|---|---|
rechnungsnummer Pflicht | rechnungs-nr., rechnungsnr, rechnung nr, re-nr, nummer, belegnummer |
belegart | dokumentart, typ, type code, invoice type, document type |
datum | rechnungsdatum, belegdatum, date, invoice date, issue date |
faellig | fällig, faelligkeit, faelligkeitsdatum, zahlbar bis, due, due date |
zahlungsziel_tage | zahlungsziel, zahlungsfrist, zahlungsziel tage, payment term days, payment terms, net days |
leistungsdatum | lieferdatum, delivery date, service date |
leistung_von | leistungszeitraum von, zeitraum von, period start |
leistung_bis | leistungszeitraum bis, zeitraum bis, period end |
waehrung | währung, currency |
steuerwaehrung | steuerwährung, tax currency |
kurs | wechselkurs, exchange rate |
profil | zugferd profil, profile, format |
bezug_rechnung | bezug, ursprungsrechnung, stornierte rechnung, preceding invoice, reference invoice |
leitweg_id | leitweg-id, leitweg, buyer reference, käuferreferenz, kaeuferreferenz |
bestellnummer | bestell-nr., bestellung, auftrag kunde, order ref, order number, po number |
auftragsnummer | auftrags-nr., auftrag, seller order ref, sales order |
lieferschein | lieferscheinnummer, lieferschein-nr., delivery note |
buchungskonto | kontierung, kostenstelle, accounting ref, accounting reference |
referenz | ihre referenz, vertragsnummer, reference, contract |
projekt | projektnummer, projekt-nr., project, project ref |
projektname | projektbezeichnung, project name |
kopftext | einleitung, anschreiben, header text, intro |
fusstext | fußtext, schlusstext, bemerkung, anmerkung, notiz, footer |
steuerregelung | steuerfall, umsatzsteuerregelung, tax scheme, vat scheme |
befreiungsgrund | steuerbefreiungsgrund, exemption reason, tax exemption reason |
nachlass | gesamtnachlass, rechnungsrabatt, allowance, document discount |
nachlass_prozent | nachlass %, rechnungsrabatt %, allowance percent, document discount percent |
nachlass_grund | nachlassgrund, rabattgrund, allowance reason, document discount reason |
nachlass2 | zweiter nachlass, allowance2, allowance 2, document discount 2 |
nachlass2_prozent | nachlass2 %, zweiter nachlass %, allowance2 percent, document discount 2 percent |
nachlass2_grund | zweiter nachlass grund, allowance2 reason, document discount 2 reason |
zuschlag | versandkosten, versand, verpackung, nebenkosten, extra charge, shipping |
zuschlag_grund | zuschlagsgrund, zuschlag bezeichnung, extra charge reason |
zuschlag_ust | zuschlag ust, zuschlag mwst, extra charge vat |
skonto_tage | skonto tage, skontofrist, skonto days, discount days |
skonto_prozent | skonto prozent, skonto %, skonto, skonto percent |
skonto2_tage | skonto 2 tage, skonto2 days |
skonto2_prozent | skonto 2 prozent, skonto 2, skonto2 percent |
anzahlung | bereits gezahlt, vorauszahlung, prepaid, paid amount |
rundung | rundungsausgleich, rounding |
anrechnung | abzug, angerechnete rechnungen, anzahlungsrechnungen, vorbelege |
weitere_bezuege | weitere bezüge, weitere bezuege, further references |
bezug_datum | bezugsdatum, datum der ursprungsrechnung, reference date |
leistung_voraussichtlich | leistung voraussichtlich, voraussichtliche leistung, voraussichtlicher leistungszeitpunkt, expected delivery |
leistung_voraussichtlich_bis | leistung voraussichtlich bis, voraussichtliche leistung bis, expected delivery to |
anzahlung_eingang | anzahlung eingegangen, anzahlung eingegangen am, anzahlung erhalten am, advance received |
auftragssumme | auftragssumme netto, auftragswert, order total |
absender | absenderfirma, rechnungssteller, aussteller, eigene firma, sender, issuer |
sprache | rechnungssprache, belegsprache, language, invoice language |
zahlungsbedingungen | zahlungsbedingung, zahlungskonditionen, konditionen, terms of payment, payment terms text, payment conditions |
lieferbedingungen | lieferbedingung, lieferkonditionen, incoterms, incoterm, delivery terms, terms of delivery |
unser_zeichen | unser zeichen, sachbearbeiter, bearbeiter, our reference, our ref, clerk |
iban | |
bic | swift |
bank | bankname, kreditinstitut, bank name |
zahlart | zahlungsart, zahlungsweise, payment method, payment means |
mandat | mandatsreferenz, sepa-mandat, mandate, mandate reference |
glaeubiger_id | gläubiger-id, glaeubiger-id, creditor id, creditor identifier |
verwendungszweck | zahlungsreferenz, payment reference, remittance information |
zahlungsempfaenger | zahlungsempfänger, abweichender zahlungsempfaenger, payee, payee name |
kundennummer | kunden-nr., kundennr, kdnr, partnernummer, debitor, debitorennummer |
kunde Pflicht | kunde_name, kundenname, name, firma, empfaenger, empfänger |
kunde_handelsname | handelsname, kunde handelsname, trading name |
kunde_rechtsform | rechtsform, gesellschaftsform, legal form |
kunde_ansprechpartner | ansprechpartner, z. hd., zu haenden, kontakt, contact, contact name |
kunde_strasse | kunde_straße, strasse, straße, kunde strasse, anschrift, adresse |
kunde_adresszusatz | adresszusatz, kunde zusatz, street2, address line 2 |
kunde_plz | plz, postleitzahl, kunde plz, zip, postal code, postcode |
kunde_ort | ort, stadt, kunde ort, city, town |
kunde_bundesland | bundesland, region, state, province |
kunde_land | land, kunde land, country, country code |
kunde_ustid | ustid, ust-idnr, ust-idnr., ust-id, umsatzsteuer-id, kunde ustid |
kunde_steuernummer | steuernummer, steuer-nr., kunde steuernummer, tax number, tax id |
kunde_email | email, e-mail, mail, kunde email, customer email |
kunde_telefon | telefon, tel, tel., kunde telefon, phone, telephone |
kunde_iban | kunden iban, iban kunde, iban des kunden, kunden-iban, empfaenger iban, erstattungskonto |
liefer_name | lieferanschrift name, lieferadresse name, lieferung an, ship to, ship to name, delivery name |
liefer_kennung | lieferstelle, standortkennung, ship to id, location id |
liefer_strasse | liefer_straße, lieferanschrift strasse, lieferstrasse, ship to street, delivery street |
liefer_adresszusatz | liefer zusatz, ship to street2 |
liefer_zusatz2 | liefer zusatz 2, ship to street3 |
liefer_plz | lieferplz, lieferanschrift plz, ship to zip, delivery zip |
liefer_ort | lieferort, lieferanschrift ort, ship to city, delivery city |
liefer_bundesland | liefer region, ship to state |
liefer_land | lieferland, lieferanschrift land, ship to country, delivery country |
position Pflicht | pos, bezeichnung, leistung, beschreibung, artikel, artikelbezeichnung |
artikelnummer | artikel-nr., artikelnr, art.-nr., sku, item id, item number |
kunden_artikelnummer | kundenartikelnummer, artikelnummer kunde, buyer item id, customer item number |
gtin | ean, barcode |
menge | anzahl, stück, stueck, stk, qty, quantity |
einheit | mengeneinheit, me, unit, uom, unit of measure |
einzelpreis Pflicht | preis, einzelpreis netto, nettopreis, stueckpreis, stückpreis, unit price |
netto Pflicht | nettobetrag, positionsnetto, zeilensumme, gesamt netto, net, line net |
ust_prozent | ust, ust %, ust-satz, mwst, mwst %, mwst-satz |
rabatt | positionsrabatt, rabatt betrag, discount, discount amount |
rabatt_prozent | rabatt %, rabatt prozent, discount %, discount rate |
zuschlag_position | positionszuschlag, zuschlag position, line surcharge, surcharge |
listenpreis | bruttolistenpreis, list price, gross price |
preisnachlass | preisrabatt, price discount |
preisbasis | preisbasismenge, preis je menge, price base quantity, base quantity |
ursprungsland | herkunftsland, origin country, country of origin |
positionsnotiz | positionstext, zusatztext, line note, item note |
No-Code & White-Label
Ohne Code: Unter Aus Datei erstellen eine Tabelle (Excel, LibreOffice oder CSV) hochladen → Vorschau, dann ZIP mit allen ZUGFeRD-PDFs. Ideal für Sachbearbeiter ohne Technik.
Make / Zapier: Mit dem „Webhooks/HTTP"-Baustein POST /v1/generate je Zeile aufrufen, kein eigener Server nötig.
White-Label-Einbettung: Für SaaS-Anbieter. Ihr Server mintet ein kurzlebiges Token aus Ihrem API-Key und bettet das Rechnungsformular im eigenen Corporate Design per iframe ein, der Endkunde legt kein Konto an, Credits laufen auf Ihr Kontingent:
# 1) Token serverseitig erzeugen (API-Key bleibt geheim)
curl -X POST https://sichere-erechnung.de/v1/embed/token \
-H "Authorization: Bearer IHR_API_KEY" -H "Content-Type: application/json" \
-d '{"accent":"#e8590c","title":"Rechnung, Ihre Marke","ttl":3600}'
# -> { "token": "…", "embed_url": "https://sichere-erechnung.de/embed?token=…" }
# 2) embed_url im iframe einbetten
<iframe src="https://sichere-erechnung.de/embed?token=…" style="width:100%;height:900px;border:0"></iframe>Theming: Akzentfarbe, Titel und Eckenradius über das Token (accent, title, radius) oder kosmetisch per URL (?accent=ff8800&radius=4). Ihr Logo kommt aus dem Profil.
Empfänger-Ansprechpartner & Katalog: Das eingebettete Formular enthält ein „z. Hd."-Feld (BT-56, erscheint auf der Rechnung) und schlägt Positionen aus Ihrem Katalog per Autovervollständigung vor (füllt Einheit, Nettopreis und USt), identisch zur Haupt-Oberfläche und unter Ihrer Marke.
Events ans Eltern-Fenster (postMessage): Das iframe sendet zugferd:resize (Höhe für Auto-Resize), zugferd:success (PDF erzeugt, inkl. filename) und zugferd:error (mit errors[]). So binden Sie es an:
window.addEventListener('message', function (ev) {
var d = ev.data || {};
if (d.type === 'zugferd:resize') iframe.style.height = d.height + 'px';
if (d.type === 'zugferd:success') console.log('Rechnung erzeugt:', d.filename);
if (d.type === 'zugferd:error') console.warn(d.errors);
});Live ansehen: White-Label-Seite mit eingebetteter Demo.
Anzahlung, Teil- und Schlussrechnung
Belegarten: 386 Anzahlungsrechnung, 875 Abschlagsrechnung Bauleistung, 326 Teilrechnung (ausgeführte Teilleistung), 876 Teilschlussrechnung Bauleistung, 877 Schlussrechnung Bauleistung. Eine Schlussrechnung ist eine Restrechnung (UStAE 14.8 Abs. 11, BMF-Schreiben vom 15.10.2024 Rn. 47 und 48): Sie enthält alle Positionen der Gesamtleistung und je Vorbeleg und Steuersatz eine Minusposition (Menge -1, Preis netto positiv). Steuer, Brutto und Zahlbetrag betreffen nur den Rest. Das Feld invoice.prepaid (BT-113) wird dafür nicht benutzt. Eine Rechnung 380 mit Anrechnung heißt auf Beleg, Mail, Liste und Mahnung „Schlussrechnung“, im XML bleibt sie 380.
Schlussrechnung per API
Für eine eigene Anzahlungsrechnung genügt die Nummer. Wir ergänzen Datum, Belegart, den anzurechnenden Betrag und die Aufteilung je Steuersatz aus Ihrem Konto:
{ "invoice": { "type_code": "380", "number": "SR-2026-001", "issue_date": "2026-09-30",
"delivery_date": "2026-09-25", "seller_order_ref": "AB-2026-0815",
"deductions": [ { "number": "AZ-2026-001" } ] },
"seller": { … }, "buyer": { … },
"lines": [ { "name": "Umbau Halle 3 gemäß Auftrag AB-2026-0815", "qty": 1, "unit_price": 30000.00, "vat_rate": 19 } ] }Ergebnis bei bezahlter Anzahlung über 10.710,00 (9.000,00 netto): 30.000,00 abzüglich 9.000,00 = 21.000,00 netto, 3.990,00 USt, Zahlbetrag 24.990,00. Ein fremder Vorbeleg (nicht in Ihrem Konto) braucht die Nettobeträge je Steuersatz; amount allein genügt nur bei genau einem Steuersatz in den Positionen (dann mit Hinweis, dass net genauer ist):
"deductions": [ { "number": "A-77", "issue_date": "2026-03-01", "type_code": "386",
"received_date": "2026-03-10", "rates": [ { "vat_rate": 19, "net": 9000.00 } ] } ]Eine Anzahlungsrechnung nennt den voraussichtlichen Zeitpunkt der Leistung statt eines Leistungsdatums:
{ "invoice": { "type_code": "386", "number": "AZ-2026-001", "issue_date": "2026-07-01",
"expected_delivery_from": "2026-10", "seller_order_ref": "AB-2026-0815", "order_total_net": 30000.00 },
"seller": { … }, "buyer": { … },
"lines": [ { "name": "Anzahlung 30 % auf Auftrag AB-2026-0815", "qty": 1, "unit_price": 9000.00, "vat_rate": 19 } ] }Neue Felder
| Feld | Bedeutung |
|---|---|
invoice.deductions[] | Anrechnungen, nur bei 380, 326, 876 und 877. Je Eintrag number (Pflicht), optional issue_date, type_code (386, 875, 326 oder 876, Vorgabe 386), received_date, amount (angerechnet brutto), rates[] mit vat_rate, net und optional tax (Kurzform {number, vat_rate, net}), cancelled_confirmed. Eine Nummer als Text gilt wie {"number": …}. Bei einem eigenen Vorbeleg gelten amount oder rates[] als bestätigter Betrag und bleiben stehen: höchstens das Brutto des Vorbelegs, mindestens der Eingang (386, 875) bzw. das abgerechnete Teilentgelt (326, 876), über dem Eingang mit Hinweis; ohne beides rechnen wir den Vorschlag. Dasselbe gilt für eine eingelesene Restrechnung (XML-Import, /v1/generate mit XML). Dieselbe Anzahlung zusätzlich unter invoice.prepaid ist ein Fehler, sie würde zweimal abgezogen. |
invoice.reference_invoice | Bezug (BT-25) als Text, als Liste oder als Objekt {number, issue_date}; eine Ganzzahl gilt als Text. Bei einer Liste wird die erste Nummer der Bezug, die übrigen werden references[]. Kommazahl und Wahrheitswert ergeben 422. |
invoice.references[] | weitere Bezüge {number, issue_date?, type_code?}. EXTENDED schreibt alle als BG-3, EN 16931, XRechnung, BASIC und BASIC WL einen und die übrigen als Satz „Weitere Bezüge: …“ in BT-22, MINIMUM keinen. |
invoice.reference_issue_date | Datum des ersten Bezugs (BT-26), YYYY-MM-DD. |
invoice.expected_delivery_from | bei 386, 875 und deren Storno: voraussichtlicher Zeitpunkt der Leistung, YYYY-MM-DD oder YYYY-MM (Kalendermonat, § 31 Abs. 4 UStDV). Mit invoice.expected_delivery_to ein Zeitraum, nur _to heißt „bis zum“, beide leer heißt „noch nicht vereinbart“. Bei anderen Belegarten ein Hinweis, das Feld wird ignoriert. |
invoice.advance_received_date | bei 386 und 875: Tag, an dem die Anzahlung eingegangen ist, nicht nach dem Rechnungsdatum. Weicht er vom Rechnungsdatum ab, steht er als BT-7 im XML (EN 16931, XRechnung, EXTENDED); BASIC und BASIC WL nennen ihn im Vermerk. |
invoice.order_total_net | Auftragssumme netto, nicht im XML; für den Prozent-Helfer und „Bisher abgerechnet“ in der Maske. |
invoice.prepaid | BT-113 heißt jetzt „bereits bezahlt, ohne Anzahlungsrechnung“. Das Vorzeichen folgt dem Brutto (negativ nur bei negativem Brutto, etwa im Storno), über dem Brutto ist es ein Fehler statt stiller Kappung, nur Zahlen und Zahltexte mit Punkt. Bei MINIMUM steht der Zahlbetrag in DuePayableAmount. Anzahlungsrechnungen ziehen Sie mit invoice.deductions ab: Wurde über diese Anzahlung eine Anzahlungsrechnung gestellt, fehlt so der Abzug der darin enthaltenen Umsatzsteuer (§ 14 Abs. 5 Satz 2 UStG). Nach UStAE 14.8 Abs. 10 kann dann die gesamte ausgewiesene Steuer geschuldet sein; bitte klären Sie das mit Ihrer Steuerberatung. Ziehen Sie Anzahlungsrechnungen mit invoice.deductions ab. |
Was angerechnet wird
- 386 und 875: der eingegangene Betrag, anteilig je Steuersatz. Ist die Anzahlungsrechnung nicht oder nur teilweise bezahlt, fordert die Schlussrechnung den Rest, die Anzahlungsrechnung gilt als abgelöst und wird nicht mehr gemahnt.
- 326 und 876: das abgerechnete Teilentgelt samt Steuer, unabhängig von der Zahlung; die Teilrechnung bleibt eine eigene Forderung.
- Ausdrückliches
amountbei einem eigenen Vorbeleg: höchstens sein Betrag, mindestens der eingegangene Betrag (386, 875) bzw. das abgerechnete Teilentgelt (326, 876), sonst422(§ 14 Abs. 5 Satz 2 UStG). Mehr als eingegangen gilt als Bestätigung: Die Differenz bleibt auf der Anzahlungsrechnung offen und wird weiter gemahnt, der Vermerk nennt beide Beträge. - Gleiche Währung und Steuerregelung, ein Vorbeleg nur in einer wirksamen Schlussrechnung. Ein stornierter, bezahlter Vorbeleg nur mit
cancelled_confirmed: trueund ohne gebuchte Erstattung (UStAE 14.8 Abs. 9).
Vermerke im Beleg (BT-22 und PDF)
- Restrechnung, wenn eine Minusposition entsteht: „Restrechnung: Die angerechneten Teilentgelte sind netto als Minuspositionen abgesetzt. Ausgewiesen ist nur die Umsatzsteuer auf das restliche Entgelt.“
- Je eigener Anzahlungsrechnung, die nicht voll angerechnet ist: „Die Anzahlungsrechnung AZ-2 vom 01.08.2026 wurde nicht bezahlt. Ihr Betrag ist in dieser Rechnung enthalten und nicht gesondert zu zahlen.“ bzw. „Von der Anzahlungsrechnung AZ-2 vom 01.08.2026 wurden 4.000,00 EUR vereinnahmt und angerechnet. Der Rest ist in dieser Rechnung enthalten und nicht gesondert zu zahlen.“ Ist mehr bestätigt als eingegangen: „… wurden 4.000,00 EUR vereinnahmt. Angerechnet sind 8.000,00 EUR. Die Differenz von 4.000,00 EUR ist weiterhin auf die Anzahlungsrechnung AZ-2 zu zahlen. …“
- Anzahlungsrechnung: „Anzahlungsrechnung: Mit dieser Rechnung wird eine Anzahlung vor Ausführung der Leistung abgerechnet.“, Abschlagsrechnung: „Abschlagsrechnung: Mit dieser Rechnung wird eine Abschlagszahlung vor Abnahme der Bauleistung abgerechnet.“, dazu der voraussichtliche Zeitpunkt. Kein Leistungsdatum (BT-72) und kein Leistungszeitraum (BG-14); ein mitgeschicktes
delivery_dateoderperiod_*wird mit Hinweis zum voraussichtlichen Zeitpunkt. Vor dieser Änderung erzeugte Anzahlungsrechnungen bleiben beim erneuten Herunterladen, wie sie ausgestellt wurden. - XRechnung: eine 386 wird als 380 mit dem Vermerk „Anzahlungsrechnung:“ geschrieben (BStBK-FAQ 4.5, BR-DE-17 ist nur eine Warnung). 875, 876 und 877 bleiben. Eine 384 verlangt dort
invoice.reference_invoice(§ 31 Abs. 5 Satz 2 UStDV, BR-DE-26), in den anderen Profilen gibt es einen Hinweis.
Storno und Korrektur
Eine 384 mit Bezug auf einen eigenen Beleg und genau dessen negiertem Brutto ist ein Vollstorno und schließt ihn; ein kleinerer negativer Betrag ist eine Teilkorrektur, ein positiver eine Nachberechnung. Der Storno einer Schlussrechnung hebt ihre Anrechnungen auf, die Anzahlungsrechnungen leben wieder auf. Storno oder Korrektur einer angerechneten Anzahlungsrechnung sind gesperrt, solange die Schlussrechnung wirksam ist, auch wenn der Bezug als Liste kommt. Ein Storno übernimmt invoice.prepaid negiert (Zeile „zuzüglich Rücknahme bereits bezahlt“ im PDF) und trägt keine deductions: Storno mit bereits bezahltem Betrag (invoice.prepaid, BT-113): Mit diesem Beleg wird nur der Zahlbetrag erstattet. Den bereits bezahlten Betrag erstatten Sie gesondert oder übernehmen ihn in die neue Rechnung.
Hinweise und Kopfzeilen
X-Invoice-Hintsbei PDF- und XML-Antworten (/v1/generate,/v1/automap?generate=1,/v1/embed,/v1/ciials XML): Hinweise der Prüfung, mit „ | “ getrennt, höchstens 2000 Byte, danach „und N weitere Hinweise“. JSON-Antworten tragenhints(nur wenn es welche gibt).- Mit
?validate=1kommen die Warnungen und Informationen des KoSIT-Validators in denselben Kanal. Gültig ist, was der Validator zur Annahme empfiehlt;/v1/validate,/v1/validate/fraudund/v1/check(unterkosit.hints) liefern die Hinweise getrennt von den Fehlern. Endet die Prüfung ohne Prüfbericht (Zeitüberschreitung), gilt der Beleg als nicht geprüft: „Prüfung nicht abgeschlossen: Der KoSIT-Validator hat keinen Prüfbericht geliefert (Zeitüberschreitung oder Abbruch). Bitte erneut prüfen.“ X-Invoice-Stored: 0: das PDF ist ausgeliefert, das Ablegen in Ihrer Rechnungsliste ist gescheitert (steht im Fehlerprotokoll).X-Invoice-PayLink: 0: der Zahllink fehlt, die Rechnung ist gespeichert.
Forderungen und Zahlungen
GET /v1/receivables nennt je Eintrag zusätzlich type_code, prepaid_cents, due_cents (Zahlbetrag), claim_cents (Forderung nach Verrechnung, null = Zahlbetrag), open_cents, overpaid_cents, closed_reason (payment, offset verrechnet, superseded abgelöst, cancelled, covered_by_prepayment, nothing_due) und links.predecessors[] / links.successors[] mit {number, type_code, kind, applied_cents} (kind: offset, cancellation, correction, reference). payments[] tragen value_date, kind (payment, settlement, refund) und note. Gutschriften, Storno- und Korrekturbelege stehen nicht in der Liste. paid_cents ist die Summe echter Zahlungen, ohne Kappung.
POST /v1/receivables/payment{number, amount_cents, value_date?, note?}: ein Datum in der Zukunft oder einamount_cents, das keine ganze Zahl ist, ergibt422; eine Überzahlung wird gebucht und inoverpaid_centsgenannt; Storno- und Korrekturbelege nehmen keine Zahlung an (409).POST /v1/receivables/paid{number, value_date?}: bucht den offenen Rest als Ausgleich; nichts offen ergibt409.POST /v1/receivables/refund{number, amount_cents, value_date?, note?}: Erstattung einer Überzahlung, höchstens bisoverpaid_cents, sonst409.
Eingangsprüfung
POST /v1/check liest BT-113, BT-114 und BT-115 und nennt unter invoice zusätzlich prepaid_total und due_payable (Dezimalzahl wie grand_total). Der Befund zahlbetrag meldet eine abgezogene Anzahlung (Hinweis), einen Widerspruch zwischen Zahlbetrag und Brutto minus Anzahlung plus Rundung über 1 Cent, ein negatives BT-113 bei positivem Brutto oder eine Rundung über 0,99 (gelb, Vormerken nur mit Bestätigung) und bei MINIMUM einen kleineren Zahlbetrag (Hinweis). Weicht der Zahlbetrag vom Brutto ab und steht er nicht im lesbaren PDF, meldet consistency gelb. Die SEPA-Sammelzahlung überweist den Zahlbetrag, nicht das Brutto; ein Zahlbetrag von 0 lässt sich nicht vormerken, eine Rechnung in fremder Währung ebenso wenig (eine unlesbare Währung steht als XXX). Belege ohne gelesenen Zahlbetrag aus der Zeit davor bestätigen Sie einmal in der Zahllauf-Box.
Import und KI
Die Import-Spalte belegart kennt „Schlussrechnung“, „Endrechnung“, „Restrechnung“ (380), „Teilschlussrechnung“ (876), „Schlussrechnung Bau“ (877), „Abschlagsrechnung“ (386, mit „Bau“ 875). Neue Spalten: anrechnung (Nummern, mit „;“ oder „,“ getrennt), leistung_voraussichtlich und _bis, anzahlung_eingang, weitere_bezuege, bezug_datum, auftragssumme. Eine Anrechnung geht nur auf Rechnungen, die schon erzeugt sind: Anzahlungs- und Schlussrechnung importieren Sie in zwei Läufen. Mehrere Beträge in anzahlung sind ein Zeilenfehler. Die Vorlage zeigt beides (Anzahlungsrechnung 2026-002, Schlussrechnung 2026-003). /v1/import nennt Zeilenfehler und Hinweise je Rechnung unter invoices[i].errors und invoices[i].hints, in info zusätzlich fehlerJeRechnung und hinweiseJeRechnung; eine Rechnung mit Zeilenfehler wird nicht erzeugt. Die KI-Erfassung (/v1/automap) erkennt Anzahlungs-, Teil- und Schlussrechnungen und „abzüglich Anzahlung AR-…“ als Anrechnung.
Word-Vorlage
Neue Platzhalter: ${service_label}, ${service_text}, ${prepaid_line}, ${net_before_deductions}, ${deductions_net}, ${advance_note}, ${grand_label}, dazu die Blöcke ${deductions_block}, ${net_block} und ${prepaid_block}. Vorlagen, die vor dieser Änderung erzeugt wurden, kennen ${service_text}, ${due_total} oder ${advance_note} nicht: Anzahlungsrechnungen, Belege mit bereits bezahltem Betrag und Belege mit Vermerk entstehen dann im Standard-Layout, der Vorlagen-Aufschlag wird erstattet, der Grund steht in X-Template-Warning. Abhilfe: im Profil „Vorlage neu erzeugen“.
Gewollte Änderungen für bestehende Aufrufe
invoice.prepaidüber dem Brutto ist ein Fehler statt stiller Kappung; negativ nur bei negativem Brutto.- 386 und 875 tragen kein Leistungsdatum mehr; XRechnung mit 386 ist kein Fehler mehr, sondern 380 mit Vermerk.
- Ein negativer Einzelpreis ohne Listenpreis wird umgedreht (Menge und Preis mal -1, Betrag gleich), mit Hinweis.
lines[].net: nulloder""rechnet jetzt wie ein fehlendes Feld (Menge mal Preis), vorher als Nettobetrag 0.- Die Forderungs-API bucht Überzahlungen, statt sie zu kappen, und nennt Storno- und Korrekturbelege nicht mehr.
/v1/ciimitAccept: application/jsonund/v1/import: Bei negativem Rechnungsbetrag (Storno) isttotals.prepaidjetzt 0 undtotals.dueder negative Betrag; vorher stand das Brutto als bereits bezahlt und der Zahlbetrag bei 0.- Ein zweiter Vollstorno derselben Rechnung ergibt
422(„R-100 ist bereits durch ST-102 storniert.“) statt200. - Leerzeichen am Rand von
invoice.reference_invoicewerden entfernt (BT-25). Bereits gespeicherte Belege entstehen beim erneuten Herunterladen wie ausgestellt. - Der Storno einer eigenen Anzahlungs- oder Abschlagsrechnung (386, 875) trägt kein Leistungsdatum (BT-72), dazu kommt ein Hinweis in
X-Invoice-Hints. invoice.prepaidals Text mit Komma ("100,50") ergibt422; vorher wurde still 100.00 daraus.- Profil
minimummitinvoice.prepaidoderinvoice.rounding:DuePayableAmountist der Zahlbetrag statt des Bruttos. Bereits gespeicherte Belege entstehen beim erneuten Herunterladen wie ausgestellt.
Beispiel mit Hinweisen im Kopf: curl -i -X POST https://sichere-erechnung.de/v1/generate … zeigt X-Invoice-Hints in der Antwort.