Przegląd
Webhooki
Webhooki automatycznie informują Twój serwer o zmianach stanu faktury, dzięki czemu nie musisz cyklicznie sprawdzać jej statusu. Gdy wystąpi obsługiwane zdarzenie, system tworzy powiadomienie i wysyła je do wszystkich aktywnych endpointów webhooków w organizacji, które subskrybują dany typ zdarzenia.
Historię prób i wyniki wysyłki sprawdzisz w Rejestrach doręczeń.
Jak działa doręczanie
Dla każdego zdarzenia system tworzy osobne doręczenie do każdego aktywnego endpointu webhooka, który subskrybuje dany typ zdarzenia. Doręczanie odbywa się asynchronicznie, a problemy z jednym endpointem nie blokują wysyłki do pozostałych organizacji.
Przed każdą próbą system ponownie sprawdza adres endpointu. Jeśli endpoint został wyłączony lub usunięty, doręczenie otrzymuje status endpoint_disabled i żądanie nie jest wysyłane. Jeśli adres zostanie uznany za niebezpieczny, próba kończy się statusem failed, również bez wykonania żądania HTTP.
Nieudane doręczenia mogą być ponawiane, dlatego to samo zdarzenie może zostać wysłane więcej niż raz. Odbiorca powinien deduplikować zdarzenia na podstawie event.id.
Format żądania
Każde doręczenie to żądanie HTTP POST z Content-Type: application/json. Treścią jest surowy JSON zdarzenia Event. Każdemu żądaniu towarzyszą trzy nagłówki:
Ksef-Event-Id: evt_V3sGDb5VXxLxzGzvYVw0PwKsef-Timestamp: 2026-06-01T10:18:30ZKsef-Signature: v1=<lowercase-hex-hmac>Ksef-Event-Id odzwierciedla id zdarzenia, Ksef-Timestamp to znacznik czasu podpisu, a Ksef-Signature niesie podpis HMAC opisany poniżej.
Nagłówek Ksef-Signature
Pozwala zweryfikować, że webhook pochodzi z emfakt i jego treść nie została zmieniona. Podpis jest obliczany algorytmem HMAC-SHA256 na podstawie ciągu:
Ksef-Timestamp + "." + surowa treść żądaniaDo obliczenia podpisu używany jest sekret endpointu whsec_.... Wartość nagłówka ma format:
v1=<podpis HMAC zapisany małymi znakami szesnastkowymi>Podczas weryfikacji treść żądania powinna zostać użyta dokładnie w takiej postaci, w jakiej została odebrana. Nie powinna być parsowana ani nie serializowana ponownie, ponieważ nawet niewielka zmiana treści spowoduje niezgodność podpisu.
Do porównania podpisu z nagłówkiem użyj funkcji o stałym czasie działania (na przykład crypto.timingSafeEqual) zamiast zwykłego porównania ciągów.
import crypto from 'node:crypto'// rawBody musi być dokładnymi otrzymanymi bajtami, przed parsowaniem JSON.function isValidSignature(rawBody, headers, signingSecret) { const timestamp = headers['ksef-timestamp'] const received = headers['ksef-signature'] // "v1=<lowercase-hex-hmac>" const expected = 'v1=' + crypto .createHmac('sha256', signingSecret) .update(`${timestamp}.${rawBody}`) .digest('hex') const a = Buffer.from(received) const b = Buffer.from(expected) return a.length === b.length && crypto.timingSafeEqual(a, b)}Ponowienia doręczeń
Doręczanie nie podąża za przekierowaniami, każdą odpowiedź 3xx traktujemy jako nieudane doręczenie, bo podpisanego payloadu nie wolno przekazywać do nieoczekiwanego hosta. Błędy przejściowe typu 429, 5xx, timeout, awaria połączenia lub nieoczekiwany błąd po stronie wysyłającego powodują zaplanowanie kolejnej próby z prostym backoffem. Błędy nieponawialne typu 3xx albo 4xx inne niż 429 kończą doręczenie niepowodzeniem. Czas kolejnych prób nie jest gwarantowany żadnym harmonogram.
Ponowienia mogą tworzyć duplikaty doręczeń, dlatego zawsze deduplikuj po event.id natomiast nigdy po identyfikatorze doręczenia.
Nie ma publicznego endpointu do listowania zdarzeń ani API do odtwarzania zdarzeń czy testowej wysyłki webhooka. Jedyne sposoby obserwowania doręczeń to Twój własny endpoint oraz oczyszczone Rejestry doręczeń.