De boekhoud-API van KRONENWERK is een kleine, gedocumenteerde HTTPS-interface op https://kronenwerk.org/api/extern/v1. Een Bearer-API-sleutel die aan precies één onderneming is gebonden, leest klanten, uitgereikte facturen, transacties en openstaande posten, en maakt klanten, transacties en factuurconcepten aan. Elke write vereist een Idempotency-Key. Onomkeerbare handelingen — een factuur uitreiken, een betaling registreren, annuleren — zijn niet beschikbaar via de API; ze gebeuren in het product en worden teruggemeld via ondertekende webhooks. De API, de webhooks en de MCP-server maken deel uit van het Enterprise-abonnement.
Waarvoor de boekhoud-API dient
Ze is bedoeld voor software die gegevens in de boeken van een onderneming moet plaatsen, of moet lezen wat er verschuldigd is, zonder dat iemand cijfers tussen twee systemen overtypt. Typische aanroepers zijn een SaaS-backend die een transactie en een factuurconcept opent wanneer een klant een contract tekent, een intern dashboard dat vorderingen leest, of een AI-agent die via de MCP-server de vraag "welke facturen zijn vervallen" beantwoordt.
Het ontwerpprincipe is dat de API dezelfde services bereikt als de schermen. Er is niets dat een externe aanroeper kan lezen wat de browser niet kan, en niets dat hij via een kortere weg kan doen. De tenantgrens, de abonnementscontrole, de nummerreeks en de regels van elke landenmodule worden één keer afgedwongen, in het product, en de API erft ze. Daarom aanvaardt de API bewust minder velden dan u misschien verwacht: het nummer, de vervaldatum en de betalingszin van een concept komen uit de jurisdictie van de verkoper en de met de klant overeengekomen voorwaarden, niet uit het verzoek.
Authenticatie: één sleutel, één onderneming
U authenticeert met een API-sleutel in de Authorization-header als Bearer-token. Live-sleutels beginnen met greif_live_, testsleutels met greif_test_. Een testsleutel werkt tegen dezelfde host in testmodus voor de onderneming die ze heeft aangemaakt; er is geen aparte sandbox-host.
Een sleutel behoort tot precies één onderneming, vastgelegd bij het uitgeven van de sleutel en nadien nooit gewijzigd. De organisatiekolom op de sleutel is niet bijwerkbaar, de handelende context wordt uit die kolom opgebouwd, en niets in een verzoek kan die beïnvloeden. Een persoon die lid is van twee ondernemingen en een sleutel uitgeeft terwijl hij onderneming A bekijkt, heeft een sleutel die nooit onderneming B kan lezen. GET /me rapporteert dit als een benoemd binding-object, zodat u dit ontdekt voordat u op de tegenovergestelde aanname bouwt.
Sleutels dragen scopes die bij het aanmaken van de sleutel worden gekozen:
| Scope | Wat ze toestaat |
|---|---|
customers:read | Klanten opsommen en lezen |
customers:write | Klanten aanmaken |
invoices:read | Uitgereikte facturen opsommen en lezen |
invoices:write | Factuurconcepten aanmaken |
transactions:read | Transacties opsommen (opdrachten met een fase en een vervaldatum) |
transactions:write | Transacties aanmaken |
reports:read | Het rapport openstaande posten lezen |
companies:read | De instellingen van de uitreikende onderneming lezen (nodig om een concept op te bouwen) |
Een scope is een gedocumenteerde naam voor een set mogelijkheden die het product al afdwingt; het is geen tweede rechtenmodel. Details staan op de authenticatiepagina.
Endpoints: de volledige lijst
Deze tien adressen vormen de hele interface. De referentietabel op het ontwikkelaarsportaal wordt gegenereerd uit dezelfde constante die de server afdwingt, zodat de scope die naast een adres staat de scope is die daar wordt gecontroleerd.
| Methode en pad | Vereiste scopes | Geeft terug |
|---|---|---|
GET /me | geen | De sleutel, haar ondernemingsbinding, omgeving en scopes |
GET /customers | customers:read | Een pagina klanten |
GET /customers/{id} | customers:read | Eén klant |
POST /customers | customers:write | 201 met de aangemaakte klant, inclusief nummer |
GET /invoices | invoices:read | Een pagina uitgereikte facturen, nieuwste eerst; filters status (OPEN of PAID), from, to |
GET /invoices/{number} | invoices:read | Eén uitgereikte factuur op nummer |
POST /invoices/drafts | invoices:write customers:read companies:read | 201 met een concept in status DRAFT |
GET /transactions | transactions:read | Een pagina transacties; filters stage, search, includeArchived |
POST /transactions | transactions:write transactions:read | 201 met de aangemaakte transactie en haar nummer |
GET /reports/outstanding | reports:read | Vandaag openstaande vorderingen en schulden |
Lijsten worden gepagineerd met page (vanaf 0) en size (standaard 25, maximaal 100). Een pagina heeft de vorm {"data": [...], "page": 0, "size": 25, "total": 137, "more": true}. Geld is altijd een aantal kleinste munteenheden met een valutacode — {"minor": 105910, "currency": "EUR"} — nooit een opgemaakte tekenreeks. Kalenderdata zoals issuedOn zijn ISO-data zonder tijd; tijdstempels zoals createdAt zijn instants.
Voorbeeld: GET /me
De eerste aanroep die u schrijft, omdat ze de vragen beantwoordt die een verkeerd geconfigureerde integratie werkelijk heeft: praat ik met de juiste onderneming, is dit de testsleutel, welke scopes heb ik gekregen.
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 is SANDBOX voor een greif_test_-sleutel en PRODUCTION voor een greif_live_-sleutel. scopes is het gepubliceerde vocabularium; permissions is de interne lijst van mogelijkheden die werkelijk beslist. Beide worden gerapporteerd, zodat een mogelijkheid zonder scope erboven zichtbaar is in plaats van verborgen.
Voorbeeld: POST /transactions met een Idempotency-Key
Een transactie in KRONENWERK is een werkeenheid met een titel, een optionele klant, een fase uit de eigen workflow van de onderneming en een vervaldatum — wat een onderneming een opdracht of een order noemt. Ze draagt geen geld en geen juridisch gevolg, en is daarom de write met de minste formaliteiten. Ze gaat toch door dezelfde service als het scherm: het nummer wordt uit de reeks van de onderneming voor het jaar getrokken, de fase wordt afgestemd op de fasen die deze onderneming gebruikt, en een klant die aan iemand anders toebehoort, wordt geweigerd.
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": "Annual licence 2026/27 — Beispiel GmbH",
"customerId": "3f2b…",
"description": "Stripe subscription sub_1Q…",
"dueOn": "2026-09-30"
}'
{
"id": "9c7d…",
"number": "V2026-0481",
"title": "Annual licence 2026/27 — Beispiel GmbH",
"stage": "NEU",
"customer": "Beispiel GmbH",
"dueOn": "2026-09-30",
"archived": false,
"createdAt": "2026-09-03T08:15:41Z"
}
De Idempotency-Key-header is vereist bij elke POST, niet optioneel. Het eerste verzoek onder een sleutel doet het werk en de sleutel onthoudt de identificatie van wat ze heeft aangemaakt; een herhaling onder dezelfde sleutel leest dat record opnieuw via dezelfde tenantcontrole en geeft het terug zonder het werk opnieuw te doen. Een herhaling met een andere body onder dezelfde sleutel wordt geweigerd met 409 IDEMPOTENZ_KONFLIKT, omdat een sleutel één bedoelde bewerking benoemt. Sleutels mogen tot 200 tekens lang zijn, dus een ordernummer met een voorvoegsel is prima. Twee kopieën van dezelfde retry die tegelijk aankomen, worden beslecht door een unieke index, niet door een look-then-write. Zie idempotentie.
Fouten en rate limits
Elke weigering is JSON met een zin voor een mens en een code voor een programma: {"fehler": "…", "code": "…"}. De zin kan in elke release worden geherformuleerd; de code maakt deel uit van het contract.
| Status | Code | Betekenis |
|---|---|---|
| 400 | ANFRAGE | Het verzoek kon niet worden gelezen: een ontbrekend veld (de zin noemt het), een niet-parseerbare body |
| 401 | UNAUTHENTICATED | Geen sleutel, een onleesbare, ingetrokken of verlopen sleutel — één antwoord voor alle vier |
| 403 | PLAN_ERFORDERLICH | Het abonnement van de onderneming omvat de API niet; alleen wie betaalt kan dit oplossen |
| 403 | KEINE_BERECHTIGUNG | De sleutel mist de scope die dit adres vereist |
| 404 | NICHT_GEFUNDEN | Geen dergelijk record — ook een echt record dat aan een andere onderneming toebehoort |
| 409 | IDEMPOTENZ_KONFLIKT | De idempotentiesleutel is al gebruikt voor een ander verzoek, of hetzelfde verzoek is nog in behandeling |
| 409 | FALSCHER_ZUSTAND | De status van het record laat dit niet toe |
| 409 | ABGELEHNT | Een domeinregel heeft de wijziging geweigerd; de zin zegt welke |
| 429 | ZU_VIELE_ANFRAGEN | Te veel verzoeken voor deze sleutel; bevat Retry-After |
De twee 403's zien er op de statusregel identiek uit en vereisen volledig verschillende actie; daarom bestaat de code. Een 404 wordt bewust teruggegeven voor "bestaat, maar is niet van u": een 403 zou een aanroeper laten bevestigen welke identificaties echt zijn in de onderneming van iemand anders.
De rate limit geldt per sleutel, niet per IP-adres: een budget van 240 verzoeken dat continu wordt aangevuld met één verzoek per 500 milliseconden, ongeveer twee per seconde aanhoudend met ruimte voor pieken. Wanneer het budget leeg is, is het antwoord 429 met een Retry-After-header in seconden en een body in de gebruikelijke vorm plus "wartesekunden". Een integratie die meer doorvoer nodig heeft, wordt over twee sleutels gesplitst, en de logs zeggen dan welke helft luidruchtig is. Zie limieten en fouten.
Webhooks: hoe onomkeerbare handelingen u bereiken
Een factuur uitreiken verbruikt een nummer en geeft een juridisch document vrij; een betaling registreren wijzigt de boeken; annuleren levert een correctie op. Geen van deze handelingen heeft een adres op de API en geen enkele heeft een scope die er een zou kunnen bereiken. Ze worden in plaats daarvan naar buiten gemeld, als ondertekende webhook-leveringen voor de gebeurtenissen invoice.issued, invoice.paid, invoice.cancelled, purchase.recorded en payment.recorded.
Elke levering is een HTTPS-POST naar het endpoint dat u registreert, met de headers KRONENWERK-Signature (t=<unix seconds>,v1=<hex>, een HMAC-SHA256 over de tijdstempel, een punt en de ruwe body, met een tolerantie van vijf minuten), KRONENWERK-Event-Id, KRONENWERK-Event, KRONENWERK-Delivery, KRONENWERK-Attempt en Idempotency-Key (gelijk aan de event-id). De body is een plat JSON-object waarvan de waarden tekenreeksen zijn, met sleutels in gesorteerde volgorde, en bevat altijd "event" en "id". Levering is at-least-once met retries; dedupliceer op de event-id. Alleen HTTPS op poort 443 wordt aanvaard, en redirects worden niet automatisch gevolgd — elk redirect-doel wordt getoetst aan dezelfde regels als het oorspronkelijke adres, en een keten van meer dan drie hops mislukt. Details en een verificatievoorbeeld staan op de webhooks-pagina.
MCP: dezelfde gegevens voor AI-agents
De MCP-server op https://kronenwerk.org/api/extern/mcp spreekt Streamable HTTP (alleen POST, protocolrevisie 2026-07-28, met de drie vorige revisies nog aanvaard) en authenticeert met dezelfde Bearer-API-sleutel. Er is nergens in het protocol een sessie of een organisatieparameter: de onderneming die een agent bereikt, is de onderneming van de sleutel, bepaald voordat het verzoek wordt gerouteerd.
Leestools: 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. Concepttools: create_invoice_draft, create_transaction, add_transaction_note. Geen enkele tool reikt een factuur uit, verstuurt e-mail, verplaatst geld of wijzigt instellingen. Zie MCP.
Hoe KRONENWERK hiermee omgaat
Ondersteund De hier beschreven API is de API die vandaag draait, op https://kronenwerk.org/api/extern/v1. Ze is beschikbaar in het Enterprise-abonnement, samen met webhooks, de MCP-server en de integratiedirectory; zie prijzen. Sleutels worden aangemaakt in de ontwikkelaarsinstellingen van het product, met de scopes en omgeving die u kiest, en GET /me vertelt u wat u hebt gekregen.
Wat ze niet doet, in duidelijke bewoordingen: ze reikt geen facturen uit, registreert geen betalingen, annuleert niet, verstuurt geen e-facturen en wijzigt geen instellingen. Dat zijn handelingen die een persoon in het product uitvoert, met de goedkeuringen die zijn land en zijn onderneming eromheen hebben gelegd — het fiscale oordeel, de VIES-controle, de validatie van het gestructureerde bestand en het aaneensluitende nummer gebeuren daar allemaal. De pagina over de factuur-API legt uit waarom de grens precies bij het concept ligt, en een SaaS-product koppelen toont de hele lus van begin tot einde. Begin met de snelstart en de referentie.
Veelgestelde vragen
Is er een sandbox?
Een greif_test_-sleutel werkt tegen dezelfde host in testmodus voor de onderneming die ze heeft aangemaakt. Er is geen aparte sandbox-host of basis-URL.
Kan één API-sleutel toegang krijgen tot meerdere ondernemingen?
Nee. Een sleutel wordt bij het uitgeven aan één onderneming gebonden en die binding kan niet veranderen. Maak één sleutel per onderneming aan; GET /me toont de binding.
Waarom kan ik geen factuur uitreiken via de API?
Uitreiken verbruikt een nummer uit een aaneensluitende reeks, bevriest de archiefrij, produceert het gestructureerde bestand en geeft het in sommige landen door aan een staatssysteem. Dat is geen stap die een lus die twee keer heeft gedraaid zou mogen zetten, dus blijft hij in het product; de API maakt concepten aan en de webhook invoice.issued vertelt u wanneer een persoon er een heeft uitgereikt.
Wat gebeurt er als ik de Idempotency-Key-header vergeet?
De POST wordt geweigerd met 400. De header is vereist in plaats van aangeboden, omdat een optionele garantie alleen de aanroepers beschermt die geen bescherming nodig hadden.
Hoe worden bedragen weergegeven?
Als een geheel aantal kleinste munteenheden plus een valutacode, bijvoorbeeld {"minor": 105910, "currency": "EUR"}. Nooit als opgemaakte tekenreeks.
Welk abonnement omvat de API?
De API, webhooks, MCP en de integratiedirectory maken deel uit van het Enterprise-abonnement. De actuele prijzen staan op de prijzenpagina.
Bronnen
- KRONENWERK developer documentation — geraadpleegd op
- RFC 6750 — The OAuth 2.0 Authorization Framework: Bearer Token Usage — geraadpleegd op
- Model Context Protocol specification — geraadpleegd op