Webhooki
Gdy coś dzieje się w Foudrze, może ona powiadomić inny system, wysyłając mu wiadomość: centrum kontroli misji dowiaduje się, że serwis łodzi jest zakończony, sklep — że zmienił się zapas. Tylko administratorzy. Żeby o coś zapytać Foudrę albo coś w niej zmienić, użyj API; webhooki służą do otrzymywania powiadomień.
Tworzenie
| Pole | Znaczenie |
|---|---|
| Name (nazwa) | Co jest po drugiej stronie |
| URL (adres) | Dokąd wysyłać. Musi to być https osiągalny z internetu. Adres w sieci prywatnej jest odrzucany, chyba że operator Foudry zezwolił na ten host |
| Events (zdarzenia) | Które zdarzenia wysyłać |
Sekret podpisu jest pokazywany raz, na następnej stronie. Skopiuj go wtedy: odbiorca potrzebuje go, żeby sprawdzić, że wiadomość pochodzi od Foudry.
Send test (wyślij test) wysyła zdarzenie ping. Switch off (wyłącz) wstrzymuje wysyłanie; zdarzenia, które zajdą, gdy webhook jest wyłączony, nie są dla niego odkładane. Remove (usuń) usuwa go, zachowując historię dostarczeń.
Zdarzenia
| Zdarzenie | Kiedy | data |
|---|---|---|
work_order.completed |
Wykonano pełną ilość zlecenia produkcyjnego | work_order (id, number, external_ref, quantity, quantity_done, due_at, notes) i part (id, part_number, name, is_stocked) |
stock.changed |
Każdy ruch magazynowy. Przesunięcie to dwa | movement (id, type, quantity_delta, reference_type, reference_id, occurred_at), part, location, on_hand_here, on_hand_total |
ping |
Send test | {"hello": "world"} |
external_ref zlecenia produkcyjnego mówi drugiemu systemowi, czego dotyczyła praca. Utwórz serwis z numerem zewnętrznym „Hull 207”, a zdarzenie zakończenia to poda.
Co jest wysyłane
POST z treścią JSON:
{
"id": 412,
"type": "work_order.completed",
"occurred_at": "2026-10-01T14:11:18Z",
"text": "WO-00031 completed: 1 × Class 1 service (Hull 207).",
"data": { "work_order": { "number": "WO-00031", "external_ref": "Hull 207" }, "part": { } }
}
text to jedno zdanie dla człowieka. Ilości są ciągami znaków, tak jak w API.
| Nagłówek | Znaczenie |
|---|---|
X-Foudra-Event |
Typ zdarzenia |
X-Foudra-Event-Id |
Identyfikator zdarzenia, ten sam co id w treści |
X-Foudra-Delivery |
Identyfikator tego dostarczenia |
X-Foudra-Signature |
t=<unix time>,v1=<signature> |
Co musi zrobić odbiorca
- Odpowiedzieć szybko dowolnym statusem
2xx, a pracę wykonać później. Brak odpowiedzi w ciągu 10 sekund liczy się jako błąd. Przekierowania nie są obsługiwane. - Sprawdzić podpis. Oblicz HMAC-SHA256 z kluczem w postaci sekretu podpisu dla tekstu
<t>.<body>: wartośćtz nagłówka, kropka, a potem treść dokładnie w takiej postaci, w jakiej przyszła. Porównaj wynik, szesnastkowo, zv1. Odrzuć wiadomość, jeśli się różnią albo jeślitjest starsze niż kilka minut. - Liczyć się z powtórzeniami. Wiadomość może przyjść dwa razy. Zapamiętuj identyfikatory obsłużonych zdarzeń i ignoruj te, które już widziałeś.
import hmac, hashlib, time
def verify(secret: str, header: str, body: bytes) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
signed = parts["t"].encode() + b"." + body
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"]) and abs(time.time() - int(parts["t"])) < 300
Gdy coś zawiedzie
Nieudane dostarczenie jest ponawiane po 1 minucie, potem po 5, 15 minutach, godzinie, 3, 6 i 12 godzinach, a po ósmej próbie, mniej więcej dobę później, porzucane. Recent deliveries (ostatnie dostarczenia) pokazuje każde z nich, liczbę prób i ostatnią odpowiedź; Send now (wyślij teraz) od razu ponawia wybrane.
Po ośmiu nieudanych próbach z rzędu, bez żadnego sukcesu pomiędzy, webhook zostaje wyłączony, a na pulpicie pojawia się zadanie z przyczyną. Napraw odbiorcę, włącz webhook ponownie i użyj Send now dla wszystkiego, co zostało porzucone.
Zdarzenia są wysyłane mniej więcej w kolejności, w jakiej zachodzą, ale ponowione może przyjść po późniejszym. Jeśli kolejność ma znaczenie, korzystaj z occurred_at.