Salta ai contenuti

Buone pratiche per i webhook

Verifica la firma, metti l’evento in coda (riga di database, coda, job in background) e restituisci subito 2xx. SpacePost attende al massimo 15 secondi, e un gestore lento si trasforma in nuovi tentativi e duplicati.

La consegna è at-least-once (almeno una volta). Salva il webhook-id di ogni consegna elaborata (basta un vincolo di unicità) e salta le ripetizioni.

const inserted = await db.insert(processedWebhooks).values({ id: webhookId }).onConflictDoNothing().returning();
if (inserted.length === 0) return new Response("duplicate", { status: 200 });

Usa il corpo grezzo, rifiuta i timestamp più vecchi di 5 minuti, confronta le firme in tempo costante (l’SDK e le librerie lo fanno). Vedi Verificare le firme.

Gli eventi possono arrivare in ordine sparso, soprattutto dopo i nuovi tentativi. Confronta il created_at del payload con quanto hai salvato e applica solo le modifiche che fanno avanzare lo stato. Anche il last_event di SpacePost segue la stessa regola.

Evento Azione tipica
email.bounced Segna l’indirizzo come non valido nel tuo database; smetti di inviargli email.
email.complained Annulla subito l’iscrizione dell’utente alle email non essenziali.
email.delivery_delayed Di solito nulla; avvisa se si tratta di un’email urgente (reimpostazione della password).
email.failed Registra data.failed.reason, avvisa, eventualmente riprova con una correzione.
email.suppressed Un destinatario era nella tua lista di soppressione; mostralo nella tua interfaccia di amministrazione.

Iscriviti solo agli eventi che gestisci. Meno eventi significano meno traffico e meno errori.

  • Servilo su HTTPS con un certificato valido.
  • Non registrare nei log i secret né i payload completi che contengono dati personali.
  • Usa un percorso dedicato senza altri comportamenti e restituisci un corpo generico.
  • Conserva il signing_secret in un gestore di secret, non nel controllo di versione.

Tieni d’occhio il log delle consegne nella dashboard o imposta avvisi sugli errori ripetuti: se il tuo endpoint resta fuori servizio per più di circa 27 ore, tutti i nuovi tentativi vengono esauriti e dovrai rinviare manualmente.