Przejdź do dokumentacji
Baza wiedzy

Webhooki

Powiadom swój endpoint, gdy przyjdzie poczta, zamiast zmuszać Cię do odpytywania.

Szczegóły

  • Dostępne już dziś z Ustawienia → Webhooki i przez API: zarejestruj endpoint https, wybierz, których z dwudziestu zdarzeń ma dotyczyć, i skopiuj sekret podpisujący whsec_, który pokazywany jest przy utworzeniu i przy rotacji, i nigdy więcej. Dostarczenia to prawdziwe, podpisane żądania POST wywoływane przez samą skrzynkę, a nie przez jakiekolwiek wywołanie API, więc wyzwalają się na poczcie przychodzącej oraz na otwarciach i kliknięciach, niezależnie od tego, co wysłało wiadomość. Wysyłka wyzwala zdarzenie z każdej powierzchni, a kiedyś wyzwalała tylko z niektórych: wysyłka przez API, MCP, szablon albo regułę podnosiła email.sent, a wiadomość wysłana z własnego okna tworzenia w aplikacji już nie, bo edytor zapisuje do skrzynki bezpośrednio, a nie przez usługę wysyłki emitującą to zdarzenie. Zdarzenie jest teraz podnoszone przy samej skrzynce, czyli tam, gdzie wszystkie się spotykają, więc napisanie wiadomości w aplikacji, zaplanowanie jej na wtorek i wysłanie przez API to trzy sposoby wywołania tego samego webhooka. Wysyłka odroczona mówi o sobie dwa razy: email.scheduled albo email.queued, gdy zostaje przyjęta, email.sent, gdy naprawdę wychodzi, i email.cancelled, jeśli w międzyczasie ją wycofasz. Dziesięć endpointów na skrzynkę, egzekwowane wszędzie tam, gdzie rejestruje się endpoint, a nie tylko na tym ekranie.
  • Zdarzenia dzielą się na trzy rodziny. Piętnaście dotyczy jednej wiadomości: email.received, email.replied, email.sent, email.delivered, email.failed, email.cancelled, email.scheduled, email.queued (odpowiednik scheduled dla cofnięcia wysyłki), email.delivery_delayed, email.bounced, email.complained, email.suppressed, email.opened, email.clicked i email.downloaded. email.sent znaczy, że usługa wysyłki przyjęła wiadomość, email.delivered — że przyjął ją serwer odbiorcy, a email.delivery_delayed — że jeszcze nie dotarła i próby są ponawiane. email.replied wyzwala się obok email.received, gdy przychodząca wiadomość odpowiada na taką, która jest już w skrzynce, więc konsument, który chce obu, dostaje oba. email.downloaded wyzwala się, gdy człowiek pobiera plik, który wyszedł jako link do pobrania, przy czym ten sam klasyfikator trzyma skanery i podglądy linków poza licznikiem, i nie wskazuje żadnego odbiorcy, bo link jest ten sam dla wszystkich, do których poszła wiadomość. Trzy dotyczą domeny: domain.verified, gdy zaczyna odbierać, domain.sending_changed, gdy zmienia się jej werdykt wysyłki, i domain.deleted, gdy zostaje usunięta, czy to na Twoją prośbę, czy przez siedmiodniowego żniwiarza, który usunął ją niezweryfikowaną. Dwa dotyczą samej listy blokad, która jest czym innym niż email.suppressed: suppression.added, gdy adres na nią trafia, i suppression.removed, gdy znów jest dopuszczony. Niesubskrybowanie żadnego z nich oznacza każde zdarzenie wiadomości oprócz email.replied, dziś czternaście, nigdy rodzinę dodaną później, a API odczytuje to z powrotem jako ["*"]. Wymień zdarzenia, których chcesz, jeśli wolisz mówić wprost. Każde dostarczenie niesie X-OpenEmail-Signature w postaci t=<unix>,v1=<hex>, czyli HMAC-SHA-256 po znaczniku czasu, kropce i surowym ciele żądania, plus X-OpenEmail-Event i X-OpenEmail-Delivery. Weryfikuj po bajtach w postaci, w jakiej przyszły: sparsowanie i ponowna serializacja zmienia kolejność kluczy i psuje podpis. 300-sekundowe okno powtórzeń egzekwuje odbiorca, a weryfikator w SDK przyjmuje je domyślnie.
  • Rejestracja jest odrzucana dla wszystkiego, co nie jest https albo nie jest publicznie routowalne (pętla zwrotna, RFC1918, link-local, CGNAT i ich odpowiedniki w IPv6), a przekierowania nie są śledzone, więc 3xx jest zapisywane jako nieudane dostarczenie, a nie gonione gdzie indziej. Odbiorca dostaje 5 sekund, endpointy są obsługiwane równolegle, więc dziesięć z nich wciąż kosztuje 5 sekund, a nie 50, a ostatnie próby są wypisane na stronie danego endpointu wraz z kodem odpowiedzi i czasem trwania.
  • Dostarczenie jest próbowane maksymalnie pięć razy. Pierwsza próba wychodzi w chwili zdarzenia; niepowodzenie, które może się samo wyjaśnić, jest ponawiane po 1 minucie, potem po 5, po 25 i po 2 godzinach, co rozkłada jedno zdarzenie na około dwie i pół godziny. Ponowienia są trzymane jako trwała praca, a nie w pamięci, więc wdrożenie w środku tego okna ich nie gubi. Powtarzane są tylko niepowodzenia warte powtórzenia: przekroczenie czasu, odrzucone połączenie, 408, 425, 429 albo dowolne 5xx. Każde inne 4xx to świadome odrzucenie ładunku przez endpoint, a pytanie cztery razy więcej to czterokrotne obciążenie dla tej samej odpowiedzi. Identyfikator zdarzenia jest tworzony raz i każda próba niesie go w X-OpenEmail-Delivery, więc odbiorca, który widzi to samo id dwa razy, może odrzucić drugie, zamiast zadziałać dwukrotnie. Po 100 zdarzeniach z rzędu, w których zawiodła każda próba, endpoint zostaje wyłączony, obszar roboczy dostaje wiadomość e-mail, a powód można odczytać przy samym endpointcie. Endpoint odpowiadający 410 Gone jest wyłączany od ręki.
  • Endpoint, który zawiedzie 100 razy z rzędu, jest wyłączany, a nie wybierany w nieskończoność, i każdy z dostępem do webhooków dostaje o tym e-mail: który to endpoint, co zgłosiła ostatnia próba i że nic nie było kolejkowane, gdy zawodził. Licznik liczy próby POD RZĄD i każde udane dostarczenie go zeruje, więc jedno złe popołudnie w marcu nie może zsumować się do wyłączonego endpointu dzisiaj. Ponowne włączenie zeruje licznik wraz z nim. Konsola rozróżnia te dwa stany, zamiast pokazywać jeden przełącznik: endpoint, który wyłączyłeś, wygląda inaczej niż ten, który wyłączyliśmy my.
  • Zarządzanie endpointami to jedno zadanie z dwoma wejściami. Przez API są to POST /webhooks, patch, delete, rotacja sekretu, test i log dostarczeń, z metodą dla każdego z nich w SDK; w aplikacji jest to Ustawienia → Webhooki, działające na tym samym rejestrze, a nie na drugim. Odczyt jest bramkowany przez webhooks:read, więc każdy, kto buduje integrację, może zobaczyć endpointy i historię ich dostarczeń (który się wyzwolił, co odpowiedział odbiorca, ile to trwało), nie będąc właścicielem. Rejestrowanie, edytowanie, testowanie, rotowanie i usuwanie wymagają webhooks:write ORAZ własności skrzynki, na obu powierzchniach, i ta druga połowa jest celowa: endpoint nie ma osi adresów, więc otrzymuje każdy adres posiadany przez obszar roboczy, z tematami i odbiorcami, a brak uprawnienia znaczy „można mu to wszystko wysłać”. Rola, która buduje integracje i nie czyta poczty, obsługuje je zamiast tego kluczem obszaru roboczego.