События вебхуков

Как сказано в обзоре, вебхуки позволяют строить приложения, управляемые событиями.

Agent Inbox поддерживает несколько типов событий для полноценных событийных сценариев почтовых агентов.

Все полезные нагрузки вебхуков имеют одну базовую структуру:

1{
2 "type": "event",
3 "event_type": "event.name",
4 "event_id": "evt_123abc..."
5 // ... event-specific data object
6}

Разбор событий через SDK

В SDK Agent Inbox есть типизированные классы для каждого события вебхука — сырые полезные нагрузки можно разобрать в типизированные объекты.

1import { serialization } from "agentinbox";
2
3async function handleWebhook(payload: Record<string, unknown>) {
4 const eventType = payload.event_type;
5
6 if (eventType === "message.received") {
7 const event = await serialization.events.MessageReceivedEvent.parse(payload);
8 // access typed fields
9 console.log(event.message.subject);
10 console.log(event.thread.messageCount);
11 } else if (eventType === "message.sent") {
12 const event = await serialization.events.MessageSentEvent.parse(payload);
13 console.log(event.send.recipients);
14 } else if (eventType === "message.bounced") {
15 const event = await serialization.events.MessageBouncedEvent.parse(payload);
16 console.log(event.bounce.type);
17 } else if (eventType === "message.delivered") {
18 const event = await serialization.events.MessageDeliveredEvent.parse(payload);
19 console.log(event.delivery.recipients);
20 } else if (eventType === "message.complained") {
21 const event = await serialization.events.MessageComplainedEvent.parse(payload);
22 console.log(event.complaint.type);
23 } else if (eventType === "message.rejected") {
24 const event = await serialization.events.MessageRejectedEvent.parse(payload);
25 console.log(event.reject.reason);
26 } else if (eventType === "domain.verified") {
27 const event = await serialization.events.DomainVerifiedEvent.parse(payload);
28 console.log(event.domain.status);
29 }
30}

Копировать в Cursor / Claude

Скопируйте один из блоков ниже для разбора событий вебхука за один раз.

1"""
2Agent Inbox Webhook Events — copy into Cursor/Claude.
3
4Parse typed events: MessageReceivedEvent (has message+thread), MessageSentEvent (send), MessageBouncedEvent (bounce),
5MessageDeliveredEvent (delivery), MessageComplainedEvent (complaint), MessageRejectedEvent (reject), DomainVerifiedEvent (domain).
6Only message.received includes full message+thread; others have send/delivery/bounce/complaint/reject/domain.
7"""
8from agentinbox import (
9 MessageReceivedEvent, MessageSentEvent, MessageBouncedEvent,
10 MessageDeliveredEvent, MessageComplainedEvent, MessageRejectedEvent, DomainVerifiedEvent,
11)
12
13def handle(payload: dict):
14 t = payload.get("event_type")
15 if t == "message.received": e = MessageReceivedEvent(**payload); print(e.message.subject, e.thread.message_count)
16 elif t == "message.sent": e = MessageSentEvent(**payload); print(e.send.recipients)
17 elif t == "message.bounced": e = MessageBouncedEvent(**payload); print(e.bounce.type)
18 elif t == "message.delivered": e = MessageDeliveredEvent(**payload)
19 elif t == "message.complained": e = MessageComplainedEvent(**payload)
20 elif t == "message.rejected": e = MessageRejectedEvent(**payload); print(e.reject.reason)
21 elif t == "domain.verified": e = DomainVerifiedEvent(**payload); print(e.domain.status)

События сообщений

message.received

  • Описание: срабатывает, когда новое письмо успешно получено и обработано в одном из ваших ящиков (Inboxes). Чаще всего это триггер для запуска сценариев агента.
  • Пример сценария: запуск внутреннего процесса, когда жалоба клиента попадает в ящик поддержки

Важно: только у message.received в полезной нагрузке есть и метаданные цепочки (Thread), и сообщения (Message). У остальных типов событий в теле только метаданные самого события. Если нужны метаданные и для других типов — напишите на info@patternautomation.com.

Поля text и preview могут отсутствовать, если исходное письмо содержит только HTML без текстовой части. Так бывает у пересланных писем из Gmail и Outlook. При обработке входящих опирайтесь в первую очередь на html, а text считайте необязательным.

1{
2 "type": "event",
3 "event_type": "message.received",
4 "event_id": "evt_123abc",
5 "message": {
6 "inbox_id": "inbox_456def",
7 "thread_id": "thd_789ghi",
8 "message_id": "<abc123@agentinbox.space>",
9 "labels": ["received"],
10 "timestamp": "2023-10-27T10:00:00Z",
11 "from": "Jane Doe <jane@example.com>",
12 "to": ["Support Agent <info@patternautomation.com>"],
13 "subject": "Question about my account",
14 "preview": "A short preview of the email text...",
15 "text": "The full text body of the email.",
16 "html": "<html>...</html>",
17 "size": 2048,
18 "updated_at": "2023-10-27T10:00:00Z",
19 "created_at": "2023-10-27T10:00:00Z"
20 },
21 "thread": {
22 "inbox_id": "inbox_456def",
23 "thread_id": "thd_789ghi",
24 "labels": ["received"],
25 "timestamp": "2023-10-27T10:00:00Z",
26 "senders": ["Jane Doe <jane@example.com>"],
27 "recipients": ["Support Agent <info@patternautomation.com>"],
28 "subject": "Question about my account",
29 "preview": "A short preview of the email text...",
30 "last_message_id": "<abc123@agentinbox.space>",
31 "message_count": 1,
32 "size": 2048,
33 "updated_at": "2023-10-27T10:00:00Z",
34 "created_at": "2023-10-27T10:00:00Z"
35 }
36}

message.sent

  • Описание: срабатывает, когда сообщение успешно отправлено из одного из ваших ящиков.
  • Сценарий: учёт исходящих, обновление БД или последующие шаги после отправки.
1{
2 "type": "event",
3 "event_type": "message.sent",
4 "event_id": "evt_456def",
5 "send": {
6 "inbox_id": "inbox_456def",
7 "thread_id": "thd_789ghi",
8 "message_id": "<abc123@agentinbox.space>",
9 "timestamp": "2023-10-27T10:05:00Z",
10 "recipients": [
11 "recipient@example.com"
12 ]
13 }
14}

message.delivered

  • Описание: срабатывает, когда отправленное письмо успешно доставлено на почтовый сервер получателя.
  • Сценарий: подтверждение доставки, обновление статуса, сценарии подтверждения доставки.
1{
2 "type": "event",
3 "event_type": "message.delivered",
4 "event_id": "evt_789ghi",
5 "delivery": {
6 "inbox_id": "inbox_456def",
7 "thread_id": "thd_789ghi",
8 "message_id": "<abc123@agentinbox.space>",
9 "timestamp": "2023-10-27T10:06:00Z",
10 "recipients": [
11 "recipient@example.com"
12 ]
13 }
14}

В чём разница между message.sent и message.delivered?

message.sent значит, что письмо успешно ушло с наших серверов и путешествует по сети. Обычно это происходит раньше, чем message.delivered: последнее значит, что принимающий сервер (Gmail, Outlook и т. п.) ответил 200 OK — письмо им принято. Что они с ним дальше делают — нам неизвестно.

Нет. Как сказано выше, message.delivered значит, что почтовый сервер получателя сообщил: «Мы получили письмо, дальше сами». У провайдеров свои алгоритмы — попадёт ли письмо во входящие или в спам. Со своей стороны мы делаем всё нужное, чтобы письма выглядели для провайдеров как легитимные для основного ящика.

message.bounced

  • Описание: срабатывает, когда отправка не удалась и письмо отскочило. Включает тип и подтип отскока.
  • Сценарий: обработка отскоков, обновление статуса получателя, сценарии после bounce.
1{
2 "type": "event",
3 "event_type": "message.bounced",
4 "event_id": "evt_012jkl",
5 "bounce": {
6 "inbox_id": "inbox_456def",
7 "thread_id": "thd_789ghi",
8 "message_id": "<abc123@agentinbox.space>",
9 "timestamp": "2023-10-27T10:07:00Z",
10 "type": "Permanent",
11 "sub_type": "General",
12 "recipients": [
13 {
14 "address": "invalid@example.com",
15 "status": "bounced"
16 }
17 ]
18 }
19}

message.complained

  • Описание: срабатывает, когда получатель пометил письмо как спам или подал жалобу.
  • Сценарий: реакция на жалобы, репутация отправителя, внутренние процессы по жалобам.
1{
2 "type": "event",
3 "event_type": "message.complained",
4 "event_id": "evt_345mno",
5 "complaint": {
6 "inbox_id": "inbox_456def",
7 "thread_id": "thd_789ghi",
8 "message_id": "<abc123@agentinbox.space>",
9 "timestamp": "2023-10-27T10:08:00Z",
10 "type": "abuse",
11 "sub_type": "spam",
12 "recipients": [
13 "complainer@example.com"
14 ]
15 }
16}

message.rejected

  • Описание: срабатывает, когда отправка отклонена до фактической отправки — обычно из‑за ошибок валидации или политики.
  • Сценарий: логирование причин, сценарии валидации.
1{
2 "type": "event",
3 "event_type": "message.rejected",
4 "event_id": "evt_678pqr",
5 "reject": {
6 "inbox_id": "inbox_456def",
7 "thread_id": "thd_789ghi",
8 "message_id": "<abc123@agentinbox.space>",
9 "timestamp": "2023-10-27T10:09:00Z",
10 "reason": "Invalid recipient address"
11 }
12}

Если вы отправляете на адрес со статусом bounced, rejected или после complained, мы блокируем дальнейшую отправку на этот адрес, чтобы держать низкий уровень отскоков. Следите, чтобы доля отскоков аккаунта была ниже 4%, иначе аккаунт может попасть на проверку.

События домена

domain.verified

  • Описание: срабатывает, когда домен успешно верифицирован и готов к отправке.
  • Сценарий: автоматическое включение функций домена, обновление статуса, шаги после верификации.
1{
2 "type": "event",
3 "event_type": "domain.verified",
4 "event_id": "evt_901stu",
5 "domain": {
6 "domain_id": "dom_123abc",
7 "status": "verified",
8 "feedback_enabled": true,
9 "records": [
10 // ... DNS verification records
11 ],
12 "created_at": "2023-10-27T09:00:00Z",
13 "updated_at": "2023-10-27T10:00:00Z"
14 }
15}

Фильтрация событий

При создании вебхука можно указать, на какие события подписываться. Это позволяет:

  • снизить трафик вебхуков, подписавшись только на нужное;
  • завести отдельные вебхуки под отдельные сценарии.

Например, только на входящие — message.received. Для трекинга доставки — message.sent, message.delivered и message.bounced.