Tipi di evento
Iscriviti a qualsiasi combinazione di questi tipi di evento quando crei un webhook.
| Evento | Viene emesso quando | Imposta last_event su |
|---|---|---|
email.scheduled |
Un’email con scheduled_at è stata accettata. |
scheduled |
email.sent |
L’email è stata consegnata ad Amazon SES. | sent |
email.delivered |
Il server di posta del destinatario ha accettato l’email. | delivered |
email.delivery_delayed |
La consegna è in ritardo o fallisce temporaneamente; SES continua a riprovare. | delivery_delayed |
email.bounced |
Errore permanente (l’indirizzo non esiste, il dominio rifiuta). | bounced |
email.complained |
Il destinatario ha segnalato l’email come spam. | complained |
email.opened |
Il destinatario ha aperto l’email (richiede il tracciamento delle aperture). | opened |
email.clicked |
Il destinatario ha cliccato su un link (richiede il tracciamento dei clic). | clicked |
email.failed |
SpacePost o SES non hanno potuto inviare l’email (rifiutata, errore di rendering, team o tenant in pausa). | failed |
email.suppressed |
Un destinatario è stato saltato perché è nella tua lista di soppressione. | suppressed |
Struttura del payload
Sezione intitolata “Struttura del payload”I corpi dei webhook sono esattamente quelli di Resend, quindi i gestori scritti per Resend continuano a funzionare.
{ "type": "email.delivered", "created_at": "2026-10-23T14:02:10.000Z", "data": { "email_id": "0192e1c4-7a3b-7c1e-9d2f-3b5a8e6f4c10", "from": "Acme <hello@acme.com>", "to": ["user@example.com"], "subject": "Welcome to Acme", "created_at": "2026-10-23T14:02:09.512Z", "broadcast_id": "0192e1c4-0000-7000-8000-0000000000bb", "tenant_id": "0192e1c4-5555-7000-8000-0000000000cc", "tags": { "category": "welcome" } }}typeè l’evento;created_atè il momento in cui l’evento è avvenuto.data.email_id,from,to(tutti i destinatari dell’email, non solo quello interessato),subjectecreated_at(quando l’email è stata creata) sono sempre presenti.data.broadcast_idè presente solo per le email di campagna.data.tenant_idè presente solo quando l’email è stata inviata per un tenant (modalità piattaforma). È il nostro id del tenant, non il tuoexternal_id.data.tagsè presente solo se l’email aveva dei tag, come oggetto ({ "name": "value" }).- Alcuni eventi aggiungono a
dataun ulteriore oggetto, chiamato come l’evento:bounce,click,open,failedosuppressed. Sono elencati qui sotto. Non viene aggiunto nient’altro: non ci sono chiavi di primo livellobounceType,delayTypeoreason.
email.scheduled
Sezione intitolata “email.scheduled”{ "type": "email.scheduled", "created_at": "2026-10-23T14:02:09.700Z", "data": { "email_id": "0192e1c4-7a3b-7c1e-9d2f-3b5a8e6f4c10", "from": "Acme <hello@acme.com>", "to": ["user@example.com"], "subject": "Your trial ends tomorrow", "created_at": "2026-10-23T14:02:09.512Z" }}email.sent
Sezione intitolata “email.sent”{ "type": "email.sent", "created_at": "2026-10-23T14:02:10.100Z", "data": { "email_id": "0192e1c4-7a3b-7c1e-9d2f-3b5a8e6f4c10", "from": "Acme <hello@acme.com>", "to": ["user@example.com"], "subject": "Welcome to Acme", "created_at": "2026-10-23T14:02:09.512Z" }}email.delivered
Sezione intitolata “email.delivered”{ "type": "email.delivered", "created_at": "2026-10-23T14:02:11.350Z", "data": { "email_id": "0192e1c4-7a3b-7c1e-9d2f-3b5a8e6f4c10", "from": "Acme <hello@acme.com>", "to": ["user@example.com"], "subject": "Welcome to Acme", "created_at": "2026-10-23T14:02:09.512Z" }}email.delivery_delayed
Sezione intitolata “email.delivery_delayed”Emesso per i ritardi di consegna di SES e per i rimbalzi temporanei. Per un semplice ritardo non ci sono campi aggiuntivi. Un rimbalzo temporaneo include anche l’oggetto bounce (vedi sotto, con type: "Transient").
{ "type": "email.delivery_delayed", "created_at": "2026-10-23T14:07:00.000Z", "data": { "email_id": "0192e1c4-7a3b-7c1e-9d2f-3b5a8e6f4c10", "from": "Acme <hello@acme.com>", "to": ["user@example.com"], "subject": "Welcome to Acme", "created_at": "2026-10-23T14:02:09.512Z" }}email.bounced
Sezione intitolata “email.bounced”Solo i rimbalzi permanenti raggiungono questo evento, e aggiungono l’indirizzo alla tua lista di soppressione. data.bounce contiene type (Permanent), subType e il message del server ricevente.
{ "type": "email.bounced", "created_at": "2026-10-23T14:02:12.000Z", "data": { "email_id": "0192e1c4-7a3b-7c1e-9d2f-3b5a8e6f4c10", "from": "Acme <hello@acme.com>", "to": ["nobody@example.com"], "subject": "Welcome to Acme", "created_at": "2026-10-23T14:02:09.512Z", "bounce": { "type": "Permanent", "subType": "General", "message": "smtp; 550 5.1.1 The email account that you tried to reach does not exist." } }}I sottotipi di rimbalzo includono General, NoEmail, Suppressed, OnAccountSuppressionList, MailboxFull, MessageTooLarge, ContentRejected e AttachmentRejected.
email.complained
Sezione intitolata “email.complained”Nessun campo aggiuntivo. L’indirizzo viene aggiunto alla tua lista di soppressione.
{ "type": "email.complained", "created_at": "2026-10-23T15:30:00.000Z", "data": { "email_id": "0192e1c4-7a3b-7c1e-9d2f-3b5a8e6f4c10", "from": "Acme <hello@acme.com>", "to": ["user@example.com"], "subject": "Our monthly newsletter", "created_at": "2026-10-23T14:02:09.512Z" }}email.opened
Sezione intitolata “email.opened”{ "type": "email.opened", "created_at": "2026-10-23T14:05:44.000Z", "data": { "email_id": "0192e1c4-7a3b-7c1e-9d2f-3b5a8e6f4c10", "from": "Acme <hello@acme.com>", "to": ["user@example.com"], "subject": "Welcome to Acme", "created_at": "2026-10-23T14:02:09.512Z", "open": { "ipAddress": "203.0.113.7", "userAgent": "Mozilla/5.0 (Macintosh)" } }}email.clicked
Sezione intitolata “email.clicked”{ "type": "email.clicked", "created_at": "2026-10-23T14:06:10.000Z", "data": { "email_id": "0192e1c4-7a3b-7c1e-9d2f-3b5a8e6f4c10", "from": "Acme <hello@acme.com>", "to": ["user@example.com"], "subject": "Welcome to Acme", "created_at": "2026-10-23T14:02:09.512Z", "click": { "link": "https://acme.com/get-started", "ipAddress": "203.0.113.7", "userAgent": "Mozilla/5.0 (Macintosh)", "timestamp": "2026-10-23T14:06:10.000Z" } }}email.failed
Sezione intitolata “email.failed”{ "type": "email.failed", "created_at": "2026-10-23T14:02:10.000Z", "data": { "email_id": "0192e1c4-7a3b-7c1e-9d2f-3b5a8e6f4c10", "from": "Acme <hello@acme.com>", "to": ["user@example.com"], "subject": "Welcome to Acme", "created_at": "2026-10-23T14:02:09.512Z", "failed": { "reason": "Attachment https://files.acme.com/report.pdf returned HTTP 404" } }}email.suppressed
Sezione intitolata “email.suppressed”suppressed.reason è suppression_list (il destinatario è nella tua lista di soppressione) oppure recipient_domain_does_not_accept_mail (il dominio del destinatario non ha un server di posta).
{ "type": "email.suppressed", "created_at": "2026-10-23T14:02:10.000Z", "data": { "email_id": "0192e1c4-7a3b-7c1e-9d2f-3b5a8e6f4c10", "from": "Acme <hello@acme.com>", "to": ["user@example.com", "other@example.com"], "subject": "Welcome to Acme", "created_at": "2026-10-23T14:02:09.512Z", "suppressed": { "recipients": ["other@example.com"], "reason": "suppression_list" } }}Tipizzare gli eventi in TypeScript
Sezione intitolata “Tipizzare gli eventi in TypeScript”L’SDK Node esporta un’unione WebhookPayload discriminata da type, e spacepost.webhooks.verify() la restituisce, quindi restringere su event.type ti dà i campi data corretti:
import type { WebhookPayload } from "@spacepost/node";
function handle(event: WebhookPayload) { switch (event.type) { case "email.bounced": return event.data.bounce?.subType; case "email.clicked": return event.data.click?.link; case "email.suppressed": return event.data.suppressed.recipients; case "email.failed": return event.data.failed.reason; default: return event.data.tenant_id; // present when the email was sent for a tenant }}