Przejdź do treści

Dla programistów

Europejskie API księgowe dla programistów: VAT, e-faktury, RODO, księga

Ostatnia weryfikacja SUPPORTED WITH LIMITATIONS

Tłumaczenie wersji angielskiej, która jest aktualizowana jako pierwsza. Stwierdzenia regulacyjne odnoszą się do wymienionych źródeł i daty ich odczytu.

API księgowe dla Europy musi poprawnie rozwiązać osiem spraw, które API dla jednego kraju może pominąć: VAT zależny od krajów i statusu obu stron, odwrotne obciążenie i wymagane sformułowanie na fakturze, weryfikację numeru VAT w VIES, ustrukturyzowane e-faktury w formacie krajowym, obowiązki z RODO wobec danych klientów, idempotentne zapisy z podpisanymi webhookami, prawdziwą księgę o podwójnym zapisie oraz księgowość wielowalutową. Ten przewodnik objaśnia każde z wymagań i pokazuje, jak API KRONENWERK się do nich odnosi — włącznie z tym, gdzie API się kończy: tworzy klientów, wersje robocze i transakcje oraz odczytuje księgi; nie wystawia faktur, nie księguje zapisów i nie składa deklaracji.

VAT w wielu krajach jest funkcją faktów, nie polem ze stawką

W UE traktowanie sprzedaży pod kątem VAT wynika z kraju sprzedawcy, kraju nabywcy, tego, czy nabywca jest przedsiębiorcą czy konsumentem, oraz tego, czy przedmiotem jest dostawa towarów czy świadczenie usług. Ramy wyznacza dyrektywa 2006/112/WE: dla usług B2B miejscem świadczenia jest miejsce siedziby usługobiorcy (art. 44); gdy usługodawca nie ma tam siedziby, VAT rozlicza usługobiorca w ramach odwrotnego obciążenia (art. 196); wewnątrzwspólnotowe dostawy towarów do zarejestrowanego podatnika VAT w innym państwie członkowskim są zwolnione po spełnieniu warunków (art. 138); a art. 226 wymienia, co faktura musi zawierać, w tym adnotację „odwrotne obciążenie” tam, gdzie ma ona zastosowanie. Stawki, progi i zwolnienia są krajowe.

Konsekwencją dla projektu API jest to, że wywołującego nigdy nie należy pytać o stawkę VAT w oderwaniu od faktów. Dobrze zaprojektowane europejskie API przyjmuje fakty i zwraca werdykt — stawka podstawowa, stawka zerowa, zwolnienie, odwrotne obciążenie, poza zakresem — wraz z wynikającą z niego stawką i sformułowaniem na fakturze, a gdy brakuje faktu, odmawia zgadywania.

KRONENWERK: każda faktura niesie werdykt podatkowy wyprowadzony z faktów transakcji (kraj sprzedawcy, kraj nabywcy, przedsiębiorca czy konsument, rodzaj świadczenia). Werdykt to jedno z: stawka podstawowa, stawka zerowa, zwolnienie, odwrotne obciążenie, poza zakresem, albo „wymaga danych” / „wymaga potwierdzenia przez specjalistę”, gdy fakty nie rozstrzygają. Jest zapisywany z fakturą i nigdy nie jest później wnioskowany z danych podstawowych. Przez API werdykt nie jest polem, które Państwo ustawiają: wersja robocza utworzona przez POST /invoices/drafts dziedziczy jurysdykcję sprzedawcy, a werdykt zostaje utrwalony, gdy osoba wystawia fakturę w produkcie. To, czy dane świadczenie kwalifikuje się do zwolnienia, jest pytaniem do specjalisty, i produkt tak właśnie mówi, zamiast decydować.

Odwrotne obciążenie wymaga obu numerów VAT i właściwych słów

Faktura z odwrotnym obciążeniem różni się od krajowej w trzech miejscach: nie nalicza się VAT, obok numeru VAT sprzedawcy musi być obecny numer VAT nabywcy, a dokument musi stwierdzać, że podatek rozlicza nabywca. W terminologii EN 16931 kategoria VAT to AE, powód zwolnienia jest obowiązkowy, a reguły BR-AE-01 do BR-AE-10 wymuszają podział podatku i identyfikatory. Ustrukturyzowana e-faktura z niewłaściwą kategorią jest odrzucana przez walidator odbiorcy; PDF z niewłaściwym sformułowaniem to problem zgodności dla obu stron.

KRONENWERK: gdy werdykt brzmi „odwrotne obciążenie”, faktura zostaje wystawiona z VAT 0 %, kategorią AE w dokumencie ustrukturyzowanym, numerem VAT nabywcy i ustawową adnotacją w języku dokumentu. API odczytuje wynik przez GET /invoices/{number}, gdzie tax wynosi zero, a net równa się gross. Nie ma parametru API wymuszającego odwrotne obciążenie; wynika ono z kraju i numeru VAT klienta, które mogą Państwo przekazać przez POST /customers:

POST https://kronenwerk.org/api/extern/v1/customers
Authorization: Bearer greif_test_XXXXXXXXXXXXXXXX
Idempotency-Key: 6f1c2f4e-3c0a-4b8f-9d61-2a7c1c2e9b10
Content-Type: application/json

{
  "name": "Atelier Dupont SARL",
  "email": "compta@example.fr",
  "street": "12 rue de la Paix",
  "postalCode": "75002",
  "city": "Paris",
  "country": "FR",
  "vatId": "FR12345678901",
  "currency": "EUR"
}

Weryfikacja w VIES we właściwym momencie

VIES to prowadzony przez Komisję system wymiany informacji o VAT. Jego usługa sieciowa checkVat przyjmuje kod kraju i numer, a zwraca informację, czy numer jest ważny w dniu zapytania, oraz nazwę i adres tam, gdzie państwo członkowskie je ujawnia; checkVatApprox dodatkowo dopasowuje dane podmiotu i zwraca requestIdentifier — numer konsultacji, który dokumentuje sprawdzenie. Komisja oferuje też interfejs REST o tej samej semantyce. Systemy państw członkowskich bywają niedostępne; wówczas usługa zgłasza status taki jak MS_UNAVAILABLE zamiast informacji o ważności. Usługa istnieje na potrzeby transakcji wewnątrzwspólnotowych na mocy rozporządzenia Rady (WE) nr 904/2010.

Wynikają z tego dwie reguły projektowe. Sprawdzać w momencie, od którego zależy decyzja — przy wystawieniu — a nie tylko przy tworzeniu klienta, ponieważ rejestracje wygasają. I zapisywać wynik razem z dokumentem, ponieważ późniejsze pytanie brzmi „czy numer był ważny, gdy fakturowaliśmy”, a nie „czy jest ważny dzisiaj”.

KRONENWERK: numer VAT nabywcy jest sprawdzany w VIES przy wystawieniu, a wynik zapisywany z fakturą razem z werdyktem. Jeśli VIES lub system państwa członkowskiego nie odpowiada, sprawdzenie zostaje odnotowane na fakturze jako nieosiągalne i pokazane jako komunikat przy wystawieniu; awaria nigdy nie jest traktowana jako wynik pozytywny i nie jest buforowana, natomiast rzeczywisty wynik jest pamiętany przez jeden dzień, aby rejestr nie był odpytywany przy każdym naciśnięciu klawisza. Bezpłatna weryfikacja numeru VAT uruchamia to samo sprawdzenie dla pojedynczego numeru bez zapisywania go. API nie udostępnia własnego punktu końcowego VIES; udostępnia zapisany wynik na wystawionej fakturze.

Ustrukturyzowane e-faktury są krajowe, nie europejskie

Dyrektywa UE o fakturowaniu elektronicznym (2014/55/UE) zobowiązuje podmioty publiczne do przyjmowania faktur EN 16931; obowiązki B2B są krajowe i różnią się formatem, siecią i terminami. Niemcy wymagają od przedsiębiorstw odbioru faktur ustrukturyzowanych i stopniowo wprowadzają obowiązek wystawiania (XRechnung lub ZUGFeRD); Belgia nakazuje Peppol BIS Billing 3.0 przez sieć Peppol dla B2B od 1 stycznia 2026 r.; Polska rozlicza faktury przez KSeF w strukturze FA(3); Francja działa przez platformy akredytowane (plateformes agréées) z Factur-X jako jednym z akceptowanych formatów. Kanada i Stany Zjednoczone nie mają obowiązku faktur ustrukturyzowanych. Zob. harmonogram i formaty.

Dla API oznacza to, że format jest właściwością kraju sprzedawcy i kanału nabywcy, rozstrzyganą przy wystawieniu, a dokument musi zostać zwalidowany krajowymi artefaktami (Schematron CEN plus reguły profilu), zanim zaistnieje. API, które przyjmowałoby od wywołujących dowolny XML, i tak musiałoby go walidować, a najtrudniejszą część problemu przerzucałoby na każdego wywołującego.

KRONENWERK: plik ustrukturyzowany jest generowany i walidowany przy wystawieniu dla kraju sprzedawcy — XRechnung i ZUGFeRD (Schematron KoSIT, sprawdzany krzyżowo biblioteką Mustang), Factur-X, Peppol BIS UBL, FA(3). API tworzy wersję roboczą; format, walidacja i wysyłka należą do produktu. To największa uczciwie nazwana luka dla programistów, którzy spodziewali się wysłać fakturę przez POST i otrzymać XML: nie ma punktu końcowego „wystaw” i nie ma XML w API. Strona API e-fakturowania określa dokładnie, co jest dostępne, a przewodnik EN 16931 dla programistów omawia reguły, jeśli generują Państwo dokumenty samodzielnie.

RODO: dane klientów to dane osobowe

Imię i nazwisko, adres, e-mail i numer VAT osoby prowadzącej jednoosobową działalność gospodarczą są danymi osobowymi, więc integracja księgowa jest czynnością przetwarzania. RODO wymaga umowy między administratorem a podmiotem przetwarzającym określającej przedmiot, czas trwania, charakter, cel i kategorie danych (art. 28 ust. 3); rejestru czynności przetwarzania (art. 30); bezpieczeństwa odpowiedniego do ryzyka, w tym szyfrowania tam, gdzie jest ono właściwe (art. 32); a przy przekazywaniu poza UE/EOG — ważnego mechanizmu transferu (rozdział V, od art. 44). To, czego programista potrzebuje od dostawcy księgowości, jest zatem konkretne: umowa powierzenia przetwarzania danych, informacja o tym, gdzie dane są przechowywane i jacy podprocesorzy są wykorzystywani, oraz sposób usunięcia lub wyeksportowania rekordów osoby, której dane dotyczą.

KRONENWERK: warunki przetwarzania i ustalenia dotyczące hostingu są opisane na stronie prywatności i stronie bezpieczeństwa; to tam, a nie w tym przewodniku, znajduje się wiążące oświadczenie. KRONENWERK nie posiada żadnego certyfikatu bezpieczeństwa i nie twierdzi, że jest „certyfikowany zgodnie z RODO”, ponieważ taka certyfikacja nie istnieje. W API klucze mają zakresy, dzięki czemu integracja potrzebująca tylko reports:read nigdy nie otrzymuje rekordów klientów, a każdy klucz jest przypisany do jednej firmy.

Idempotencja i webhooki

Awarie sieci czynią każdy zapis niejednoznacznym: POST, który przekroczył limit czasu, mógł utworzyć rekord albo nie. Standardową odpowiedzią jest klucz idempotencji — unikalna wartość wybierana przez klienta dla każdej operacji logicznej, którą serwer zapisuje wraz z wynikiem, tak aby ponowna próba z tym samym kluczem zwróciła ten sam wynik zamiast duplikatu. Po stronie wychodzącej webhooki muszą być podpisane, aby odbiorca mógł zweryfikować pochodzenie, nieść identyfikator zdarzenia, aby można było odrzucić duplikaty, i być ponawiane po niepowodzeniu.

KRONENWERK: każdy POST wymaga nagłówka Idempotency-Key; powtórzenie z tym samym kluczem i treścią zwraca pierwotny wynik, a powtórzenie z inną treścią odpowiada 409 IDEMPOTENZ_KONFLIKT. Błędy są w JSON z kodem maszynowym i jednym zdaniem: UNAUTHENTICATED, ANFRAGE, PLAN_ERFORDERLICH, KEINE_BERECHTIGUNG, NICHT_GEFUNDEN, IDEMPOTENZ_KONFLIKT, FALSCHER_ZUSTAND, ABGELEHNT, ZU_VIELE_ANFRAGEN. Limit żądań to budżet 240 żądań na klucz, uzupełniany w sposób ciągły w tempie około dwóch na sekundę, z odpowiedzią 429 i Retry-After. Wychodzące webhooki są podpisane (KRONENWERK-Signature) i niosą KRONENWERK-Event-Id, KRONENWERK-Event, KRONENWERK-Delivery, KRONENWERK-Attempt oraz Idempotency-Key; zdarzenia to invoice.issued, invoice.paid, invoice.cancelled, purchase.recorded i payment.recorded; dostarczanie odbywa się wyłącznie przez HTTPS, jest ponawiane i nigdy nie podąża za przekierowaniami. Szczegóły: idempotencja, webhooki, błędy, limity.

Księga prowadzona jest podwójnym zapisem, a API ją odczytuje

System księgowy to nie lista faktur. Każda faktura, płatność i wydatek tworzy zbilansowane zapisy w dzienniku — Wn należności, Ma przychody i VAT należny; Wn bank, Ma należności — a raporty są sumami po kontach, nie po dokumentach. API zbudowane na takiej księdze może obiecać, że „należności otwarte” uzgadniają się z kontem rozrachunkowym należności, a wynik finansowy jest ostateczny dopiero wtedy, gdy stojące za nim okresy są zamknięte. API zbudowane na liście dokumentów tego nie może.

KRONENWERK: księga prowadzona jest podwójnym zapisem z zamykanymi okresami. REST API odczytuje pozycje otwarte przez GET /reports/outstanding; serwer MCP udostępnia dodatkowo get_profit_and_loss, get_balance_sheet, list_receivables i list_payables z tej samej księgi, z flagą is_final na rachunku zysków i strat. Nic w API nie księguje zapisu w dzienniku; zapisy powstają z czynności, które osoba wykonuje w produkcie — wystawienia, zarejestrowania płatności, zatwierdzenia faktury zakupowej. Odpowiedź z raportu pozycji otwartych, w skrócie:

{
  "asOf": "2026-09-03",
  "currency": "EUR",
  "booksOpen": true,
  "receivables": { "outstanding": { "minor": 1284050, "currency": "EUR" },
                   "due":         { "minor": 412000,  "currency": "EUR" },
                   "overdue":     { "minor": 105910,  "currency": "EUR" },
                   "count": 9 },
  "payables":    { "outstanding": { "minor": 336000,  "currency": "EUR" },
                   "due":         { "minor": 0,       "currency": "EUR" },
                   "overdue":     { "minor": 0,       "currency": "EUR" },
                   "count": 3 }
}

Waluta: jednostki podrzędne, jedna waluta ksiąg, zapisane kursy

Kwoty jako liczby zmiennoprzecinkowe gubią grosze; kwoty jako sformatowane ciągi znaków są niejednoznaczne między lokalizacjami („1.059,10” a „1,059.10”). Solidną reprezentacją jest całkowitoliczbowa liczba jednostek podrzędnych z kodem ISO 4217. Firma wielowalutowa fakturuje w walucie klienta, prowadzi księgi w jednej walucie ksiąg i musi zapisywać kurs użyty na każdym dokumencie, aby późniejsze raporty nie dryfowały wraz z dzisiejszym kursem.

KRONENWERK: każda kwota w API ma postać {"minor": 105910, "currency": "EUR"}, nigdy liczby dziesiętnej ani ciągu znaków. Firma ma jedną walutę ksiąg; klienci mogą mieć preferowaną walutę fakturowania; liczby utrwalone na wystawionej fakturze są tymi, które zwraca API, a nie dzisiejszymi danymi podstawowymi. Konfiguracje wielofirmowe używają jednego klucza na firmę. Zob. kilka firm, kilka walut oraz stronę produktu o wielu firmach.

Jak KRONENWERK to obsługuje

OBSŁUGIWANE Z OGRANICZENIAMI Publiczne API pod adresem https://kronenwerk.org/api/extern/v1 obejmuje GET /me, klientów (GET, GET /{id}, POST), faktury (GET, GET /{number}, POST /invoices/drafts), transakcje (GET, POST) oraz GET /reports/outstanding, z kluczami o określonych zakresach, obowiązkową idempotencją przy zapisach, budżetem żądań na klucz, błędami JSON z kodami maszynowymi, podpisanymi webhookami i serwerem MCP na tym samym kluczu. Ograniczenia są zamierzone i należy je uwzględnić w planach: API tworzy wyłącznie wersje robocze i transakcje — nie wystawia faktur, nie tworzy ani nie przyjmuje ustrukturyzowanego XML, nie księguje zapisów, nie rejestruje płatności, nie uruchamia sprawdzeń VIES na żądanie ani nie składa i nie odprowadza żadnego podatku. Te czynności odbywają się w produkcie, gdzie walidują je moduły krajowe, a API i webhooki raportują wyniki. Wszystko to jest częścią planu Enterprise; zob. cennik, przegląd API księgowego, szybki start i przewodnik podłączenia SaaS.

Najczęściej zadawane pytania

Czy mogę ustawić stawkę VAT na fakturze przez API?

Nie przez REST API: wersja robocza dziedziczy jurysdykcję sprzedawcy, a werdykt jest utrwalany przy wystawieniu na podstawie faktów. Przez serwer MCP create_invoice_draft przyjmuje tax_rate_percent dla każdej pozycji wersji roboczej; osoba nadal ją przegląda i wystawia. Pozycja obciążona kilkoma podatkami naraz — GST i QST w Quebecu, GST i PST w Kolumbii Brytyjskiej, stan, hrabstwo i miasto w Stanach Zjednoczonych — albo nazwany podatek, który niczego nie nalicza, jak eksport ze stawką zerową, jest zamiast tego podawana jako taxes na pozycji: jeden wpis na podatek z name, rate_percent oraz, gdy nic nie jest naliczane, własnym reason sprzedawcy. Każdy podatek jest stosowany do kwoty netto pozycji oraz drukowany i sumowany pod własną nazwą; KRONENWERK nie dostarcza stawki i nie rozstrzyga nexusu. create_quote_draft przyjmuje tę samą listę na pozycji oferty, a REST API niesie ją jako steuern na pozycji oferty tak samo jak faktury; faktura powstała z oferty niesie ją bez zmian. Schemat narzędzia zwracany przez serwer MCP jest punktem odniesienia dla tych pól.

Czy API wystawia prawnie ważne faktury?

Nie. Tworzy wersje robocze. Wystawienie — numeracja, walidacja jako ustrukturyzowana e-faktura, wysyłka — odbywa się w produkcie, a webhook invoice.issued o tym informuje.

Jak zweryfikować numer VAT klienta przed fakturowaniem?

KRONENWERK sprawdza go w VIES przy wystawieniu i zapisuje wynik. Do doraźnego sprawdzenia służy weryfikacja numeru VAT; API nie ma punktu końcowego VIES.

Czy istnieje sandbox?

Klucz greif_test_ działa wobec tego samego hosta w trybie testowym dla firmy, która go utworzyła. Nie ma osobnego hosta sandbox.

Gdzie przechowywane są moje dane i czy istnieje umowa powierzenia przetwarzania?

Wiążące odpowiedzi znajdują się na stronie prywatności i stronie bezpieczeństwa. KRONENWERK nie posiada certyfikatu bezpieczeństwa i nie twierdzi, że jest „certyfikowany zgodnie z RODO”.

Jakie kraje obejmuje API?

Te same co produkt: Niemcy, Francja, Belgia, Polska (z ograniczeniami — przesyłanie do KSeF nie zostało jeszcze sprawdzone w środowisku produkcyjnym), Kanada i Stany Zjednoczone.

Źródła

  1. Council Directive 2006/112/EC on the common system of VAT (consolidated) odczytano
  2. European Commission — VIES checkVat web service (WSDL) odczytano
  3. Regulation (EU) 2016/679 (GDPR) odczytano
  4. ConnectingEurope — eInvoicing-EN16931 validation artefacts odczytano
  5. KRONENWERK developer documentation odczytano

Czytaj dalej