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_live_…application/json · integer centsQuickstart
Erstelle unter Einstellungen → 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) |
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.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:readMaschinenlesbare 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 hat einen Testmodus: Ein Klick in den Projekteinstellungen erstellt ein
separates Sandbox-Projekt mit eigenen rk_test_…-Schlüsseln. Die Sandbox nutzt
dieselbe API und dieselbe Pipeline wie die Produktion, inklusive EN-16931-Validierung und
PDF/A-3-Rendering. Du testest also exakt das Verhalten, das später live läuft.
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.
rk_test_…-Schlüssel und wechsle erst danach den Schlüssel auf rk_live_…. Der Code bleibt identisch; nur der Schlüssel entscheidet, ob
Belege echt sind. Die Sandbox ist für Integrations- und Abnahmetests gedacht (Fair Use),
nicht für Lasttests.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.