Zum Inhalt springen

REST · JSON · OpenAPI 3.1 · v1

Rechnungskit API

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.

BASE URLhttps://api.rechnungskit.de/v1
AUTHAuthorization: Bearer rk_key_…
FORMATapplication/json · integer cents

Quickstart

Ein Schlüssel, zwei Berechtigungen

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.

Empfehlung: Nutze für eine fest verbaute Produktionsintegration einen unbefristeten Schlüssel. Erstelle getrennte Schlüssel je Umgebung und System und vergib nur benötigte Scopes. Zeitlich begrenzte Schlüssel sind für Tests oder Übergänge gedacht. Rotation ist ohne Downtime möglich, weil mehrere Schlüssel parallel aktiv sein können.

Integrationsablauf

Deine Referenz bleibt der rote Faden

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.

  1. 1
    Bestellung senden

    Deine orderNo wird zum stabilen Korrelationsschlüssel.

  2. 2
    Zahlung oder Erfüllung

    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.

  3. 3
    Status abfragen

    GET /v1/orders/{orderNo} liefert die zugeordneten Rechnungen.

  4. 4
    Exakte Beleg-ID übernehmen

    Speichere die zurückgegebene Invoice-UUID oder Belegnummer für diesen Beleg.

  5. 5
    Dokument laden

    PDF und XML bleiben Bearer-geschützt und werden serverseitig abgerufen.

1 · Bestellung

Bestellung idempotent senden

Jeder POST benötigt einen stabilen Idempotency-Key. Bei einem Timeout kannst du dieselbe Anfrage mit demselben Key wiederholen, ohne eine zweite Bestellung anzulegen.

Für SaaS und digitale Leistungen ist dieser Aufruf der einzige, den du brauchst. Lass 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.
cURLPOST /v1/orders
curl 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
    }]
  }'
201 CreatedBestellung angenommen
{
  "data": {
    "id": "6d754aec-40d9-4c1a-a78c-50dbb6c8e307",
    "orderNo": "CM-10482",
    "status": "created"
  },
  "requestId": "9d61558e-3c00-465d-b980-c074db600047"
}
Die hier zurückgegebene data.id ist die interne Bestellungs-ID, nicht die spätere Rechnungs-ID. Für deinen Ablauf bleibt CM-10482 maßgeblich.

Pflichtangaben

FeldTypHinweis
orderNostringIn deinem Projekt dauerhaft eindeutig
billingAddressobjectLand immer; vollständige Anschrift für reguläre Rechnungen
items[]arrayMindestens eine Position
unitNetCents oder unitGrossCentsintegerGeldbeträge ausschließlich in Cent

Optionale Felder

FeldTypHinweis
billingAddress.leitweg_idstring?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
discountNetCentsinteger?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
shippingGrossCentsinteger?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
paymentRefstring?Eindeutige Provider-Referenz für Payment-Matching
requiresShippingboolean?true hält physische Ware bis zur Erfüllung zurück
service_periodobject?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

Versand oder Leistungserfüllung melden

Bei physischer Ware ist das Versanddatum das relevante Leistungsdatum. Melde daher den vollständigen Versand. Teilfulfillments erzeugen noch keinen vollständigen Beleg.

SaaS und digitale Leistungen: diesen Schritt komplett weglassen. Ohne 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.
cURLPOST /v1/fulfillments
curl 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

So erhältst du die Rechnungs-ID

Frage den Status mit deiner eigenen Bestellnummer ab. Sobald eine Rechnung angelegt wurde, enthält invoices[] ihre UUID, Belegnummer und ihren Archivstatus.

cURLGET /v1/orders/CM-10482
curl https://api.rechnungskit.de/v1/orders/CM-10482 \
  -H "Authorization: Bearer $RK_API_KEY"
200 OKRechnung 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.

cURLGET /v1/invoices/{id}/pdf
curl https://api.rechnungskit.de/v1/invoices/f77ba43d-6f06-4b84-bd24-5cfab76a1192/pdf \
  -H "Authorization: Bearer $RK_API_KEY" \
  --output RK-2026-0148.pdf
{reference} akzeptiert: Invoice-UUIDBelegnummerBestellnummerZahlungsreferenz
Eine Bestellnummer kann nach einem Storno mehrere Belege haben. Ein direkter Abruf über /invoices/CM-10482 liefert den neuesten Beleg. Für einen exakten Original- oder Korrekturbeleg immer die UUID aus invoices[] verwenden.

Alternative · Rechnungskauf

Rechnung zuerst, Zahlung später

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.

JSON-AuszugPOST /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 v1 Endpunkte

GET /api/health

Prozess- und Datenbankstatus

öffentlich
GET /v1

API-Discovery und verfügbare Endpunkte

öffentlich
POST /v1/orders

Bestellung idempotent anlegen oder aktualisieren

orders:write
GET /v1/orders/{orderNo}

Bestell-, Fulfillment- und Rechnungsstatus abrufen

invoices:read
POST /v1/fulfillments

Versand oder Leistungserfüllung melden

orders:write
GET /v1/invoices

Rechnungen filtern und per Cursor paginieren

invoices:read
GET /v1/invoices/{reference}

Metadaten über UUID, Beleg-, Bestell- oder Zahlungsreferenz

invoices:read
GET /v1/invoices/{reference}/pdf

Archiviertes PDF herunterladen

invoices:read
GET /v1/invoices/{reference}/xml

Archiviertes EN-16931-XML herunterladen

invoices:read

Fehler & Wiederholungen

Jede Antwort trägt eine Request-ID

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.

422 Unprocessable Entityvalidation_failed
{
  "error": {
    "code": "validation_failed",
    "message": "billingAddress.country_code is required for VAT determination",
    "field": "billingAddress.country_code"
  },
  "requestId": "9d61558e-3c00-465d-b980-c074db600047"
}
StatusBedeutungReaktion
400/422Request oder Fachfelder ungültigNicht blind wiederholen; Daten korrigieren
401/403Key ungültig oder Scope fehltKey und Berechtigungen prüfen
404Bestellung oder Beleg noch nicht vorhandenBei asynchronem Ablauf mit Backoff erneut prüfen
409Konflikt oder Dokument noch nicht archiviertAntwortcode auswerten und später erneut abrufen
429/503Temporär nicht verfügbarRetry-After beachten, exponentieller Backoff
5xxTransienter Serverfehler (z. B. während eines Deployments)Pflicht: mit Backoff wiederholen, mindestens 24 Stunden lang
Zustell-Kontrakt (Pflicht): Dein System muss fehlgeschlagene Pushes wiederholen. Jeder 5xx- oder Netzwerkfehler ist transient; wiederhole mit exponentiellem Backoff über mindestens 24 Stunden. Wiederholungen sind immer sicher: Bestellungen sind idempotent über 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

Erst testen, dann live gehen

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.

Empfehlung: Baue deine Integration komplett im Testmodus und geh dann live. Code und Schlüssel bleiben identisch; ob Belege echt sind, entscheidet allein der Go-Live deines Projekts, nie der Schlüssel. Der Testmodus ist für Integrations- und Abnahmetests gedacht (Fair Use), nicht für Lasttests.

Sicherheit

Secrets bleiben im Backend

  • API-Schlüssel nie in Browser-, Mobile- oder öffentliches Repository einbauen.
  • Schlüssel in Secret-Manager oder verschlüsselten Umgebungsvariablen speichern.
  • Unbefristete Produktionsschlüssel bewusst rotieren; kurze Laufzeiten nur für Tests oder Übergänge verwenden.
  • Schlüssel, die länger als 90 Tage nicht verwendet wurden, in der API-Einstellung prüfen und bei nicht mehr benötigten Integrationen widerrufen.
  • Bei Verdacht sofort einen neuen Schlüssel anlegen, ausrollen und den alten widerrufen.
  • Dokumente serverseitig abrufen; keine dauerhaften Bearer-Links an Kunden geben.
Health Check

status: ok bestätigt den Prozess, db: true zusätzlich die Datenbankverbindung. Prüfe beide Werte, nicht nur HTTP 200.

/api/health ↗

Bereit?

Erstelle deinen ersten API-Schlüssel

Projektgebunden erstellt, die vollständige Zeichenfolge wird nur einmal angezeigt.

Zu den API-Einstellungen
de