orders:write Bestellungen & Fulfillment Erlaubt ausschließlich das Melden von Verkaufs- und Erfüllungsdaten.
REST · JSON · OpenAPI 3.1 · v1
POST /orders sendet Bestellungen, POST /fulfillments meldet den
Versand. Daraus entstehen validierte ZUGFeRD-Rechnungen mit GoBD-Archiv und DATEV-Export.
Bearer-Auth, Integer-Cents, idempotent über deine orderNo; PDF und XML per GET.
https://api.rechnungskit.de/v1Authorization: Bearer rk_key_…application/json · integer centsQuickstart
Erstelle unter Verbindungen → API einen projektgebundenen Schlüssel. Der vollständige Schlüssel wird genau einmal angezeigt und gehört ausschließlich in dein Backend oder Secret-Management.
orders:write Bestellungen & Fulfillment Erlaubt ausschließlich das Melden von Verkaufs- und Erfüllungsdaten.
invoices:read Status & Dokumente Erlaubt das Lesen von Rechnungsmetadaten sowie PDF und XML.
Integrationsablauf
Du musst keine interne Rechnungskit-ID kennen. Nutze eine dauerhaft eindeutige orderNo und – bei Zahlung über Stripe, Mollie oder einen anderen Provider –
dessen eindeutige paymentRef.
Deine orderNo wird zum stabilen Korrelationsschlüssel.
Zahlungswebhook matcht über paymentRef. Nur physische Ware (requiresShipping: true) wartet auf Fulfillment; SaaS und digitale Leistungen überspringen diesen Schritt,
die Rechnung entsteht direkt mit der Zahlung.
GET /v1/orders/{orderNo} liefert die zugeordneten Rechnungen.
Speichere die zurückgegebene Invoice-UUID oder Belegnummer für diesen Beleg.
PDF und XML bleiben Bearer-geschützt und werden serverseitig abgerufen.
1 · Bestellung
Jeder POST benötigt einen stabilen Idempotency-Key. Bei einem Timeout kannst
du dieselbe Anfrage mit demselben Key wiederholen, ohne eine zweite Bestellung anzulegen.
requiresShipping einfach weg (Standard false): Es gibt dann
keine Erfüllungs-Wartestufe, Schritt 2 (/v1/fulfillments) entfällt komplett.
Schick paymentRef mit; sobald die Zahlung deines Zahlungsanbieters zur Bestellung
passt, entsteht die Rechnung automatisch. Ein eigenes „bezahlt“-Feld gibt es bewusst nicht:
Den Zahlungsstatus liefert der angebundene Zahlungsanbieter, nicht der Sender.POST /v1/orderscurl https://api.rechnungskit.de/v1/orders \
-X POST \
-H "Authorization: Bearer $RK_API_KEY" \
-H "Idempotency-Key: order:CM-10482:v1" \
-H "Content-Type: application/json" \
-d '{
"orderNo": "CM-10482",
"paymentRef": "pi_3PqK8w2eZvKYlo2C",
"currency": "EUR",
"requiresShipping": false,
"billingAddress": {
"name": "Lisa Brandt",
"street": "Torstraße 99",
"postal_code": "10119",
"city": "Berlin",
"country_code": "DE"
},
"service_period": {
"start_date": "2026-06-01",
"end_date": "2026-06-30"
},
"items": [{
"name": "Monatsabo Pro · Juni 2026",
"sku": "saas-pro",
"quantity": 1,
"unitNetCents": 4118,
"discountNetCents": 500,
"taxRate": 19
}]
}'Bestellung angenommen{
"data": {
"id": "6d754aec-40d9-4c1a-a78c-50dbb6c8e307",
"orderNo": "CM-10482",
"status": "created"
},
"requestId": "9d61558e-3c00-465d-b980-c074db600047"
}data.id ist die interne Bestellungs-ID, nicht die spätere Rechnungs-ID. Für deinen Ablauf bleibt CM-10482 maßgeblich.| Feld | Typ | Hinweis |
|---|---|---|
orderNo | string | In deinem Projekt dauerhaft eindeutig |
billingAddress | object | Land immer; vollständige Anschrift für reguläre Rechnungen |
items[] | array | Mindestens eine Position |
unitNetCents oder unitGrossCents | integer | Geldbeträge ausschließlich in Cent |
| Feld | Typ | Hinweis |
|---|---|---|
billingAddress.leitweg_id | string? | Nur für öffentliche Auftraggeber (Behörde, Kommune, Hochschule): ihre Leitweg-ID. Ist sie gesetzt, entsteht die
Rechnung dieser Bestellung als XRechnung 3.0 (reines XML mit PDF-Lesefassung)
statt als ZUGFeRD. Format 2 bis 12 Ziffern, optionale Feinadressierung,
zweistellige Prüfziffer, mit Bindestrich getrennt (z. B. 04011000-1234512-68); formal ungültig antwortet die API mit 422 und field: "billingAddress.leitweg_id".
Voraussetzung ist eine Telefonnummer im Rechnungskontakt (XRechnung-Regel
BR-DE-6), sonst hält Rechnungskit die Rechnung als Aufgabe an |
discountNetCents | integer? | Netto-Rabatt je Position (ZUGFeRD BG-27); Stückpreis bleibt unrabattiert. Nur für echte Rabatte; Guthaben-Einlösungen sind eine Zahlart, nie ein Rabatt |
shippingGrossCents | integer? | Versand wie bezahlt (brutto); Rechnungskit bestimmt die Steuer als Nebenleistung;
gemischte Warenkörbe werden nach Brutto-Verhältnis aufgeteilt (BFH
XI R 22/22). Alternativ shippingNetCents + shippingTaxRate, wenn dein Checkout
die Versandsteuer bereits berechnet |
paymentRef | string? | Eindeutige Provider-Referenz für Payment-Matching |
requiresShipping | boolean? | true hält physische Ware bis zur Erfüllung zurück |
service_period | object? | Leistungszeitraum für zeitbasierte Leistungen (SaaS, Abos): start_date und end_date als ISO-Datum (YYYY-MM-DD), beide zusammen oder keins. Steuert die Rechnungsabgrenzung (pRAP) direkt und
hat Vorrang vor der Produkt-Voreinstellung. Ein start_date vor dem
Rechnungsdatum ist erlaubt; liegt es in einem früheren (meist abgeschlossenen)
Wirtschaftsjahr, legt Rechnungskit bei Bilanzierung eine Prüf-Aufgabe an
(periodengerechte Zuordnung ins Vorjahr), erstellt die Rechnung aber trotzdem.
Ohne service_period und ohne SaaS-Voreinstellung am Produkt wird bei Bilanzierung
noch keine Rechnung erstellt: Die Bestellung wartet als Aufgabe „Produkt ohne Umsatzrealisierung",
bis du die Umsatzrealisierung am Produkt festlegst oder den Zeitraum nachreichst (bei
EÜR entfällt das, es wird sofort vereinnahmt) |
creditRedemptions | array? | Eingesetztes Empfehlungsguthaben: [{ "type": "referral_credit", "amountCents": 1000, "externalRef": "tx_81"
}]. Guthaben ist eine Zahlung, kein Rabatt: Die Rechnung weist die Umsatzsteuer auf
den vollen Betrag aus und zeigt den Guthabenanteil als bezahlt, dein
Zahlungsanbieter zieht nur den Rest ein. Braucht grossTotalCents, die
Summe darf ihn nicht übersteigen. Deckt das Guthaben alles ab (Summe = grossTotalCents, financialStatus „paid“), entsteht die Rechnung ohne Zahlungseingang |
2 · Erfüllung
Bei physischer Ware ist das Versanddatum das relevante Leistungsdatum. Melde daher den vollständigen Versand. Teilfulfillments erzeugen noch keinen vollständigen Beleg.
requiresShipping (Standard false) gibt es keine
Erfüllungs-Wartestufe: Die Rechnung entsteht, sobald die Zahlung des Zahlungsanbieters zur
Bestellung passt. POST /v1/orders mit paymentRef ist dann der
einzige nötige Aufruf; /v1/fulfillments wird nie aufgerufen. Ein eigenes „bezahlt“-Feld
gibt es bewusst nicht: Den Zahlungsstatus liefert der angebundene Zahlungsanbieter, nicht der
Sender.POST /v1/fulfillmentscurl https://api.rechnungskit.de/v1/fulfillments \
-X POST \
-H "Authorization: Bearer $RK_API_KEY" \
-H "Idempotency-Key: fulfillment:CM-10482:fulfilled:v1" \
-H "Content-Type: application/json" \
-d '{
"orderNo": "CM-10482",
"status": "fulfilled",
"shippedAt": "2026-07-27T10:30:00Z",
"trackingNumber": "003404341612"
}'3 · Status & Dokumente
Frage den Status mit deiner eigenen Bestellnummer ab. Sobald eine Rechnung angelegt wurde,
enthält invoices[] ihre UUID, Belegnummer und ihren Archivstatus.
GET /v1/orders/CM-10482curl https://api.rechnungskit.de/v1/orders/CM-10482 \ -H "Authorization: Bearer $RK_API_KEY"
Rechnung gefunden{
"data": {
"orderNo": "CM-10482",
"status": "invoiced",
"fulfillmentStatus": "fulfilled",
"invoices": [{
"id": "f77ba43d-6f06-4b84-bd24-5cfab76a1192",
"number": "RK-2026-0148",
"status": "archived",
"url": "/v1/invoices/f77ba43d-6f06-4b84-bd24-5cfab76a1192"
}]
},
"requestId": "3a61c30d-4386-4c60-9354-841342cbc372"
}Verwende anschließend die UUID, wenn du einen ganz bestimmten Beleg herunterladen willst. Das ist bei Stornos oder mehreren Dokumenten zu einer Bestellung eindeutig.
GET /v1/invoices/{id}/pdfcurl https://api.rechnungskit.de/v1/invoices/f77ba43d-6f06-4b84-bd24-5cfab76a1192/pdf \ -H "Authorization: Bearer $RK_API_KEY" \ --output RK-2026-0148.pdf
/invoices/CM-10482 liefert den neuesten Beleg. Für einen exakten Original- oder Korrekturbeleg immer die UUID aus invoices[] verwenden.Alternative · Rechnungskauf
Bei Kauf auf Rechnung gibt es zunächst keine Provider-Zahlung. Sende stattdessen den in Rechnungskit unter Connect freigegebenen Gateway-Namen. Nach vollständigem Fulfillment entsteht die Rechnung mit offenem Posten und Zahlungsziel.
POST /v1/orders{
"orderNo": "CM-10483",
"paymentGateway": "invoice",
"financialStatus": "pending",
"requiresShipping": true,
"billingAddress": { "...": "vollständige Rechnungsanschrift" },
"items": [ "..." ]
}paymentGateway muss exakt zu einem unter Connect → Rechnungskauf aktivierten Gateway passen. Ohne passende Zahlung oder
freigegebenes Invoice-first-Gateway bleibt die Bestellung bewusst ohne Rechnung.Guthaben · Push
Verwaltet deine Anwendung Guthaben selbst, etwa Empfehlungsprämien, schickst du jede
Bewegung an POST /v1/credit-transactions: Verdienen (earn),
Einlösen (redeem), Rücknahme (reverse), Auszahlung (payout) und Verfall (expire). Jede Transaktion trägt deine eindeutige id; ein wiederholter Aufruf legt nichts doppelt an. Bis zu 500 je Aufruf.
POST /v1/credit-transactions{
"transactions": [
{
"id": "tx_81",
"type": "earn",
"email": "kundin@example.com",
"amount_cents": 500,
"occurred_at": "2026-10-02T09:14:00+02:00",
"order_ref": "103002"
},
{
"id": "tx_82",
"type": "redeem",
"email": "kundin@example.com",
"amount_cents": 500,
"occurred_at": "2026-10-05T18:40:00+02:00",
"order_ref": "103950"
}
]
}200{ "accepted": 2, "duplicates": 0, "applied": 1 }Einmal am Tag meldest du die Salden je Kunde 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 auch eine verlorene Meldung auf.
creditRedemptions, damit die Rechnung
ihn als bezahlt zeigt. Details: Guthaben aus dem eigenen Shop.Referenz
/api/health Prozess- und Datenbankstatus
öffentlich/v1 API-Discovery und verfügbare Endpunkte
öffentlich/v1/orders Bestellung idempotent anlegen oder aktualisieren
orders:write/v1/orders/{orderNo} Bestell-, Fulfillment- und Rechnungsstatus abrufen
invoices:read/v1/fulfillments Versand oder Leistungserfüllung melden
orders:write/v1/invoices Rechnungen filtern und per Cursor paginieren
invoices:read/v1/invoices/{reference} Metadaten über UUID, Beleg-, Bestell- oder Zahlungsreferenz
invoices:read/v1/invoices/{reference}/pdf Archiviertes PDF herunterladen
invoices:read/v1/invoices/{reference}/xml Archiviertes EN-16931-XML herunterladen
invoices:read/v1/credit-transactions Guthaben-Bewegungen melden (Push), je id genau einmal
orders:write/v1/credit-balances Salden je Kunde für den Abgleich melden
orders:writeMaschinenlesbare Referenz: OpenAPI 3.1 herunterladen ↗
Fehler & Wiederholungen
Der Header X-Request-Id und das JSON-Feld requestId identifizieren dieselbe Anfrage. Du findest sie 30 Tage lang in der API-Aktivität
deines Projekts.
validation_failed{
"error": {
"code": "validation_failed",
"message": "billingAddress.country_code is required for VAT determination",
"field": "billingAddress.country_code"
},
"requestId": "9d61558e-3c00-465d-b980-c074db600047"
}| Status | Bedeutung | Reaktion |
|---|---|---|
400/422 | Request oder Fachfelder ungültig | Nicht blind wiederholen; Daten korrigieren |
401/403 | Key ungültig oder Scope fehlt | Key und Berechtigungen prüfen |
404 | Bestellung oder Beleg noch nicht vorhanden | Bei asynchronem Ablauf mit Backoff erneut prüfen |
409 | Konflikt oder Dokument noch nicht archiviert | Antwortcode auswerten und später erneut abrufen |
429/503 | Temporär nicht verfügbar | Retry-After beachten, exponentieller Backoff |
5xx | Transienter Serverfehler (z. B. während eines Deployments) | Pflicht: mit Backoff wiederholen, mindestens 24 Stunden lang |
orderNo, der Idempotency-Key-Header dedupliziert
parallele Zustellungen. Empfehlung zusätzlich: ein täglicher Abgleichs-Job, der alles
erneut sendet, was dein System als fehlgeschlagen markiert hat. Der klassische Fehlerfall
ist eine Zahlung, die dank PSP-Retry ankommt, während der eigene Bestell-Push ohne
Wiederholung an einem einzigen 502 scheitert; die Rechnung kann dann nicht entstehen.Sandbox
Jedes Konto startet im Testmodus, mit derselben API, derselben Pipeline und demselben rk_key_…-Schlüssel wie im Echtbetrieb, inklusive EN-16931-Validierung und
PDF/A-3-Rendering. Du testest also exakt das Verhalten, das später live läuft — mit dem
Schlüssel, der auch live gilt.
TEST-2026-0001 Eigener Nummernkreis Testbelege sind unübersehbar als Testbeleg gekennzeichnet, in PDF und XML, und laufen in einem eigenen TEST-Nummernkreis.
0,00 € Ohne Abrechnung Testbelege zählen nicht in die Abrechnung und tauchen weder im DATEV-Export noch in OSS- oder ZM-Auswertungen auf.
isoliert Kein Versand, keine Wirkung Rechnungsversand ist in der Sandbox gesperrt; Testbelege haben keine steuerliche Wirkung und lassen sich jederzeit per Reset verwerfen.
Sicherheit
status: ok bestätigt den Prozess, db: true zusätzlich die Datenbankverbindung. Prüfe beide Werte, nicht nur HTTP
200.
Bereit?
Projektgebunden erstellt, die vollständige Zeichenfolge wird nur einmal angezeigt.