Zum Inhalt springen

Für Entwickler

SaaS an die Buchhaltung anbinden: Kunden, Entwürfe, Webhooks

Zuletzt geprüft SUPPORTED WITH LIMITATIONS

Übersetzung der englischen Fassung, die als Erste gepflegt wird. Rechtliche Angaben beziehen sich auf die genannten Quellen und ihr Lesedatum.

Ein SaaS-Produkt mit KRONENWERK an die Buchhaltung anzubinden bedeutet vier Dinge: je zahlendem Konto einen Kunden anlegen, für jedes abrechenbare Ereignis einen Vorgang und einen Rechnungsentwurf mit einem aus Ihrem eigenen Datensatz abgeleiteten Idempotency-Key eröffnen, invoice.issued, invoice.paid und payment.recorded an einem Webhook-Endpunkt empfangen und mit GET /reports/outstanding abstimmen. Die API stellt keine Rechnungen aus und erfasst keine Zahlungen; das tut eine Person im Produkt, und die Ereignisse teilen Ihrem System mit, was geschehen ist. Das ist die ehrliche Gestalt der Integration, und diese Seite zeigt sie Schritt für Schritt.

Was die Integration automatisieren kann und was nicht

Die KRONENWERK-API legt wiederherstellbare Datensätze an und liest die Bücher. Sie führt die unumkehrbaren Handlungen nicht aus – eine Rechnung ausstellen, eine Zahlung erfassen, stornieren –, weil jede davon etwas verbraucht, das sich nicht zurückholen lässt, oder Geld im Hauptbuch bewegt. Für ein SaaS-Backend ist das eine Randbedingung, die Sie kennen sollten, bevor Sie entwerfen.

Ihr EreignisWas Ihre App tutWas im Produkt geschiehtWas zurückkommt
Konto registriert sich oder wechselt auf einen bezahlten PlanPOST /customersDer Kunde erscheint in den Stammdaten mit einer Partnernummer201 mit id und number des Kunden
Vertrag oder Bestellung wird vereinbartPOST /transactionsEin Vorgang (ein Auftrag mit Phase und Fälligkeitsdatum) erscheint auf dem Board des Unternehmens201 mit number wie V2026-0481
Abrechnungszeitraum eines B2B-Kontos wird fälligPOST /invoices/draftsEin Entwurf wartet auf Positionen und die Ausstellung durch eine Person201 mit dem Entwurf; später invoice.issued
Kunde zahlt (Karte, Überweisung)Nichts auf der APIDie Zahlung wird im Produkt erfasst: manuell oder aus dem verbundenen Bankkonto zugeordnetpayment.recorded und, wenn die Forderung ausgeglichen ist, invoice.paid
Erstattung oder Reklamation macht eine Rechnung rückgängigNichts auf der APIEine Person stellt eine vollständige Korrektur ausinvoice.cancelled mit Nennung der Gutschrift
Prüfung zum MonatsendeGET /reports/outstanding, GET /invoices?status=OPENHeute offene Forderungen und Verbindlichkeiten; die offenen Rechnungen

Die API ist Teil des Enterprise-Plans; die gesamte Schnittstelle steht auf der Seite zur Buchhaltungs-API. Die betriebswirtschaftliche Seite der Buchführung eines Abonnementunternehmens – passive Rechnungsabgrenzung, Umsatzsteuer auf digitale Dienstleistungen, mehrere Währungen – wird in Buchhaltung für SaaS und Eine App mit der Buchhaltung verbinden behandelt.

Muster 1: ein Kunde je zahlendem Konto, idempotent angelegt

Legen Sie den KRONENWERK-Kunden an, wenn ein Konto zum zahlenden Kunden wird, nicht bei der Registrierung, und verwenden Sie Ihre eigene Kontokennung im Idempotency-Key. Ein Wiederholungsversuch nach einer verlorenen Antwort liefert dann den angelegten Kunden zurück statt eines Duplikats – und ein doppelter Kunde ist der Fehler, den niemand bemerkt, bis eine Rechnung an den falschen Datensatz geht.

curl -X POST https://kronenwerk.org/api/extern/v1/customers \
  -H "Authorization: Bearer greif_live_…" \
  -H "Idempotency-Key: account-88213" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Beispiel GmbH",
    "email": "billing@example.de",
    "street": "Musterstraße 1",
    "postalCode": "10115",
    "city": "Berlin",
    "country": "DE",
    "vatId": "DE123456789",
    "currency": "EUR"
  }'

Name, Straße, Postleitzahl und Ort sind Pflicht – die EN 16931 führt eine Adresse in Einzelteilen, und an einen Kunden ohne Straße lässt sich keine Rechnung adressieren. Land, USt-IdNr. und Währung sind optional; ein fehlendes Land wird mit dem des eigenen Unternehmens vorbelegt. Speichern Sie die zurückgegebene id zu Ihrem Konto. Die USt-IdNr. ist wichtiger, als sie aussieht: Bei der Ausstellung prüft KRONENWERK sie gegen VIES und leitet daraus das Steuerurteil ab (zum Beispiel Reverse Charge für einen Unternehmerkunden in einem anderen EU-Land). Erheben Sie sie im Checkout.

Muster 2: ein Vorgang je Bestellung, mit Ihren Kennungen darin

Ein Vorgang in KRONENWERK ist eine Arbeitseinheit mit Titel, Kunde, einer Phase aus dem eigenen Workflow des Unternehmens und einem Fälligkeitsdatum – eine Bestellung, ein Projekt, ein Abonnementzeitraum. Er trägt kein Geld, und genau deshalb ist er der richtige Datensatz für „etwas Abrechenbares ist passiert“, bevor jemand entschieden hat, was auf der Rechnung stehen wird. Schreiben Sie Ihre Anbieterkennungen in die Beschreibung, damit die Person, die später die Rechnung ausstellt, das Stripe-Abonnement oder die Bestellung mit einer einzigen Suche findet.

curl -X POST https://kronenwerk.org/api/extern/v1/transactions \
  -H "Authorization: Bearer greif_live_…" \
  -H "Idempotency-Key: sub_1Q…-2026-09" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Team plan, September 2026 — Beispiel GmbH",
    "customerId": "3f2b…",
    "description": "Stripe subscription sub_1Q…, invoice in_1Q…, 12 seats",
    "dueOn": "2026-09-30"
  }'

Nur title ist Pflicht. stage kann einen Phasenschlüssel des Unternehmens-Workflows nennen; fehlt er, beginnt der Vorgang dort, wo der Workflow beginnt. Die Antwort enthält id, number, title, stage, customer, dueOn, archived und createdAt. GET /transactions?search=sub_1Q… findet ihn wieder. Beachten Sie, dass dies keine Buchung im Hauptbuch ist: Nichts wird gebucht, bis im Produkt eine Rechnung ausgestellt oder eine Zahlung erfasst wird.

Muster 3: ein Rechnungsentwurf für jedes B2B-Abrechnungsereignis

Für Geschäftskunden, die eine ordentliche Rechnung brauchen – eine XRechnung für einen deutschen öffentlichen Auftraggeber, ein Peppol-Dokument für einen belgischen, eine Factur-X für einen französischen –, starten Sie einen Entwurf, wenn der Abrechnungszeitraum fällig wird. Der Entwurf trägt den Nummerierungsvorschlag des Verkäufers und die Zahlungsbedingungen des Kunden; eine Person fügt die Positionen hinzu und stellt ihn aus, und die strukturierte Datei wird in diesem Moment erzeugt und validiert. Warum die Grenze beim Entwurf gezogen wird, erklärt die Seite zur Rechnungs-API.

curl -X POST https://kronenwerk.org/api/extern/v1/invoices/drafts \
  -H "Authorization: Bearer greif_live_…" \
  -H "Idempotency-Key: in_1Q…" \
  -H "Content-Type: application/json" \
  -d '{ "customerId": "3f2b…" }'

Verwenden Sie die Rechnungskennung des Anbieters als Schlüssel: eine Stripe-Rechnung, ein KRONENWERK-Entwurf, egal wie oft der auslösende Webhook zugestellt wird. Wenn Ihr Produkt Verbraucher statt Unternehmen abrechnet, brauchen Sie möglicherweise gar keinen Entwurf je Zahlung; eine periodische Zusammenfassung, die im Produkt bearbeitet wird, passt oft besser, und ob ein Verkauf an Verbraucher in einem bestimmten Land eine Einzelrechnung erfordert, erfordert fachliche Bestätigung.

Muster 4: Webhooks empfangen, prüfen, deduplizieren, schnell antworten

Registrieren Sie im Produkt einen HTTPS-Endpunkt auf Port 443 und abonnieren Sie invoice.issued, invoice.paid, invoice.cancelled und payment.recorded. Jede Zustellung trägt KRONENWERK-Signature: t=<seconds>,v1=<hex> – ein HMAC-SHA256 über den Zeitstempel, einen Punkt und den rohen Body – sowie eine stabile Ereignis-ID in KRONENWERK-Event-Id und Idempotency-Key. Der Body ist ein flaches JSON-Objekt, dessen Werte Zeichenketten sind, mit sortierten Schlüsseln, wobei event und id immer vorhanden sind.

POST /hooks/kronenwerk HTTP/1.1
Content-Type: application/json; charset=utf-8
KRONENWERK-Event: invoice.paid
KRONENWERK-Event-Id: 0d3c…
KRONENWERK-Delivery: 61af…
KRONENWERK-Attempt: 1
Idempotency-Key: 0d3c…
KRONENWERK-Signature: t=1788768000,v1=9f2c…
User-Agent: KRONENWERK-Webhooks/1

{"amountDueMinor":"0","buyerName":"Beispiel GmbH","currency":"EUR","documentType":"INVOICE","dueDate":"2026-09-17","event":"invoice.paid","grossMinor":"105910","id":"0d3c…","invoiceId":"7a90…","issueDate":"2026-09-03","netMinor":"89000","number":"2026-0042","paidOn":"2026-09-10","paymentState":"PAID","taxMinor":"16910"}

Die Verarbeitungsregeln sind dieselben, die Stripe für seine eigenen Webhooks dokumentiert, und aus denselben Gründen: Prüfen Sie die Signatur gegen den rohen Body, bevor Sie parsen, lehnen Sie einen Zeitstempel außerhalb Ihrer Toleranz ab (der eigene Verifizierer von KRONENWERK verwendet fünf Minuten), protokollieren Sie die Ereignis-ID und überspringen Sie alles, was Sie schon gesehen haben, verlassen Sie sich nicht auf die Reihenfolge, und antworten Sie schnell mit 2xx und erledigen Sie die Arbeit in einer Warteschlange. Die Zustellung erfolgt mindestens einmal mit Wiederholungen; Weiterleitungen werden als Fehler behandelt. Die vollständige Beschreibung steht unter Webhooks.

Muster 5: Abstimmung mit dem Bericht über offene Posten

GET /reports/outstanding beantwortet die Frage „was ist heute in jeder Richtung offen“ aus derselben Übersicht, die das Dashboard des Inhabers anzeigt, sodass Ihre Zahl und dessen Zahl nicht auseinanderlaufen können.

{
  "asOf": "2026-09-03",
  "currency": "EUR",
  "booksOpen": true,
  "receivables": {
    "outstanding": { "minor": 4237650, "currency": "EUR" },
    "due": { "minor": 1105910, "currency": "EUR" },
    "overdue": { "minor": 318400, "currency": "EUR" },
    "count": 23
  },
  "payables": {
    "outstanding": { "minor": 812000, "currency": "EUR" },
    "due": { "minor": 0, "currency": "EUR" },
    "overdue": { "minor": 0, "currency": "EUR" },
    "count": 4
  }
}

Die beiden Seiten werden getrennt ausgewiesen und niemals saldiert: Geld, das einem Unternehmen geschuldet wird, und Geld, das es schuldet, werden an verschiedenen Tagen fällig, und eine einzige Zahl wäre genau dann beruhigend, wenn sie es nicht sein sollte. Für eine Sicht je Rechnung blättern Sie durch GET /invoices?status=OPEN und vergleichen outstanding und overdue mit Ihrem eigenen Abrechnungsstand. Eine Abweichung bedeutet meist eine Zahlung, die die Bank erreicht hat, aber im Produkt noch nicht zugeordnet wurde, oder eine Rechnung, die Ihr Webhook-Handler verloren hat – das Protokoll der Ereignis-IDs sagt Ihnen, welches von beiden.

Beispielablauf für ein über Stripe abgerechnetes Abonnement

  1. Stripe sendet customer.subscription.created. Ihr Handler prüft es, dedupliziert anhand der Stripe-Ereignis-ID und ruft POST /customers mit Idempotency-Key: account-<id> auf, falls für das Konto noch kein KRONENWERK-Kunde existiert. Speichern Sie die zurückgegebene id.
  2. Ihr Handler ruft POST /transactions mit Idempotency-Key: sub_<id>-<period> auf, schreibt die Kennungen des Abonnements und der Stripe-Rechnung in description und das Ende des Zeitraums in dueOn.
  3. Für B2B-Konten ruft Ihr Handler POST /invoices/drafts mit Idempotency-Key: in_<id> auf.
  4. Eine Person in der Finanzabteilung öffnet den Entwurf, fügt anhand der Beschreibung des Vorgangs die Position für den Zeitraum hinzu und stellt ihn aus. KRONENWERK berechnet das Steuerurteil, prüft die USt-IdNr., validiert die strukturierte Datei, verbraucht die Nummer und sendet invoice.issued an Ihren Endpunkt. Speichern Sie number und invoiceId zur Stripe-Rechnung.
  5. Stripe zieht die Kartenzahlung ein und zahlt auf das Bankkonto des Unternehmens aus. Die Bankanbindung (Enable Banking für europäische Banken, Plaid für kanadische und US-Banken) zeigt die Auszahlung; eine Person ordnet sie der Rechnung zu oder erfasst die Zahlung manuell. payment.recorded und invoice.paid erreichen Ihren Endpunkt.
  6. Erstattet Stripe die Belastung, stellt eine Person im Produkt eine Korrektur aus; invoice.cancelled kommt mit cancelledByNumber an, und Sie hängen die Gutschriftsnummer an die Erstattung.
  7. Zum Monatsende vergleichen Sie GET /reports/outstanding mit Ihren eigenen offenen Forderungen.

Fallstricke

Idempotenzschlüssel aus Zeit oder Zufall ableiten
Ein Schlüssel, der sich beim Wiederholungsversuch ändert, schützt nichts. Leiten Sie ihn aus dem Datensatz ab, den Sie spiegeln – Konto-ID, Abonnement-ID plus Zeitraum, Rechnungs-ID des Anbieters –, sodass ein Wiederholungsversuch dieselbe Operation bedeutet. Ein anderer Body unter demselben Schlüssel antwortet mit 409 IDEMPOTENZ_KONFLIKT, was ein Fehler in Ihrem Code ist, kein vorübergehender Fehler.
Entwürfe anlegen, bevor der Kunde existiert
Stripe garantiert keine Ereignisreihenfolge; invoice.paid kann vor customer.subscription.created eintreffen. Ermitteln Sie zuerst den KRONENWERK-Kunden, legen Sie ihn idempotent an, falls er fehlt, und erstellen Sie dann den Entwurf.
Ein Schlüssel, eine Firma
Ein KRONENWERK-API-Schlüssel ist für seine gesamte Lebensdauer an genau eine Firma gebunden. Ein SaaS mit mehreren Rechtsträgern (etwa einer deutschen GmbH und einer französischen SAS) braucht je Rechtsträger einen Schlüssel und muss jedes Konto an den richtigen leiten; siehe Mehrere Firmen, mehrere Währungen.
invoice.issued als „versendet“ behandeln
Es bedeutet, dass ein validiertes Dokument existiert und eine Nummer verbraucht wurde. Die Zustellung – E-Mail, Peppol über den verbundenen Access-Point-Anbieter oder ein nationales System – ist ein separater Schritt im Produkt und wird auf der API nicht gemeldet.
Das Ratenlimit ignorieren
Das Budget beträgt 240 Anfragen je Schlüssel, aufgefüllt mit etwa zwei pro Sekunde. Ein Monatsend-Job, der tausend Entwürfe in einem Schwung anlegt, trifft auf 429 mit Retry-After; beachten Sie den Header und verteilen Sie die Arbeit. Details unter Grenzen.
Gegen den Live-Schlüssel testen
Verwenden Sie während der Entwicklung einen greif_test_-Schlüssel; er funktioniert gegen denselben Host im Testmodus für die Firma, die ihn erstellt hat. GET /me meldet environment als SANDBOX oder PRODUCTION, sodass eine Startprüfung sich weigern kann, einen Test-Build mit einem Live-Schlüssel auszuführen.
Formatierte Beträge speichern
Beträge sind auf der API ganzzahlige Nebeneinheiten mit Währungscode und in Webhook-Bodys Zeichenketten aus Nebeneinheiten. Parsen Sie nirgendwo „1.059,10 €“; es gibt nichts zu parsen.

So geht KRONENWERK damit um

MIT EINSCHRÄNKUNGEN UNTERSTÜTZT Alles hier Gezeigte läuft auf der API, wie sie heute existiert, im Enterprise-Plan (Preise): idempotentes Anlegen von Kunden, Vorgängen und Rechnungsentwürfen; signierte Webhooks für Ausstellung, Zahlung, Stornierung, Einkäufe und Zahlungen; der Bericht über offene Posten und seitenweises Lesen von Rechnungen. Die Einschränkungen sind die durchgehend genannten: keine Ausstellung, keine Zahlungserfassung, keine Stornierung und kein Datei-Download über die API sowie kein automatischer Import von Stripe-Zahlungen. Wenn Ihre Integration eine Abrechnungsschleife ohne Menschen braucht, ist die API von KRONENWERK nicht das Richtige. Wenn die Bücher einer Firma widerspiegeln sollen, was Ihr Produkt verkauft hat, wobei die rechtlichen Schritte von einer Person nach den Regeln des Landes vorgenommen werden, ist dies der vorgesehene Weg. Die zugehörigen Produktseiten sind Buchhaltung, Rechnungen und Automatisierung; der Vergleich von Buchhaltungswerkzeugen mit API steht unter Buchhaltungssoftware mit API.

Häufig gestellte Fragen

Kann ich eine Stripe-Zahlung über die API erfassen?

Nein. Die API erfasst keine Zahlungen. Auszahlungen erreichen die Bücher über die Bankanbindung, oder eine Person erfasst die Zahlung; payment.recorded und invoice.paid erreichen dann Ihren Endpunkt.

Was ist ein „Vorgang“ (transaction) auf der API?

Eine Arbeitseinheit mit Titel, optionalem Kunden, einer Phase aus dem Workflow der Firma und einem Fälligkeitsdatum – eine Bestellung oder ein Abonnementzeitraum. Es ist keine Buchung im Hauptbuch.

Brauche ich für jede Verbraucherzahlung einen Entwurf?

Oft nicht. Entwürfe sind für Kunden gedacht, die eine einzelne, strukturierte Rechnung brauchen. Ob Verkäufe an Verbraucher in einem bestimmten Land eine solche erfordern, ist eine Frage, die fachliche Bestätigung erfordert.

Wie sollte ich Idempotenzschlüssel ableiten?

Aus Ihren eigenen stabilen Kennungen: Konto-ID für Kunden, Abonnement-ID plus Zeitraum für Vorgänge, Rechnungs-ID des Anbieters für Entwürfe. Schlüssel dürfen bis zu 200 Zeichen lang sein.

Wie teste ich, ohne die Live-Bücher zu berühren?

Erstellen Sie einen greif_test_-Schlüssel. Er funktioniert gegen dieselbe API im Testmodus für die Firma, die ihn erstellt hat, und GET /me meldet "environment", damit Ihr Build es prüfen kann.

Quellen

  1. KRONENWERK developer documentation gelesen am
  2. Stripe — Receive Stripe events in your webhook endpoint (duplicates, ordering, signatures) gelesen am
  3. Stripe — Idempotent requests gelesen am

Weiter mit der Dokumentation

Schnellstart lesen Referenz

Weiterlesen