Zum Inhalt springen
Rechnungskit

Eigene Anwendung per API anbinden

Aktualisiert am

Mit der REST-API meldet deine eigene Anwendung (SaaS, eigener Checkout, Plattform) Transaktionen an Rechnungskit. Diese Seite erklärt Schlüssel, Endpunkte, die wichtigsten Felder und was du beim Senden beachten musst. Die vollständige Referenz findest du auf rechnungskit.de/docs/api.

Der Ablauf in Kurzform: Deine Anwendung schickt die Bestellung. Die Zahlung kommt vom angebundenen Zahlungsanbieter, und sobald beides zusammenpasst, erstellt Rechnungskit den Beleg. Bei Ware wartet die Rechnung zusätzlich auf deine Versandmeldung.

REST-API · Ablauf
Von der API-Bestellung zur E-Rechnung
Deine Anwendung
POST /v1/ordersPositionen und Beträge in Cent, optional paymentRef
POST /v1/fulfillmentsnur bei physischer Ware, setzt das Leistungsdatum
Rechnungskit
  1. Nimmt die Bestellung anidempotent über deine orderNo
  2. Ordnet die Zahlung zuvom angebundenen Zahlungsanbieter, paymentRef beschleunigt das
  3. Erstellt den Belegmit EN-16931-Validierung und PDF
Ergebnis
E-RechnungZUGFeRD, mit gültiger Leitweg-ID als XRechnung 3.0
Abruf per APIStatus über GET /v1/orders/{orderNo}, PDF und XML über /v1/invoices
Ein „bezahlt“-Feld gibt es nicht: Den Zahlungsstatus liefert der Zahlungsanbieter. Einzige Ausnahme ist eine Bestellung, die komplett mit Empfehlungsguthaben bezahlt wurde.

Grundlagen

Punkt So ist es
Basis-URL https://api.rechnungskit.de/v1
Format REST mit JSON, OpenAPI 3.1
Authentifizierung Bearer-Token mit deinem API-Schlüssel
Beträge immer in ganzzahligen Cent, nie als Kommazahlen
Idempotenz Deine Bestellnummer (orderNo) ist der natürliche Schlüssel, zusätzlich wird der Idempotency-Key-Header unterstützt. Doppelte Übermittlungen erzeugen keine doppelten Belege.

API-Schlüssel

Unter Verbindungen → API erstellst du Schlüssel. Es gibt zwei Berechtigungen:

Berechtigung Wofür
orders:write Bestellungen, Stornierungen und Fulfillments melden, Guthaben-Bewegungen und Salden senden
invoices:read Belege abrufen, auch den Stand einer Bestellung über GET /v1/orders/{orderNo}

Es gibt EINEN Schlüssel-Typ (Präfix rk_key_). Ob Belege Testdaten oder echt sind, entscheidet allein der Testmodus des Projekts, nie der Schlüssel. Derselbe Schlüssel erzeugt im Testmodus Testbelege und nach dem Go-Live echte Belege, nichts muss ausgetauscht werden. Ältere Schlüssel mit rk_test_- oder rk_live_-Präfix bleiben unverändert gültig.

  • Einmal sichtbar: Der volle Schlüssel wird genau einmal angezeigt, danach nur noch der Anfang.
  • Ablauf: wählbar, 30, 90 oder 365 Tage oder ohne Ablauf.
  • Unbenutzt: Schlüssel, die über 90 Tage nicht benutzt wurden, werden markiert.

Wichtigste Endpunkte

Endpunkt Wofür Berechtigung
POST /v1/orders Bestellung übermitteln (Positionen, Beträge in Cent, Zahlart) orders:write
GET /v1/orders/{orderNo} Stand einer Bestellung samt aller Belege invoices:read
POST /v1/orders/{orderNo}/cancel Stornierung einer Bestellung melden (siehe unten) orders:write
POST /v1/fulfillments Versand melden (setzt das Leistungsdatum), nur für physische Ware nötig orders:write
POST /v1/checkout-links Einmal-Link zum Abo-Checkout, mit vorausgefüllter E-Mail und deinen Metadaten (siehe unten) orders:write
GET /v1/invoices Belege auflisten invoices:read
GET /v1/invoices/{reference} einen Beleg abrufen invoices:read
GET /v1/invoices/{reference}/pdf und /xml Beleg-Dateien laden invoices:read

Beispiel-Bestellung

POST https://api.rechnungskit.de/v1/orders
Authorization: Bearer rk_key_…

{
  "orderNo": "CM-10482",
  "email": "kunde@example.com",
  "paymentRef": "pi_123",
  "requiresShipping": true,
  "shippingGrossCents": 490,
  "billingAddress": { "name": "Erika Muster", "country_code": "DE" },
  "items": [
    { "name": "Kaffee 1kg", "quantity": 2, "unitGrossCents": 2490, "taxRate": 7, "productId": "bohne-42" }
  ]
}

Pflicht sind orderNo, billingAddress mit country_code und mindestens eine Position mit name, quantity und unitNetCents oder unitGrossCents.

unitNetCents ist der Nettopreis, unitGrossCents der Bruttopreis. taxRate ist optional: Fehlt er, bestimmt Rechnungskit den Satz aus dem Produkt und rechnet die Umsatzsteuer bei unitNetCents obendrauf, bei unitGrossCents heraus.

Versandkosten

Versandkosten schickst du auf einem von zwei Wegen:

  • shippingGrossCents: der bezahlte Bruttobetrag. Rechnungskit ermittelt die Steuer selbst.
  • shippingNetCents plus shippingTaxRate: wenn dein Checkout die Versandsteuer schon berechnet hat.

Bei gemischten Steuersätzen im Warenkorb teilt Rechnungskit den Versand automatisch nach dem Brutto-Warenwert auf (BFH, Urteil vom 22.01.2025, XI R 22/22: Aufteilung nach Bruttoverkaufspreisen), genau wie beim Rechnungskit-Checkout. Der bezahlte Betrag ändert sich dabei nie.

Belege einer Bestellung abrufen

GET /v1/orders/{orderNo} liefert je Beleg:

  • den Typ (invoice, correction, voucher_receipt) und die Belegart,
  • den Bezug auf die korrigierte Rechnung (referencedInvoiceId),
  • Datum, Bruttobetrag und PDF-Link.

Was GET /v1/invoices/{reference} zurückgibt, hängt davon ab, womit du fragst:

Du fragst mit Du bekommst
UUID oder Belegnummer genau diesen Beleg
Bestellnummer oder Zahlungsreferenz die Rechnung der Bestellung, auch wenn es inzwischen eine Stornorechnung gibt

Die Stornorechnung holst du über ihre UUID aus GET /v1/orders/{orderNo}.

Ist dein Kunde in deiner Software angemeldet, fordert dein Server den Link zum Abo-Checkout an, statt einen festen Link anzuzeigen:

POST /v1/checkout-links
{
  "plan": "abo-pro",
  "email": "kunde@firma.de",
  "metadata": { "workspace_id": "ws_42" },
  "returnUrl": "https://app.deine-software.de/abrechnung"
}
→ 201 { "data": { "id": "…", "url": "https://checkout.rechnungskit.de/s/abo-pro?t=…", "expiresAt": "…" } }
  • plan ist der Teil nach /s/ im Abo-Link des Plans (oder die Plan-Id).
  • In der URL steht nur ein zufälliger Token, keine E-Mail und keine Metadaten. Der Käufer kann nichts davon ändern.
  • Die E-Mail ist im Checkout vorausgefüllt, der Käufer kann sie noch ändern.
  • metadata (bis 20 Einträge, nur Text) landet am Abo und kommt in jedem subscription.*-Webhook zurück, für die ganze Laufzeit: bei Verlängerung, Upgrade, Downgrade, Mengenänderung, Kündigung und Zahlungsproblemen, auch wenn der Käufer das im Kundenportal ändert. So weiß deine Software immer, welcher Workspace gemeint ist. Namen, die Rechnungskit selbst nutzt (etwa migrated_from), lehnt die API ab.
  • returnUrl: Nach dem erfolgreichen Kauf leitet die Danke-Seite dorthin weiter, mit ?subscription=<Abo-Id> am Ende (dieselbe Id wie subscriptionId im Webhook). Ohne returnUrl gilt die Weiterleitung am Plan: in der App unter Produkte → Abo-Plan bearbeiten → „Nach dem Kauf weiterleiten zu“.
  • Der Link gilt 24 Stunden (expiresInMinutes, 5 Minuten bis 7 Tage). Bis das Abo aktiv ist, lässt er sich erneut öffnen, etwa nach einer abgebrochenen Zahlung. Danach und nach Ablauf zeigt er einen Hinweis und, wenn gesetzt, einen Link zurück zu returnUrl.
  • Dein bestehender API-Schlüssel mit orders:write reicht. Einen Idempotency-Key berücksichtigt der Endpunkt, er ist hier aber nicht Pflicht.

Schick die E-Mail nie als Parameter im öffentlichen Abo-Link mit: Sie stünde dann in Browserverlauf und Server-Logs.

Nur Geschäftskunden

Verkaufst du laut AGB nur an Unternehmen, stell in der App unter Produkte am Abo-Plan den Kundenkreis auf „Nur Geschäftskunden“. Der Checkout zeigt dann keine Auswahl „Privatperson“, der Firmenname ist Pflicht, und Käufer aus anderen EU-Ländern müssen ihre USt-IdNr. angeben. Rechnungskit prüft das auch auf dem Server, ein angepasster Aufruf kommt also nicht daran vorbei. Die Einstellung gilt für alle neuen Abschlüsse des Plans, mit und ohne API-Link. Laufende Abos bleiben unverändert.

Artikel-Id je Position: productId

Jede Position darf eine productId tragen, die stabile Artikel-Id aus deinem System. Sie ist optional, aber empfohlen: Sie bindet die Position an genau ein Produkt im Rechnungskit-Katalog, auch wenn sich Name oder SKU später ändern.

Ohne productId sucht Rechnungskit das Produkt zuerst über die SKU und, wenn auch die fehlt, über den exakten Namen. Änderst du dann dein SKU-Schema oder lieferst eine SKU nach, entsteht je Variante ein neues Katalogprodukt. Das fällt zuerst dort auf, wo Produkte gepflegt werden: Dieselbe Ware steht mehrfach in der Liste, und jede Fassung braucht eigene USt-Kategorie und Umsatzrealisierung.

Die Id ist beliebiger Text (zum Beispiel die Primärschlüssel-Id deiner Artikeltabelle). Wichtig ist nur, dass sie je Artikel gleich bleibt. Verschiedene productId bedeuten verschiedene Artikel, auch bei identischem Namen. So bleiben echte Varianten sauber getrennt.

SaaS und digitale Leistungen: nur ein Endpunkt

Für SaaS oder rein digitale Leistungen genügt POST /v1/orders. Das Feld requiresShipping lässt du einfach weg (Standard false). Dann gibt es keine Erfüllungs-Wartestufe, und /v1/fulfillments wird nie aufgerufen.

Die Rechnung entsteht, sobald die Zahlung des angebundenen Zahlungsanbieters zur Bestellung passt. paymentRef mitschicken beschleunigt die Zuordnung. Ein „bezahlt“-Feld gibt es bewusst nicht: Den Zahlungsstatus liefert der Zahlungsanbieter, nicht der Sender.

Leistungszeitraum (SaaS/Abos): das Feld service_period

Für zeitbasierte Leistungen (SaaS, Abos) sendest du den Leistungszeitraum im optionalen Feld service_period. Achtung, hier gilt snake_case, nicht camelCase.

Regel Details
Aufbau Objekt mit start_date und end_date, jeweils als ISO-Datum YYYY-MM-DD
Vollständig entweder beide Schlüssel oder keiner, fehlt einer, kommt 422
Reihenfolge end_date darf nicht vor start_date liegen

Beispiel im Bestell-Body:

"service_period": { "start_date": "2026-06-01", "end_date": "2026-06-30" }
service_period · Fälle
Was mit dem Leistungszeitraum passiert
Mitgeschickt oder am Produkt hinterlegt
Steuert die pRAP (nur Bilanzierer) und steht als Leistungszeitraum auf der ZUGFeRD-Rechnung. Ein mitgeschickter Zeitraum hat Vorrang vor dem Abrechnungsrhythmus am SaaS-Produkt
Rechnungsofort
Weggelassen, keine Voreinstellung
Bei EÜR passiert nichts weiter. Bei Bilanzierung hält Rechnungskit die Rechnung als Aufgabe „Produkt ohne Umsatzrealisierung“ an
Bilanzerst nach dem Nachtragen
Beginn im früheren Wirtschaftsjahr
Bei Bilanzierung entsteht die Aufgabe „Leistungszeitraum im Vorjahr“, als Hinweis, keine Blockade
Rechnungtrotzdem sofort
Bei EÜR wird sofort vereinnahmt, eine Rechnungsabgrenzung gibt es dort nicht.

Wozu der Zeitraum dient

Der Leistungszeitraum steuert die passive Rechnungsabgrenzung (pRAP, nur Bilanzierer; bei EÜR wird sofort vereinnahmt) und landet als Leistungszeitraum auf der ZUGFeRD-Rechnung. Ein hier mitgeschickter service_period hat Vorrang vor der SaaS-Voreinstellung am Produkt.

Lässt du das Feld weg, greift die Produkt-Voreinstellung (z. B. der am SaaS-Produkt hinterlegte Abrechnungsrhythmus). Der Checkout-Link (/c/…) kennt kein Feld dafür, dort kommt der Zeitraum aus der Produktkonfiguration.

Rückdatierter Leistungszeitraum

Ein start_date, das VOR dem Rechnungsdatum liegt, ist erlaubt. Liegt der Beginn im selben Wirtschaftsjahr, ist das unproblematisch, das Jahresergebnis stimmt.

Beginnt der Zeitraum in einem FRÜHEREN, meist abgeschlossenen Wirtschaftsjahr, legt Rechnungskit (bei Bilanzierung) eine Aufgabe „Leistungszeitraum im Vorjahr“ an. Die bereits vergangenen Monate gehören periodengerecht ins Vorjahr, ggf. ist eine Bilanzberichtigung nötig. Die Rechnung wird trotzdem erstellt, die Aufgabe ist ein Hinweis, keine Blockade.

Fehlender Leistungszeitraum bei zeitbasierten Produkten

Schickst du keinen service_period und ist am Produkt auch keine SaaS-Voreinstellung (Abrechnungszeitraum) hinterlegt, hängt es von der Gewinnermittlung ab:

  • EÜR: Es wird sofort vereinnahmt, es passiert nichts weiter.
  • Bilanzierung: Rechnungskit braucht den Zeitraum für die Rechnungsabgrenzung. Die Rechnung wird dann NICHT sofort erstellt, sondern als Aufgabe „Produkt ohne Umsatzrealisierung“ unter Zu prüfen gehalten. Es wird noch keine Rechnungsnummer vergeben.

Du legst dann die Umsatzrealisierung am Produkt fest (Produkte → Alle Produkte) oder schickst den service_period an der Bestellung nach. Danach wird die Rechnung automatisch erstellt.

Zahlarten über die API

Die Zuordnung von Zahlungen läuft über die Zahlungsanbieter-Anbindungen (Stripe, Mollie, PayPal, Unzer), deine Anwendung liefert die Bestelldaten. Für Kauf auf Rechnung muss das Feld paymentGateway exakt einem unter Verbindungen → Connect hinterlegten Rechnungskauf-Gateway entsprechen. Die Schreibweise zählt.

Überweisung über Stripe (paymentGateway stripe_transfer)

Soll dein Kunde per Überweisung zahlen und das Geld über dein Stripe-Konto ankommen, sendest du die Bestellung mit paymentGateway „stripe_transfer“ und einer E-Mail-Adresse.

stripe_transfer · Ablauf
Überweisung über dein Stripe-Konto
  1. Deine AnwendungBestellung mit stripe_transferplus E-Mail-Adresse
  2. RechnungskitRechnung und ZahlungsauftragLeistung sofort, Ware mit der Versandmeldung
  3. Dein KundeÜberweistan die virtuelle Stripe-IBAN, mit Stripes Referenz als Verwendungszweck
  4. StripeOrdnet zuRechnungskit schließt den offenen Posten
Es entsteht keine Stripe-Rechnung, also auch keine Invoicing-Gebühr, nur die Gebühr für die Überweisung.

So läuft es ab:

  1. Bei einer Leistung entsteht die Rechnung sofort, bei Ware erst mit der Versandmeldung über /v1/fulfillments.
  2. Gleichzeitig legt Rechnungskit in deinem Stripe-Konto einen Zahlungsauftrag für Banküberweisung an.
  3. Auf der Rechnung stehen die virtuelle Stripe-IBAN deines Kunden und, als Verwendungszweck, Stripes Referenz für genau diese Zahlung.
  4. Kommt die Überweisung mit dieser Referenz an, ordnet Stripe das Geld zu, und Rechnungskit schließt den offenen Posten unter /receivables.

Ist die Rechnung bezahlt?

GET /v1/invoices/{reference} und GET /v1/invoices liefern je Beleg einen Block payment mit status (open, partially_paid, paid oder uncollectible), paidCents und openCents. Bei Kauf auf Rechnung und Vorkasse folgt er dem offenen Posten: Er springt auf paid, sobald du die Zahlung in der App unter Offene Posten bestätigst oder eine zugeordnete Überweisung eingeht. Eine Rechnung zu einer Zahlung beim Zahlungsanbieter ist von Anfang an paid. Bei Gutschriften ist der Block null. totals.dueCents ist dagegen der Betrag, der auf der Rechnung steht, und ändert sich nach der Ausstellung nie. Deine Software fragt also payment.status ab, um etwa einen Zugang freizuschalten.

Fehlt einem Produkt die Umsatzrealisierung, antwortet POST /v1/fulfillments mit 200 und invoicesCreated: 0 sowie held.reason: recognition_missing. Die Versandmeldung ist gespeichert, in der App entsteht eine Aufgabe, und sobald das Produkt eingestuft ist, entsteht die Rechnung von selbst.

Weil keine Stripe-Rechnung entsteht, fällt keine Invoicing-Gebühr an, nur die für die Überweisung. Als Überweisungsbetrag gilt das Bestellbrutto, und die Rechnung trifft ihn auf den Cent.

Dafür braucht der Stripe-Schlüssel die Rechte Customers (Schreiben) und Payment Intents (Schreiben). Fehlt eines, entsteht keine Rechnung. Stattdessen bekommst du eine dringende Aufgabe samt E-Mail, und nach dem Ergänzen holt Rechnungskit die Rechnung automatisch nach. Wird der Zahlungsauftrag in Stripe abgebrochen, bevor bezahlt ist, folgt eine Stornorechnung.

Empfehlungsguthaben an der Bestellung: creditRedemptions

Hat dein Kunde für eine Bestellung Empfehlungsguthaben eingesetzt, schickst du den Betrag im optionalen Feld creditRedemptions mit. Es ist eine Liste von Objekten:

Feld Inhalt
type „referral_credit“
amountCents ganze Cent, größer 0
externalRef optional, die Id der Einlösung in deinem System
"creditRedemptions": [{ "type": "referral_credit", "amountCents": 1000, "externalRef": "tx_81" }]

Mit dem Feld ist grossTotalCents Pflicht, und die Summe der Einlösungen darf den Bruttobetrag nicht übersteigen. Sonst antwortet die API mit 422.

Guthaben ist eine Zahlung, kein Rabatt

Die Rechnung weist die Umsatzsteuer auf den vollen Betrag aus, der Guthabenanteil gilt als bereits bezahlt. Die Zahlungsart nennt beide Anteile, etwa „PayPal (37,00 €) und Empfehlungsguthaben (12,00 €)“. Dein Zahlungsanbieter zieht nur den Rest ein. Rabatte gehören weiter in discountNetCents.

Ist die Bestellung komplett mit Guthaben bezahlt, gibt es keine Zahlung beim Anbieter. Dann schickst du financialStatus „paid“, und die Summe der Einlösungen entspricht grossTotalCents. Rechnungskit stellt die Rechnung dann ohne Zahlungseingang aus, bei Ware erst mit der Versandmeldung.

Das Guthaben selbst führt dein Shop. Rechnungskit spiegelt es im Guthabenbuch unter Gutscheine für die Verbindlichkeit und die DATEV-Buchungen und zieht die Einlösung dort vom ältesten Saldo des Kunden ab. Fehlt dort ein passender Saldo, bleibt die Rechnung richtig, und unter Zu prüfen erscheint eine Aufgabe „Empfehlungsguthaben ohne Saldo“.

Guthaben per Push: credit-transactions

Verwaltet deine Anwendung Guthaben selbst, etwa Empfehlungsprämien, meldest du jede Bewegung an POST /v1/credit-transactions, bis zu 500 je Aufruf: { "transactions": [ ... ] }.

Feld Pflicht Inhalt
id ja deine eindeutige Kennung
type ja earn, redeem, reverse, payout oder expire
email ja E-Mail-Adresse des Kunden
amount_cents ja Betrag in Cent
occurred_at ja Zeitpunkt der Bewegung
delta_cents bei reverse Veränderung in Cent
order_ref, reverses_id, payout_ref nein Bezug auf Bestellung, zurückgenommene Bewegung und Auszahlung
hc_booking_date nein das Datum, an dem deine Buchhaltung den Vorgang bisher bucht

Ein wiederholter Aufruf legt nichts doppelt an. Die Antwort nennt neue (accepted) und schon bekannte (duplicates) Transaktionen.

Einmal am Tag meldest du die Salden an PUT /v1/credit-balances:

{ "balances": [{ "email": "...", "balance_cents": 1250 }] }

Rechnungskit vergleicht sie mit dem Verlauf. Weicht ein Kunde ab, entsteht eine Aufgabe, so fällt eine verlorene Meldung auf. Beide Endpunkte brauchen den Scope orders:write. Gebucht wird erst ab dem Stichtag, den du unter Gutscheine festlegst. Die Anleitung steht unter Guthaben aus dem eigenen Shop übernehmen.

Guthabenverlauf lesen lassen (Pull)

Statt zu pushen kann dein Shop den Verlauf bereitstellen, und Rechnungskit liest ihn selbst ab. Dafür stellt dein Shop zwei lesende Endpunkte bereit, geschützt mit einem Token:

Endpunkt in deinem Shop Liefert
GET <adresse>/referral-transactions?since=<cursor>&limit=<n> { "items": [...], "next_cursor": "...", "has_more": true }
GET <adresse>/referral-balances?as_of=<YYYY-MM-DD> den Saldo je Kunde als [{ "email": "...", "balance_cents": 1250 }]

Jeder Eintrag im Verlauf hat id, type (earn, redeem, reverse, payout oder expire), email, amount_cents, occurred_at und optional delta_cents (mit Vorzeichen), order_ref, reverses_id, payout_ref und hc_booking_date. Einträge ändern sich nie, eine Korrektur ist ein neuer Eintrag.

Einrichten und anstoßen

Adresse, Token und Stichtag trägst du unter Gutscheine im Abschnitt „Guthaben aus deinem eigenen Shop“ ein. Die Schritt-für-Schritt-Anleitung mit Probelauf und Stichtag steht unter Guthaben aus dem eigenen Shop übernehmen.

Rechnungskit liest stündlich ab der zuletzt gelesenen Stelle weiter und gleicht danach je Kunde ab: Saldo im Shop gegen die Summe des Verlaufs. Weicht ein Kunde ab, siehst du ihn dort in einer Liste.

Schneller geht es mit einem Anstoß: POST /api/v1/referral-credits/poke mit deinem API-Schlüssel, ohne Inhalt. Rechnungskit liest dann sofort. Geht ein Anstoß verloren, liest der nächste stündliche Lauf trotzdem alles.

Probelauf und Stichtag

Ohne Stichtag ist das ein Probelauf: Rechnungskit liest und gleicht ab, bucht aber nichts. Ab dem Stichtag übernimmt Rechnungskit den Verlauf ins Guthabenbuch. Zum Stichtag legt es je Kunde einen Eröffnungssaldo aus dem bisherigen Verlauf an, ohne Buchung, denn bis dahin hat dein Shop selbst gebucht.

Danach bucht Rechnungskit über die Kontenrollen unter Einstellungen → DATEV:

Bewegung Buchung
Verdienst Aufwand an Verbindlichkeit
Rücknahme umgekehrt
Auszahlung an die Bank
Verfall als Ertrag
Erstattung aufs Guthaben Debitor an Verbindlichkeit

Eine Einlösung bucht Rechnungskit über die Rechnung (Feld creditRedemptions), nicht über den Verlauf. Guthaben, das vor dem Stichtag angelegt und erst danach verfügbar wurde, bucht Rechnungskit nicht noch einmal, wenn hc_booking_date vor dem Stichtag liegt.

Ab dem Stichtag vergleicht der Abgleich den Saldo im Shop mit dem Guthabenbuch. Einlösungen, deren Rechnung noch fehlt, rechnet er heraus. Weicht etwas ab, entsteht eine Aufgabe. Fehlt eine Kontenrolle, erscheint sie im DATEV-Export als fehlende Zuordnung.

Öffentliche Auftraggeber: leitweg_id

Die Rechnungsadresse (billingAddress) nimmt neben vat_id auch leitweg_id an. Ist eine gültige Leitweg-ID gesetzt, wird die Rechnung dieser Bestellung als XRechnung 3.0 erstellt, sonst als ZUGFeRD. Eine formal ungültige Leitweg-ID beantwortet die API mit 422.

Voraussetzung ist eine Telefonnummer im Rechnungskontakt unter Einstellungen. Ohne sie hält Rechnungskit die XRechnung als Aufgabe an.

Testen

Nutze deinen normalen API-Schlüssel im Testmodus. Es ist die gleiche Pipeline, EN-16931-Validierung und PDF-Erstellung inklusive, aber:

  • Testnummernkreis (TEST-...),
  • keine Abrechnung und kein Versand,
  • kein Einfluss auf DATEV, OSS und ZM.

Es gilt Fair Use, Lasttests bitte nicht. Mehr dazu unter Testmodus (Sandbox).

Stornierte Bestellungen melden

Storniert dein Shop eine Bestellung, meldest du das über POST /v1/orders/{orderNo}/cancel, optional mit reason und cancelledAt. Was dann passiert, hängt vom Stand der Bestellung ab.

Stornierung · Antworten
Was die Stornierung je nach Stand bewirkt
Noch kein Beleg
Voll erstattet: Zahlung und Erstattung werden als „storniert + erstattet“ abgelegt, ohne Aufgabe. Liegt das Geld noch bei dir, entsteht eine Aufgabe, bis die Erstattung kommt
Ergebnisnie ein Beleg
Beleg existiert schon
Die Korrektur entsteht aus der Erstattung beim Zahlungsanbieter als Stornorechnung
Antwort409 order_invoiced
Bestellung unbekannt
Nie übermittelt? Dann POST /v1/orders mit status „cancelled“ und paymentRef
Antwort404 order_not_found
Beide Aufrufe darfst du beliebig oft wiederholen.
Stand der Bestellung Was passiert
noch kein Beleg Die Bestellung wird storniert und bekommt nie einen Beleg.
kein Beleg, Zahlung vollständig erstattet Rechnungskit legt Zahlung und Erstattung als „storniert + erstattet“ ab. Weil nie ein Umsatz entstand, gibt es weder Beleg noch Aufgabe.
kein Beleg, das Geld liegt noch bei dir Es entsteht eine Aufgabe, und eine spätere Erstattung legt den Vorgang von selbst ab.
Beleg existiert bereits Die Schnittstelle antwortet mit 409 order_invoiced und ändert nichts. Die Korrektur entsteht aus der Erstattung beim Zahlungsanbieter als Stornorechnung.
Bestellung unbekannt Der Stornierungs-Aufruf antwortet mit 404 order_not_found.

Für eine Bestellung, die vor dem Zahlungsabschluss storniert und deshalb nie übermittelt wurde, schickst du POST /v1/orders mit "status": "cancelled" und der paymentRef. Darüber findet Rechnungskit die Zahlung samt automatischer Erstattung und legt beide ab. Beide Aufrufe darfst du beliebig oft wiederholen.

Zustell-Kontrakt (Pflicht für Integratoren)

Dein System muss fehlgeschlagene Pushes wiederholen. Das heißt konkret:

  1. Jeder 5xx- oder Netzwerkfehler ist transient. Auch Deployments verursachen kurze 502-Fenster.
  2. Wiederhole mit exponentiellem Backoff über mindestens 24 Stunden.
  3. Zusätzlich empfohlen: ein täglicher Abgleichs-Job, der alles erneut sendet, was dein System als fehlgeschlagen markiert hat.

Wiederholungen sind immer sicher: Bestellungen sind idempotent über orderNo, der Idempotency-Key-Header dedupliziert parallele Zustellungen.

Typischer Fehlerfall ohne Retry: Die Zahlung kommt an (der Zahlungsanbieter wiederholt automatisch), der Bestell-Push scheitert an einem einzigen 502. Die Zahlung bleibt dann als „Keine Bestellung“ in der Klärung liegen, bis die Bestellung nachgereicht wird.

Grenzen, ehrlich benannt

  • Fehlerantworten folgen den üblichen Codes (400/401/403/404/409/422/429/503), bei 429/503 mit Retry-After. Baue Backoff ein.
  • Anfragen sind über die Request-ID 30 Tage in der API-Aktivität nachvollziehbar.

So findest du es in der App

Rechnungskit ist keine Steuerberatung und keine Rechtsberatung. Dieser Beitrag erklärt allgemeine Zusammenhänge und ersetzt weder die Beratung durch deine Steuerkanzlei (§ 5 StBerG) noch eine Rechtsberatung (§ 3 RDG). Rechnungskit richtet sich an in Deutschland ansässige Unternehmen und bereitet Belege, Steuersätze und Buchungen automatisch auf. Wie dein Einzelfall zu bewerten ist, entscheidest du, im Zweifel gemeinsam mit deiner Steuerkanzlei oder einer Anwaltskanzlei.

de en