Die KRONENWERK-Buchhaltungs-API ist eine kleine, dokumentierte HTTPS-Schnittstelle unter https://kronenwerk.org/api/extern/v1. Ein an genau ein Unternehmen gebundener Bearer-API-Schlüssel liest Kunden, ausgestellte Rechnungen, Vorgänge und offene Posten und legt Kunden, Vorgänge und Rechnungsentwürfe an. Jeder Schreibzugriff erfordert einen Idempotency-Key. Unumkehrbare Handlungen — eine Rechnung ausstellen, eine Zahlung erfassen, stornieren — sind nicht exponiert; sie geschehen im Produkt und werden über signierte Webhooks zurückgemeldet. API, Webhooks und MCP-Server sind Teil des Enterprise-Plans.
Wofür die Buchhaltungs-API gedacht ist
Sie ist für Software gedacht, die Datensätze in die Bücher eines Unternehmens einstellen oder lesen muss, was offen ist — ohne dass eine Person Zahlen zwischen zwei Systemen abtippt. Typische Aufrufer sind ein SaaS-Backend, das bei Vertragsabschluss einen Vorgang und einen Rechnungsentwurf anlegt, ein internes Dashboard, das Forderungen liest, oder ein KI-Agent, der über den MCP-Server die Frage „Welche Rechnungen sind überfällig?" beantwortet.
Das Gestaltungsprinzip lautet: Die API erreicht dieselben Dienste wie die Bildschirmmasken. Es gibt nichts, was ein externer Aufrufer lesen könnte, das der Browser nicht auch lesen kann, und nichts, was er auf einem kürzeren Weg tun könnte. Mandantengrenze, Planprüfung, Nummernkreis und die Regeln jedes Ländermoduls werden einmal im Produkt durchgesetzt, und die API erbt sie. Deshalb nimmt die API bewusst weniger Felder entgegen, als Sie vielleicht erwarten: Nummer, Fälligkeitsdatum und Zahlungssatz eines Entwurfs ergeben sich aus der Rechtsordnung des Verkäufers und den mit dem Kunden vereinbarten Bedingungen, nicht aus der Anfrage.
Authentifizierung: ein Schlüssel, ein Unternehmen
Sie authentifizieren sich mit einem API-Schlüssel im Authorization-Header als Bearer-Token. Live-Schlüssel beginnen mit greif_live_, Testschlüssel mit greif_test_. Ein Testschlüssel arbeitet gegen denselben Host im Testmodus für das Unternehmen, das ihn erstellt hat; es gibt keinen separaten Sandbox-Host.
Ein Schlüssel gehört zu genau einem Unternehmen, festgelegt bei der Ausgabe des Schlüssels und danach nie mehr geändert. Die Organisationsspalte am Schlüssel ist nicht änderbar, der handelnde Kontext wird aus dieser Spalte aufgebaut, und nichts an einer Anfrage kann ihn beeinflussen. Eine Person, die Mitglied zweier Unternehmen ist und einen Schlüssel erstellt, während sie Unternehmen A ansieht, hält einen Schlüssel, der Unternehmen B niemals lesen kann. GET /me meldet dies als benanntes binding-Objekt, damit Sie es erfahren, bevor Sie auf der gegenteiligen Annahme aufbauen.
Schlüssel tragen Scopes, die beim Erstellen des Schlüssels gewählt werden:
| Scope | Was er erlaubt |
|---|---|
customers:read | Kunden auflisten und lesen |
customers:write | Kunden anlegen |
invoices:read | Ausgestellte Rechnungen auflisten und lesen |
invoices:write | Rechnungsentwürfe anlegen |
transactions:read | Vorgänge auflisten (Aufträge mit Stufe und Fälligkeitsdatum) |
transactions:write | Vorgänge anlegen |
reports:read | Den Bericht über offene Posten lesen |
companies:read | Die Einstellungen des ausstellenden Unternehmens lesen (nötig, um einen Entwurf zu erstellen) |
Ein Scope ist ein dokumentierter Name für eine Menge von Fähigkeiten, die das Produkt ohnehin durchsetzt; er ist kein zweites Berechtigungsmodell. Einzelheiten stehen auf der Seite zur Authentifizierung.
Endpunkte: die vollständige Liste
Diese zehn Adressen sind die gesamte Schnittstelle. Die Referenztabelle im Entwicklerportal wird aus derselben Konstante gerendert, die der Server durchsetzt, sodass der neben einer Adresse angegebene Scope der Scope ist, der dort geprüft wird.
| Methode und Pfad | Erforderliche Scopes | Liefert |
|---|---|---|
GET /me | keine | Den Schlüssel, seine Unternehmensbindung, Umgebung und Scopes |
GET /customers | customers:read | Eine Seite Kunden |
GET /customers/{id} | customers:read | Einen Kunden |
POST /customers | customers:write | 201 mit dem angelegten Kunden einschließlich seiner Nummer |
GET /invoices | invoices:read | Eine Seite ausgestellter Rechnungen, neueste zuerst; Filter status (OPEN oder PAID), from, to |
GET /invoices/{number} | invoices:read | Eine ausgestellte Rechnung anhand ihrer Nummer |
POST /invoices/drafts | invoices:write customers:read companies:read | 201 mit einem Entwurf im Zustand DRAFT |
GET /transactions | transactions:read | Eine Seite Vorgänge; Filter stage, search, includeArchived |
POST /transactions | transactions:write transactions:read | 201 mit dem angelegten Vorgang und seiner Nummer |
GET /reports/outstanding | reports:read | Heute offene Forderungen und Verbindlichkeiten |
Listen werden mit page (ab 0) und size (Standard 25, maximal 100) seitenweise ausgegeben. Eine Seite hat die Form {"data": [...], "page": 0, "size": 25, "total": 137, "more": true}. Geldbeträge sind immer eine Anzahl kleinster Währungseinheiten mit Währungscode — {"minor": 105910, "currency": "EUR"} — nie eine formatierte Zeichenkette. Kalenderdaten wie issuedOn sind ISO-Daten ohne Uhrzeit; Zeitstempel wie createdAt sind Zeitpunkte (Instants).
Beispiel: GET /me
Der erste Aufruf, den Sie schreiben sollten, denn er beantwortet die Fragen, die eine fehlkonfigurierte Integration tatsächlich hat: Spreche ich mit dem richtigen Unternehmen, ist das der Testschlüssel, welche Scopes habe ich bekommen.
curl https://kronenwerk.org/api/extern/v1/me \
-H "Authorization: Bearer greif_test_…"
{
"organisationId": "5b1e…",
"organisation": "Beispiel GmbH",
"binding": { "organisationId": "5b1e…", "organisation": "Beispiel GmbH", "immutable": true },
"key": "greif_test_a1b2",
"name": "Billing service",
"environment": "SANDBOX",
"scopes": ["customers:read", "invoices:read", "transactions:write", "transactions:read"],
"permissions": ["EDIT_TRANSACTIONS", "VIEW_CUSTOMERS", "VIEW_INVOICES", "VIEW_TRANSACTIONS"],
"lastUsedAt": "2026-09-03T08:14:02Z",
"expiresAt": null
}
environment ist SANDBOX für einen greif_test_-Schlüssel und PRODUCTION für einen greif_live_-Schlüssel. scopes ist das veröffentlichte Vokabular; permissions ist die interne Fähigkeitenliste, die tatsächlich entscheidet. Beide werden gemeldet, damit eine Fähigkeit ohne darüberliegenden Scope sichtbar ist statt verborgen.
Beispiel: POST /transactions mit Idempotency-Key
Ein Vorgang in KRONENWERK ist eine Arbeitseinheit mit Titel, optionalem Kunden, einer Stufe aus dem eigenen Workflow des Unternehmens und einem Fälligkeitsdatum — das, was ein Betrieb Auftrag oder Bestellung nennt. Er trägt weder Geld noch rechtliche Folgen, weshalb er der Schreibzugriff mit dem geringsten Aufwand ist. Er läuft dennoch durch denselben Dienst wie die Bildschirmmaske: Die Nummer wird aus dem Nummernkreis des Unternehmens für das Jahr gezogen, die Stufe wird gegen die Stufen aufgelöst, die dieser Betrieb verwendet, und ein Kunde, der jemand anderem gehört, wird abgelehnt.
curl -X POST https://kronenwerk.org/api/extern/v1/transactions \
-H "Authorization: Bearer greif_live_…" \
-H "Idempotency-Key: order-2026-000481" \
-H "Content-Type: application/json" \
-d '{
"title": "Jahreslizenz 2026/27 — Beispiel GmbH",
"customerId": "3f2b…",
"description": "Stripe-Abonnement sub_1Q…",
"dueOn": "2026-09-30"
}'
{
"id": "9c7d…",
"number": "V2026-0481",
"title": "Jahreslizenz 2026/27 — Beispiel GmbH",
"stage": "NEU",
"customer": "Beispiel GmbH",
"dueOn": "2026-09-30",
"archived": false,
"createdAt": "2026-09-03T08:15:41Z"
}
Der Header Idempotency-Key ist bei jedem POST erforderlich, nicht optional. Die erste Anfrage unter einem Schlüssel erledigt die Arbeit, und der Schlüssel merkt sich die Kennung des Erzeugten; eine Wiederholung unter demselben Schlüssel liest diesen Datensatz über dieselbe Mandantenprüfung erneut und gibt ihn zurück, ohne die Arbeit erneut auszuführen. Eine Wiederholung mit anderem Body unter demselben Schlüssel wird mit 409 IDEMPOTENZ_KONFLIKT abgelehnt, denn ein Schlüssel benennt genau eine beabsichtigte Operation. Schlüssel dürfen bis zu 200 Zeichen lang sein, eine Bestellnummer mit Präfix ist also in Ordnung. Zwei gleichzeitig eintreffende Kopien derselben Wiederholung werden durch einen Unique-Index entschieden, nicht durch ein Lesen-dann-Schreiben. Siehe Idempotenz.
Fehler und Ratenbegrenzung
Jede Ablehnung ist JSON mit einem Satz für Menschen und einem Code für Programme: {"fehler": "…", "code": "…"}. Der Satz kann in jedem Release umformuliert werden; der Code ist Teil des Vertrags.
| Status | Code | Bedeutung |
|---|---|---|
| 400 | ANFRAGE | Die Anfrage konnte nicht gelesen werden: ein fehlendes Feld (der Satz benennt es), ein nicht parsbarer Body |
| 401 | UNAUTHENTICATED | Kein Schlüssel, ein unlesbarer, widerrufener oder abgelaufener — eine Antwort für alle vier Fälle |
| 403 | PLAN_ERFORDERLICH | Der Plan des Unternehmens enthält die API nicht; nur die zahlende Person kann das beheben |
| 403 | KEINE_BERECHTIGUNG | Dem Schlüssel fehlt der Scope, den diese Adresse verlangt |
| 404 | NICHT_GEFUNDEN | Kein solcher Datensatz — einschließlich eines echten Datensatzes, der einem anderen Unternehmen gehört |
| 409 | IDEMPOTENZ_KONFLIKT | Der Idempotenzschlüssel wurde bereits für eine andere Anfrage verwendet, oder dieselbe Anfrage ist noch in Bearbeitung |
| 409 | FALSCHER_ZUSTAND | Der Zustand des Datensatzes lässt dies nicht zu |
| 409 | ABGELEHNT | Eine Fachregel hat die Änderung abgelehnt; der Satz sagt, welche |
| 429 | ZU_VIELE_ANFRAGEN | Zu viele Anfragen für diesen Schlüssel; enthält Retry-After |
Die beiden 403-Antworten sehen in der Statuszeile identisch aus und erfordern völlig unterschiedliches Handeln — das ist der Grund, warum der Code existiert. Ein 404 wird für „existiert, gehört aber nicht Ihnen" absichtlich zurückgegeben: Ein 403 an dieser Stelle würde einem Aufrufer erlauben zu bestätigen, welche Kennungen im Unternehmen eines anderen echt sind.
Die Ratenbegrenzung gilt pro Schlüssel, nicht pro IP-Adresse: ein Budget von 240 Anfragen, das sich kontinuierlich mit einer Anfrage alle 500 Millisekunden auffüllt — etwa zwei pro Sekunde im Dauerbetrieb mit Spielraum für Spitzen. Ist das Budget leer, lautet die Antwort 429 mit einem Retry-After-Header in Sekunden und einem Body in der üblichen Form plus "wartesekunden". Eine Integration, die mehr Durchsatz braucht, wird auf zwei Schlüssel aufgeteilt, und die Protokolle sagen dann, welche Hälfte laut ist. Siehe Grenzen und Fehler.
Webhooks: Wie unumkehrbare Handlungen Sie erreichen
Das Ausstellen einer Rechnung verbraucht eine Nummer und gibt ein rechtlich verbindliches Dokument frei; das Erfassen einer Zahlung bewegt die Bücher; das Stornieren erzeugt eine Korrektur. Keine dieser Handlungen hat eine Adresse in der API, und keine hat einen Scope, der eine solche erreichen könnte. Sie werden stattdessen nach außen gemeldet, als signierte Webhook-Zustellungen für die Ereignisse invoice.issued, invoice.paid, invoice.cancelled, purchase.recorded und payment.recorded.
Jede Zustellung ist ein HTTPS-POST an den von Ihnen registrierten Endpunkt, mit den Headern KRONENWERK-Signature (t=<unix seconds>,v1=<hex>, ein HMAC-SHA256 über Zeitstempel, Punkt und rohen Body, mit fünf Minuten Toleranz), KRONENWERK-Event-Id, KRONENWERK-Event, KRONENWERK-Delivery, KRONENWERK-Attempt und Idempotency-Key (gleich der Ereignis-ID). Der Body ist ein flaches JSON-Objekt mit Zeichenkettenwerten und sortierten Schlüsseln und enthält immer "event" und "id". Die Zustellung erfolgt mindestens einmal (at-least-once) mit Wiederholungen; deduplizieren Sie anhand der Ereignis-ID. Akzeptiert wird nur HTTPS auf Port 443, und Weiterleitungen werden nicht automatisch gefolgt — jedes Weiterleitungsziel wird nach denselben Regeln geprüft wie die ursprüngliche Adresse, und eine Kette von mehr als drei Sprüngen schlägt fehl. Einzelheiten und ein Verifikationsbeispiel stehen auf der Webhooks-Seite.
MCP: dieselben Daten für KI-Agenten
Der MCP-Server unter https://kronenwerk.org/api/extern/mcp spricht Streamable HTTP (nur POST, Protokollrevision 2026-07-28, die drei vorherigen Revisionen werden weiterhin akzeptiert) und authentifiziert mit demselben Bearer-API-Schlüssel. Es gibt nirgends im Protokoll eine Sitzung oder einen Organisationsparameter: Das Unternehmen, das ein Agent erreicht, ist das Unternehmen des Schlüssels, festgelegt bevor die Anfrage geroutet wird.
Lese-Tools: get_customer, search_customers, get_invoice, list_invoices, get_transaction, list_transactions, list_receivables, list_payables, get_profit_and_loss, get_balance_sheet, get_business_attention. Entwurfs-Tools: create_invoice_draft, create_transaction, add_transaction_note. Kein Tool stellt eine Rechnung aus, versendet E-Mails, bewegt Geld oder ändert Einstellungen. Siehe MCP.
Wie KRONENWERK damit umgeht
Unterstützt Die hier beschriebene API ist die API, die heute läuft, unter https://kronenwerk.org/api/extern/v1. Sie ist im Enterprise-Plan zusammen mit Webhooks, dem MCP-Server und dem Integrationsverzeichnis verfügbar; siehe Preise. Schlüssel werden in den Entwicklereinstellungen des Produkts mit den von Ihnen gewählten Scopes und der Umgebung erstellt, und GET /me sagt Ihnen, was Sie erhalten haben.
Was sie nicht tut, klar gesagt: Sie stellt keine Rechnungen aus, erfasst keine Zahlungen, storniert nicht, sendet keine E-Rechnungen und ändert keine Einstellungen. Das sind Handlungen, die eine Person im Produkt vornimmt, mit den Freigaben, die ihr Land und ihr Betrieb darum gelegt haben — Steuerbefund, VIES-Prüfung, Validierung der strukturierten Datei und lückenlose Nummer geschehen alle dort. Die Seite zur Rechnungs-API erklärt, warum die Grenze genau beim Entwurf gezogen ist, und Ein SaaS-Produkt anbinden zeigt den gesamten Kreislauf von Anfang bis Ende. Beginnen Sie mit dem Schnellstart und der Referenz.
Häufige Fragen
Gibt es eine Sandbox?
Ein greif_test_-Schlüssel arbeitet gegen denselben Host im Testmodus für das Unternehmen, das ihn erstellt hat. Es gibt keinen separaten Sandbox-Host und keine separate Basis-URL.
Kann ein API-Schlüssel auf mehrere Unternehmen zugreifen?
Nein. Ein Schlüssel wird bei der Ausgabe an ein Unternehmen gebunden, und diese Bindung kann sich nicht ändern. Erstellen Sie einen Schlüssel pro Unternehmen; GET /me zeigt die Bindung.
Warum kann ich über die API keine Rechnung ausstellen?
Das Ausstellen verbraucht eine Nummer aus einem lückenlosen Nummernkreis, friert die Archivzeile ein, erzeugt die strukturierte Datei und übergibt sie in manchen Ländern an ein staatliches System. Das ist kein Schritt, den eine zweimal gelaufene Schleife ausführen können sollte, daher bleibt er im Produkt; die API legt Entwürfe an, und der Webhook invoice.issued sagt Ihnen, wann eine Person eine Rechnung ausgestellt hat.
Was passiert, wenn ich den Header Idempotency-Key vergesse?
Der POST wird mit 400 abgelehnt. Der Header ist erforderlich statt optional, weil eine optionale Garantie nur die Aufrufer schützt, die keinen Schutz brauchten.
Wie werden Beträge dargestellt?
Als ganzzahlige Anzahl kleinster Währungseinheiten plus Währungscode, zum Beispiel {"minor": 105910, "currency": "EUR"}. Nie als formatierte Zeichenkette.
Welcher Plan enthält die API?
API, Webhooks, MCP und das Integrationsverzeichnis sind Teil des Enterprise-Plans. Aktuelle Preise stehen auf der Preisseite.
Quellen
- KRONENWERK developer documentation — gelesen am
- RFC 6750 — The OAuth 2.0 Authorization Framework: Bearer Token Usage — gelesen am
- Model Context Protocol specification — gelesen am