API księgowe KRONENWERK to niewielki, udokumentowany interfejs HTTPS pod adresem https://kronenwerk.org/api/extern/v1. Klucz API typu Bearer powiązany z dokładnie jedną firmą odczytuje klientów, wystawione faktury, transakcje i pozycje otwarte oraz tworzy klientów, transakcje i wersje robocze faktur. Każdy zapis wymaga nagłówka Idempotency-Key. Czynności nieodwracalne — wystawienie faktury, zaksięgowanie płatności, anulowanie — nie są udostępniane; odbywają się w produkcie i są zgłaszane zwrotnie przez podpisane webhooki. API, webhooki i serwer MCP są częścią planu Enterprise.
Do czego służy API księgowe
Jest przeznaczone dla oprogramowania, które musi wprowadzać zapisy do ksiąg firmy lub odczytywać należności bez konieczności ręcznego przepisywania liczb między dwoma systemami. Typowi użytkownicy to backend SaaS, który otwiera transakcję i wersję roboczą faktury, gdy klient podpisuje umowę, wewnętrzny pulpit odczytujący należności albo agent AI odpowiadający na pytanie „które faktury są przeterminowane” przez serwer MCP.
Zasadą projektową jest to, że API sięga do tych samych usług, z których korzystają ekrany aplikacji. Nie ma nic, co zewnętrzny wywołujący mógłby odczytać, a czego nie mogłaby przeglądarka, i nic, co mógłby zrobić krótszą drogą. Granica tenanta, sprawdzenie planu, sekwencja numeracji i reguły każdego modułu krajowego są egzekwowane raz, w produkcie, a API je dziedziczy. Dlatego API celowo przyjmuje mniej pól, niż można by oczekiwać: numer wersji roboczej, termin płatności i formuła płatności wynikają z jurysdykcji sprzedawcy i uzgodnionych z klientem warunków, a nie z żądania.
Uwierzytelnianie: jeden klucz, jedna firma
Uwierzytelniają się Państwo kluczem API w nagłówku Authorization jako tokenem Bearer. Klucze produkcyjne zaczynają się od greif_live_, klucze testowe od greif_test_. Klucz testowy działa na tym samym hoście w trybie testowym dla firmy, która go utworzyła; nie ma osobnego hosta sandbox.
Klucz należy do dokładnie jednej firmy, ustalonej w chwili wydania klucza i nigdy później niezmienianej. Kolumna organizacji na kluczu nie podlega aktualizacji, kontekst działania jest budowany z tej kolumny i nic w żądaniu nie może na niego wpłynąć. Osoba będąca członkiem dwóch firm, która wydaje klucz, przeglądając firmę A, posiada klucz, który nigdy nie odczyta firmy B. GET /me zgłasza to jako nazwany obiekt binding, aby dowiedzieli się Państwo o tym, zanim zbudują integrację na przeciwnym założeniu.
Klucze mają zakresy (scopes) wybierane przy tworzeniu klucza:
| Zakres | Na co pozwala |
|---|---|
customers:read | Listowanie i odczyt klientów |
customers:write | Tworzenie klientów |
invoices:read | Listowanie i odczyt wystawionych faktur |
invoices:write | Tworzenie wersji roboczych faktur |
transactions:read | Listowanie transakcji (zleceń z etapem i terminem) |
transactions:write | Tworzenie transakcji |
reports:read | Odczyt raportu pozycji otwartych |
companies:read | Odczyt ustawień firmy wystawiającej (potrzebny do zbudowania wersji roboczej) |
Zakres to udokumentowana nazwa zestawu uprawnień, które produkt już egzekwuje; nie jest drugim modelem uprawnień. Szczegóły znajdują się na stronie o uwierzytelnianiu.
Endpointy: pełna lista
Te dziesięć adresów to cały interfejs. Tabela referencyjna na portalu deweloperskim jest renderowana z tej samej stałej, którą egzekwuje serwer, więc zakres wydrukowany obok adresu jest zakresem sprawdzanym pod tym adresem.
| Metoda i ścieżka | Wymagane zakresy | Zwraca |
|---|---|---|
GET /me | brak | Klucz, jego powiązanie z firmą, środowisko i zakresy |
GET /customers | customers:read | Stronę klientów |
GET /customers/{id} | customers:read | Jednego klienta |
POST /customers | customers:write | 201 z utworzonym klientem, łącznie z jego numerem |
GET /invoices | invoices:read | Stronę wystawionych faktur, od najnowszych; filtry status (OPEN lub PAID), from, to |
GET /invoices/{number} | invoices:read | Jedną wystawioną fakturę po jej numerze |
POST /invoices/drafts | invoices:write customers:read companies:read | 201 z wersją roboczą w stanie DRAFT |
GET /transactions | transactions:read | Stronę transakcji; filtry stage, search, includeArchived |
POST /transactions | transactions:write transactions:read | 201 z utworzoną transakcją i jej numerem |
GET /reports/outstanding | reports:read | Należności i zobowiązania otwarte na dziś |
Listy są stronicowane parametrami page (od 0) i size (domyślnie 25, maksymalnie 100). Strona ma postać {"data": [...], "page": 0, "size": 25, "total": 137, "more": true}. Kwoty są zawsze liczbą jednostek podrzędnych z kodem waluty — {"minor": 105910, "currency": "EUR"} — nigdy sformatowanym ciągiem znaków. Daty kalendarzowe, takie jak issuedOn, są datami ISO bez czasu; znaczniki czasu, takie jak createdAt, są chwilami (instant).
Przykład: GET /me
Pierwsze wywołanie, które warto napisać, bo odpowiada na pytania, jakie faktycznie ma błędnie skonfigurowana integracja: czy rozmawiam z właściwą firmą, czy to klucz testowy, jakie zakresy otrzymałem.
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 ma wartość SANDBOX dla klucza greif_test_ i PRODUCTION dla klucza greif_live_. scopes to opublikowane słownictwo; permissions to wewnętrzna lista uprawnień, która faktycznie decyduje. Oba są zgłaszane, aby uprawnienie bez odpowiadającego mu zakresu było widoczne, a nie ukryte.
Przykład: POST /transactions z nagłówkiem Idempotency-Key
Transakcja w KRONENWERK to jednostka pracy z tytułem, opcjonalnym klientem, etapem z własnego procesu firmy i terminem — to, co firma nazywa zleceniem lub zamówieniem. Nie niesie ze sobą pieniędzy ani skutków prawnych, dlatego jest zapisem o najmniejszym ceremoniale. Nadal przechodzi przez tę samą usługę co ekran aplikacji: numer jest pobierany z sekwencji firmy na dany rok, etap jest rozstrzygany względem etapów używanych przez tę firmę, a klient należący do kogoś innego jest odrzucany.
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"
}
Nagłówek Idempotency-Key jest wymagany przy każdym POST, nie opcjonalny. Pierwsze żądanie pod danym kluczem wykonuje pracę, a klucz zapamiętuje identyfikator tego, co utworzył; powtórzenie pod tym samym kluczem ponownie odczytuje ten rekord przez to samo sprawdzenie tenanta i zwraca go bez ponownego wykonywania pracy. Powtórzenie z innym ciałem pod tym samym kluczem jest odrzucane z kodem 409 IDEMPOTENZ_KONFLIKT, ponieważ klucz nazywa jedną zamierzoną operację. Klucze mogą mieć do 200 znaków, więc numer zamówienia z prefiksem jest w porządku. Dwie kopie tego samego ponowienia przychodzące jednocześnie są rozstrzygane przez unikalny indeks, a nie przez sekwencję „sprawdź, potem zapisz”. Zob. idempotencja.
Błędy i limity żądań
Każda odmowa to JSON ze zdaniem dla człowieka i kodem dla programu: {"fehler": "…", "code": "…"}. Zdanie może zostać przeredagowane w dowolnym wydaniu; kod jest częścią kontraktu.
| Status | Kod | Znaczenie |
|---|---|---|
| 400 | ANFRAGE | Nie udało się odczytać żądania: brakujące pole (zdanie je wskazuje), nieparsowalne ciało |
| 401 | UNAUTHENTICATED | Brak klucza, klucz nieczytelny, unieważniony lub wygasły — jedna odpowiedź dla wszystkich czterech przypadków |
| 403 | PLAN_ERFORDERLICH | Plan firmy nie obejmuje API; tylko osoba płacąca może to naprawić |
| 403 | KEINE_BERECHTIGUNG | Kluczowi brakuje zakresu wymaganego pod tym adresem |
| 404 | NICHT_GEFUNDEN | Brak takiego rekordu — w tym istniejący rekord należący do innej firmy |
| 409 | IDEMPOTENZ_KONFLIKT | Klucz idempotencji został już użyty dla innego żądania albo to samo żądanie jest wciąż w toku |
| 409 | FALSCHER_ZUSTAND | Stan rekordu na to nie pozwala |
| 409 | ABGELEHNT | Reguła domenowa odrzuciła zmianę; zdanie wskazuje, która |
| 429 | ZU_VIELE_ANFRAGEN | Zbyt wiele żądań dla tego klucza; zawiera Retry-After |
Dwa błędy 403 wyglądają identycznie w linii statusu i wymagają zupełnie innych działań — to jest powód istnienia kodu. 404 jest celowo zwracany w przypadku „istnieje, ale nie jest Państwa”: 403 pozwoliłby wywołującemu potwierdzić, które identyfikatory są prawdziwe w cudzej firmie.
Limit żądań obowiązuje na klucz, nie na adres IP: budżet 240 żądań, który uzupełnia się ciągle w tempie jednego żądania co 500 milisekund, czyli około dwóch na sekundę w trybie ciągłym z zapasem na szczytowe obciążenia. Gdy budżet jest pusty, odpowiedzią jest 429 z nagłówkiem Retry-After w sekundach i ciałem w zwykłej postaci plus "wartesekunden". Integrację potrzebującą większej przepustowości dzieli się na dwa klucze, a logi mówią wtedy, która połowa jest głośna. Zob. limity i błędy.
Webhooki: jak docierają do Państwa czynności nieodwracalne
Wystawienie faktury zużywa numer i wypuszcza dokument prawny; zaksięgowanie płatności zmienia księgi; anulowanie tworzy korektę. Żadna z tych czynności nie ma adresu w API i żadna nie ma zakresu, który mógłby do niej sięgnąć. Zamiast tego są zgłaszane na zewnątrz jako podpisane dostawy webhooków dla zdarzeń invoice.issued, invoice.paid, invoice.cancelled, purchase.recorded i payment.recorded.
Każda dostawa to HTTPS POST na zarejestrowany przez Państwa endpoint, z nagłówkami KRONENWERK-Signature (t=<unix seconds>,v1=<hex>, HMAC-SHA256 nad znacznikiem czasu, kropką i surowym ciałem, z pięciominutową tolerancją), KRONENWERK-Event-Id, KRONENWERK-Event, KRONENWERK-Delivery, KRONENWERK-Attempt oraz Idempotency-Key (równym identyfikatorowi zdarzenia). Ciało to płaski obiekt JSON, którego wartości są ciągami znaków, z kluczami w porządku posortowanym, zawsze zawierający "event" i "id". Dostawa jest typu at-least-once z ponowieniami; deduplikację należy prowadzić po identyfikatorze zdarzenia. Akceptowany jest wyłącznie HTTPS na porcie 443, a przekierowania nie są automatycznie śledzone — każdy cel przekierowania jest sprawdzany według tych samych reguł co adres pierwotny, a łańcuch dłuższy niż trzy przeskoki kończy się niepowodzeniem. Szczegóły i przykład weryfikacji znajdują się na stronie o webhookach.
MCP: te same dane dla agentów AI
Serwer MCP pod adresem https://kronenwerk.org/api/extern/mcp używa Streamable HTTP (tylko POST, rewizja protokołu 2026-07-28, przy czym trzy poprzednie rewizje są nadal akceptowane) i uwierzytelnia tym samym kluczem API Bearer. Nigdzie w protokole nie ma sesji ani parametru organizacji: firma, do której sięga agent, jest firmą klucza, ustaloną przed skierowaniem żądania.
Narzędzia odczytu: 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. Narzędzia wersji roboczych: create_invoice_draft, create_transaction, add_transaction_note. Żadne narzędzie nie wystawia faktury, nie wysyła poczty, nie przenosi pieniędzy ani nie zmienia ustawień. Zob. MCP.
Jak KRONENWERK to obsługuje
OBSŁUGIWANE Opisane tu API jest API działającym dzisiaj pod adresem https://kronenwerk.org/api/extern/v1. Jest dostępne w planie Enterprise wraz z webhookami, serwerem MCP i katalogiem integracji; zob. cennik. Klucze tworzy się w ustawieniach deweloperskich produktu z wybranymi zakresami i środowiskiem, a GET /me informuje, co Państwo otrzymali.
Czego nie robi, mówiąc wprost: nie wystawia faktur, nie księguje płatności, nie anuluje, nie wysyła e-faktur i nie zmienia ustawień. Są to czynności, które osoba wykonuje w produkcie z zatwierdzeniami, jakich wymaga jej kraj i jej firma — rozstrzygnięcie podatkowe, sprawdzenie w VIES, walidacja pliku ustrukturyzowanego i ciągła numeracja odbywają się właśnie tam. Strona o API faktur wyjaśnia, dlaczego granica przebiega dokładnie na wersji roboczej, a podłączanie produktu SaaS pokazuje całą pętlę od początku do końca. Warto zacząć od szybkiego startu i dokumentacji referencyjnej.
Najczęściej zadawane pytania
Czy jest sandbox?
Klucz greif_test_ działa na tym samym hoście w trybie testowym dla firmy, która go utworzyła. Nie ma osobnego hosta sandbox ani osobnego adresu bazowego.
Czy jeden klucz API może mieć dostęp do kilku firm?
Nie. Klucz jest powiązany z jedną firmą w chwili wydania i tego powiązania nie można zmienić. Należy utworzyć po jednym kluczu na firmę; GET /me pokazuje powiązanie.
Dlaczego nie mogę wystawić faktury przez API?
Wystawienie zużywa numer z ciągłej sekwencji, zamraża wiersz archiwum, tworzy plik ustrukturyzowany, a w niektórych krajach przekazuje go do systemu państwowego. Nie jest to krok, który powinna móc wykonać pętla uruchomiona dwa razy, więc pozostaje w produkcie; API tworzy wersje robocze, a webhook invoice.issued informuje, kiedy osoba wystawiła fakturę.
Co się stanie, jeśli zapomnę nagłówka Idempotency-Key?
POST zostanie odrzucony z kodem 400. Nagłówek jest wymagany, a nie oferowany, ponieważ opcjonalna gwarancja chroni tylko tych wywołujących, którzy ochrony nie potrzebowali.
Jak są reprezentowane kwoty?
Jako całkowita liczba jednostek podrzędnych plus kod waluty, na przykład {"minor": 105910, "currency": "EUR"}. Nigdy jako sformatowany ciąg znaków.
Który plan obejmuje API?
API, webhooki, MCP i katalog integracji są częścią planu Enterprise. Aktualne ceny znajdują się na stronie z cennikiem.
Źródła
- KRONENWERK developer documentation — odczytano
- RFC 6750 — The OAuth 2.0 Authorization Framework: Bearer Token Usage — odczytano
- Model Context Protocol specification — odczytano