Sign inGet started

Zdarzenia e-mail

Emitujemy zdarzenia w miarę jak każdy odbiorca przechodzi przez proces dostarczania. Wysyłka na trzy adresy generuje trzy niezależne strumienie, powiązane przez email_id i recipient_id. Ta strona definiuje typy zdarzeń e-mail. Zobacz Webhooki, aby poznać sygnatury, ponawianie, kolejność i odtwarzanie.
Każdy odbiorca zaczyna od email.accepted, potem email.processed. Odbiorca broadcastu jest osobną wiadomością, więc otrzymuje własne email.accepted, choć tylko w zdarzeniach API i logu e-mail, a nie jako webhook. Dalej wiadomość zostaje zaakceptowana przez serwer odbiorczy (email.delivered), zostaje odroczona i ponowiona (email.deferred, co kończy się dostarczeniem lub odrzuceniem), zostaje odrzucona przez serwer odbiorczy (email.bounced) lub w ogóle nie dochodzi do próby dostarczenia (email.rejected). Po dostarczeniu strumień może kontynuować z email.out_of_band_bounce, email.complained, email.opened, email.clicked, email.unsubscribed i email.list_unsubscribed.
Każdy odbiorca kończy dokładnie z jednym statusem końcowym: delivered, bounced, complained lub rejected, zwracanym jako status per odbiorca z GET /v1/email/messages/{message_id}/recipients. Zdarzenia zaangażowania nigdy go nie zmieniają: odbiorca, który otworzył wiadomość, nadal ma status delivered. Późny raport o odrzuceniu zmienia go, ponieważ serwer odbiorczy wycofuje wcześniej udzieloną akceptację, więc odbiorca przechodzi z delivered do bounced. Wiadomość jako całość ma własny zbiorczy status i liczniki per stan na GET /v1/email/messages/{message_id}.

Koperta zdarzenia

Zdarzenia docierają jako trzyelementowa koperta używana przez każdy webhook: type, timestamp (kiedy zdarzenie wystąpiło, RFC 3339) i obiekt data specyficzny dla danego typu.
Przykład kodu
{
  "type": "email.delivered",
  "timestamp": "2026-07-23T14:51:47.107Z",
  "data": {
    "email_id": "em_01ky7qc398fmxraqtxn604zeq9",
    "recipient_id": "er_01ky7qc398fmwsc96nt6anrbqs",
    "workspace_id": "ws_01ky7m21hjffh9s8kq76gyb1xf",
    "recipient": "delivered@messagebird.dev",
    "recipient_role": "to",
    "tags": [{ "name": "category", "value": "welcome" }],
    "metadata": { "order_id": "ord_123" },
    "broadcast_id": null
  }
}
Każde zdarzenie wychodzące zawiera email_id, recipient_id, workspace_id, adres recipient i kopertę recipient_role (to, cc lub bcc). Powtarza też tags i metadata z żądania wysyłki, dzięki czemu możesz powiązać zdarzenie ze swoimi rekordami. Każda opcjonalna wartość to null, gdy wysyłka jej nie zawierała, włącznie z broadcast_id: wskazuje broadcast, w ramach którego wysłano wiadomość, dzięki czemu możesz grupować zdarzenia broadcastu bez wyszukiwania każdej wysyłki z osobna; wynosi null przy wysyłce bez broadcastu. W jednym przypadku raportowane jest null dla wysyłki, która broadcast miała: link rezygnacji z subskrypcji z wiadomości wysłanej zanim dodaliśmy to pole nie wskazuje żadnego broadcastu, więc rezygnacja przez taki link raportuje null w email.unsubscribed i email.list_unsubscribed niezależnie od tego, czy broadcast wysłał tę wiadomość. Traktuj null w tych dwóch zdarzeniach jako niekonkluzywne, w przeciwnym razie zaniżysz liczbę rezygnacji broadcastu. broadcast_id dociera do Ciebie tylko przez webhook: API poniżej zwraca każde zdarzenie bez niego. Typy zdarzeń dodają pola opisane w sekcjach cyklu życia, zaangażowania, supresji i ruchu przychodzącego.
Te same zdarzenia można odpytywać po fakcie z GET /v1/email/messages/{message_id}/events, gdzie każde z nich ma też id (prefiks ev_) i occurred_at. Użyj go do uzupełniania, odtwarzania lub uzgadniania z tym, co odebrał Twój endpoint. Kilka pól dociera do Ciebie tylko przez to API, a nie przez webhook; odpowiedni opis zdarzenia wskazuje każde z nich.

Zdarzenia cyklu życia

email.accepted

Przyjęliśmy wysyłkę i rozpoczęliśmy przygotowanie dostarczenia. Emitowane raz na żądanego odbiorcę i jest pierwszym zdarzeniem w tym strumieniu. Odbiorca broadcastu również je otrzymuje, ponieważ każdy odbiorca jest osobną wiadomością, ale jest ono rejestrowane, a nie dostarczane: odczytaj je z API lub logu e-mail, a nie z endpointu webhooka. Payload: tylko baza tożsamości.

email.processed

Wiadomość została zbudowana i umieszczona w kolejce do dostarczenia na serwer pocztowy odbiorcy. Payload: tylko baza tożsamości przez webhook; API dodaje mailbox_provider i mailbox_provider_region, klasyfikację odbiorczego systemu pocztowego (na przykład gmail, NA), obecną gdy udało się ją ustalić, a w przeciwnym razie null. Porównanie timestamp tego zdarzenia z email.accepted daje czas naszego przetwarzania pojedynczej wysyłki. Broadcast nie ma takiego interwału: jego akceptacja i przetworzenie mają ten sam moment wysyłki, więc oba znaczniki czasu się pokrywają zamiast obejmować jakiekolwiek przetwarzanie, a akceptacja dociera do Ciebie tylko przez API jako occurred_at.

email.delivered

Serwer pocztowy odbiorcy zaakceptował wiadomość i przejął za nią odpowiedzialność. To zdarzenie nie potwierdza umieszczenia w skrzynce odbiorczej ani przeczytania. Inbox Insights dostarcza szacunki umieszczenia na próbie; zdarzenia otwarć i kliknięć rejestrują żądania śledzenia. Payload: tylko baza tożsamości przez webhook; API dodaje sending_ip, adres, z którego wysłano wiadomość, co ma znaczenie, gdy problem z dostarczalnością dotyczy jednego IP, oraz mailbox_provider i mailbox_provider_region.

email.deferred

Tymczasowa awaria: serwer odbiorczy poprosił o ponowną próbę później (pełna skrzynka, greylisting, ograniczanie liczby żądań). Ponawiamy automatycznie, a odbiorca ostatecznie kończy jako email.delivered lub email.bounced, więc to zdarzenie jest informacyjne, nie końcowe, a odbiorca może zostać odroczony kilka razy wcześniej. Payload: bounce_type, bounce_class, defer_reason (powód podany przez serwer) i sending_ip przez webhook; API dodaje mailbox_provider i mailbox_provider_region.

Zdarzenia błędów

email.bounced

Trwała awaria w momencie SMTP: serwer odbiorczy odrzucił wiadomość, a status końcowy odbiorcy zmienia się na bounced. Payload: bounce_type (zobacz tabelę klasyfikacji), bounce_class, bounce_code (kod odpowiedzi SMTP, na przykład 550), bounce_description (powód podany przez serwer) i sending_ip przez webhook; API dodaje mailbox_provider i mailbox_provider_region. Twarde odrzucenie blokuje adres.

email.out_of_band_bounce

Późne odrzucenie: serwer odbiorczy zaakceptował wiadomość w momencie SMTP, a następnie wysłał raport o odrzuceniu. Ma tę samą klasyfikację co email.bounced (bounce_type, bounce_class, bounce_code, bounce_description, sending_ip przez webhook; mailbox_provider i mailbox_provider_region z API). Gdy raport klasyfikuje się jako odrzucenie (dowolna klasa w tabeli), serwer wycofał wcześniejszą akceptację, więc odbiorca przechodzi z delivered do bounced. Raporty, których klasa nie znajduje się w tabeli, na przykład automatyczne odpowiedzi, są rejestrowane na osi czasu i nie zmieniają statusu. Twarde późne odrzucenie również blokuje adres.

email.rejected

Odbiorca nigdy nie dotarł do zdalnego serwera pocztowego, więc nie podjęto próby dostarczenia. To właśnie odróżnia odrzucenie od bounce'a, gdzie to serwer odbiorczy mówi nie. Payload: rejection_reason, również w rekordzie odbiorcy, jedna z wartości:
rejection_reasonZnaczenie
recipient_suppressedOdbiorca jest zablokowany na poziomie obszaru roboczego przez listę supresji lub zadeklarowaną preferencję, więc nie podjęto próby dostarczenia
transmission_failedWiadomość nie mogła zostać przesłana do dostarczenia
generation_failureWiadomość nie mogła zostać zbudowana do dostarczenia, problem z szablonem lub treścią
policy_rejectionPolityka wysyłki odrzuciła wiadomość
domain_unverifiedDomena wysyłająca nie została zweryfikowana
quota_exceededLimit wysyłki organizacji został osiągnięty
recipient_not_allowedOdbiorca nie był dozwolony dla tej wysyłki; wysyłki na współdzielonej domenie onboardingowej trafiają wyłącznie do zweryfikowanych członków Twojego obszaru roboczego
API dodaje też mailbox_provider i mailbox_provider_region, gdy odbiorczy system pocztowy mógł zostać sklasyfikowany przed odrzuceniem.

email.complained

Odbiorca oznaczył wiadomość jako spam, a dostawca skrzynki zgłosił to z powrotem przez swoją pętlę zwrotną. Skargi docierają po dostarczeniu i ustawiają status końcowy na complained. Payload: feedback_type, rodzaj raportu wysłanego przez dostawcę, na przykład abuse lub fraud, oraz null gdy dostawca tego nie określił, plus mailbox_provider i mailbox_provider_region z API. Skarga blokuje adres dla wiadomości marketingowych. Utrzymuj niski wskaźnik skarg: dostawcy ograniczają nadawców, którzy zbierają raporty.

Zdarzenia zaangażowania

email.opened

Piksel śledzący w treści wiadomości został załadowany. Payload: ip_address i user_agent gdy znane; API dodaje is_prefetched, country (ISO 3166-1 alpha-2, określony na podstawie IP klienta), mailbox_provider i mailbox_provider_region. Sprawdź is_prefetched zanim zliczysz otwarcie. Przyjmuje wartość true, gdy funkcja prywatności skrzynki automatycznie pobrała piksel zamiast osoby otwierającej wiadomość, a zliczanie takich przypadków zawyża wskaźnik otwarć. Śledzenie otwarć i kliknięć opisuje instrumentację.

email.clicked

Odbiorca kliknął śledzony link. Payload: url (kliknięty link), ip_address i user_agent gdy znane; API dodaje country, mailbox_provider i mailbox_provider_region. Kliknięcia są na ogół silniejszym sygnałem zaangażowania niż otwarcia, ponieważ proxy prywatności mogą automatycznie ładować piksele śledzące.

email.unsubscribed

Odbiorca użył linku rezygnacji z subskrypcji w treści wiadomości. Payload: tylko baza tożsamości przez webhook; API dodaje mailbox_provider i mailbox_provider_region. Rejestruje preferencję rezygnacji, która blokuje wiadomości marketingowe. Linki rezygnacji z subskrypcji opisują, jak link trafia do Twojej wiadomości.

email.list_unsubscribed

Odbiorca użył przycisku rezygnacji z subskrypcji jednym kliknięciem, renderowanego przez dostawcę skrzynki w jego własnym interfejsie, sterowanego nagłówkami List-Unsubscribe wiadomości. Payload: tylko baza tożsamości przez webhook (plus mailbox_provider i mailbox_provider_region z API); mechanizmem jest sam typ zdarzenia, dlatego jest oddzielony od email.unsubscribed. Również rejestruje preferencję rezygnacji, która blokuje wiadomości marketingowe.

Zdarzenia na poziomie wiadomości

Dwa zdarzenia opisują wiadomość jako całość, a nie pojedynczego odbiorcę, więc ich data zawiera email_id, workspace_id, tags i metadata, ale nie zawiera tożsamości odbiorcy. Oba należą do wysyłki zaplanowanej.

email.scheduled

Przyjęliśmy wysyłkę z scheduled_at w przyszłości. Payload: baza na poziomie wiadomości plus scheduled_at. Gdy ten czas nadejdzie, cykl życia per odbiorca zaczyna się od email.accepted.

email.canceled

Zaplanowana wiadomość została anulowana zanim została wysłana, więc nie generuje żadnych zdarzeń cyklu życia odbiorcy. Payload: tylko baza na poziomie wiadomości.

Zdarzenia przychodzące i skrzynkowe

email.received obejmuje pocztę przychodzącą. Emitowane, gdy odbieramy i parsujemy wiadomość przychodzącą. Payload zawiera inbound_message_id, adresowanie, temat i werdykty uwierzytelniania. Konfiguracja, payload i API do pobierania są opisane w Odbieranie e-mail. Skrzynka ma własną rodzinę email_mailbox.*, opisaną w przewodniku po skrzynkach.

Klasyfikacja odrzuceń

bounce_class to numeryczna klasyfikacja odrzuceń dołączana do email.bounced, email.out_of_band_bounce i email.deferred. Agreguje się do ogólnej bounce_type i zachowuje szczegółowy kod, dzięki czemu możesz odróżnić pełną skrzynkę od błędu routingu, mimo że oba raportują się jako soft:
bounce_classbounce_typeZnaczenie
1undeterminedOdpowiedź serwera odbiorczego była niejednoznaczna
10, 30hardTrwała awaria: nieprawidłowy adres lub nieistniejąca domena
20 to 24, 40, 70, 100softTymczasowa awaria: pełna skrzynka, serwer tymczasowo niedostępny, problem z DNS lub routingiem
25adminOdmowa administracyjna: przekazywanie odrzucone, zablokowana domena
50 to 54blockSerwer odbiorczy odrzucił wysyłające IP
Każda klasa spoza tej listy mapuje się na undetermined. Tylko odrzucenia hard blokują adres; soft, block, admin i undetermined nie, ponieważ adres może nadal być dostarczalny.

Automatyczna supresja

Dwa zdarzenia automatycznie dodają odbiorcę do listy supresji obszaru roboczego i blokują różne rodzaje wiadomości:
ZdarzenieSupresja reasonCo blokuje
email.bounced lub email.out_of_band_bounce z bounce_type: "hard"hard_bounceWszystkie wiadomości, łącznie z transakcyjnymi
email.complainedcomplaintWiadomości marketingowe; transakcyjne nadal są wysyłane
Twarde odrzucenie blokuje wszystko, ponieważ sam adres już nie istnieje. Skarga blokuje tylko marketing, ponieważ ktoś, kto zgłosił Twój newsletter jako spam, nadal potrzebuje resetu hasła.
email.unsubscribed i email.list_unsubscribed blokują wiadomości tak samo jak skarga, tylko marketing, ale przez inny rekord: zamiast dodawać supresję, rejestrują rezygnację odbiorcy jako zadeklarowaną preferencję. Co robi rezygnacja opisuje ten rekord w całości.
Każde dodanie emituje zdarzenie email_suppression.created, które zawiera suppression_id, zablokowany email, reason i workspace_id. Pełny schemat rekordu i sposób ręcznego zarządzania wpisami opisuje Przewodnik po supresjach.
Późniejsze wysyłki na zablokowany adres są od razu odrzucane jako email.rejected z rejection_reason: "recipient_suppressed" i nigdy nie wpływają na Twoją dostarczalność.

Następne kroki