Vai al contenuto
Torna alla documentazione per sviluppatori

Guida ai webhook

Come ricevere e verificare gli eventi che Mailronix invia al tuo indirizzo: consegna, firma, contenuto, ritentativi e rotazione del segreto.

Come arrivano le consegne

Ogni evento è una richiesta POST con corpo JSON all'indirizzo HTTPS che hai registrato (porta 443 o 8443). Rispondi entro 10 secondi: qualsiasi codice 2xx conferma la consegna. Tutto il resto è un errore e fa scattare un nuovo tentativo, compresi i redirect, che non vengono seguiti. Gli indirizzi non raggiungibili da Internet pubblico vengono rifiutati.

Mailronix-Signature
La firma della richiesta. Vedi «Verificare la firma».
Mailronix-Event-Id
L'identificativo dell'evento, uguale al campo id del corpo. È lo stesso a ogni tentativo.
Mailronix-Delivery-Id
L'identificativo della consegna. Citalo quando scrivi all'assistenza.
Mailronix-Event-Type
Il tipo di evento, uguale al campo type del corpo.

Verificare la firma

Verifica sempre la firma prima di fidarti del contenuto: chiunque conosca il tuo indirizzo può inviargli una richiesta. La firma è l'HMAC-SHA256, in esadecimale, della stringa «t.corpo», con il corpo esattamente come lo hai ricevuto.

Mailronix-Signature: t=<unix>,v1=<hmac-sha256>
  v1 = hex( HMAC-SHA256( chiave, "<t>." + corpo ) )
  1. Chiave: il segreto che la console mostra una sola volta ha la forma «whsec_…». La chiave HMAC sono i byte che seguono il prefisso, da decodificare da base64url senza padding. Il testo del segreto non è la chiave.
  2. Corpo: calcola l'HMAC sui byte grezzi ricevuti. Se il tuo framework analizza il JSON prima di te, recupera il corpo grezzo (in Express, express.raw): riscrivere il JSON cambia i byte e la firma non torna.
  3. Freschezza: rifiuta le richieste in cui t dista più di cinque minuti dall'ora corrente. t è l'istante del singolo tentativo, quindi anche un ritentativo dopo ore passa il controllo.
  4. Più firme: nelle 24 ore dopo una rotazione l'intestazione contiene due valori v1, uno per il segreto nuovo e uno per il precedente. Accetta la richiesta se uno qualsiasi corrisponde a uno dei segreti che conosci.
  5. Confronto: usa un confronto a tempo costante, come negli esempi.

Esempi di verifica

import { createHmac, timingSafeEqual } from 'node:crypto'

// `segreto` è quello mostrato dalla console, «whsec_…». La chiave HMAC sono i
// suoi byte: si toglie il prefisso e si decodifica da base64url.
const chiave = (segreto) => Buffer.from(segreto.replace(/^whsec_/, ''), 'base64url')

// `corpo` è il corpo ESATTO ricevuto (Buffer), non il JSON riscritto.
export function verificaFirma(intestazione, corpo, segreti, toleranza = 300) {
  const parti = intestazione.split(',').map((p) => p.trim().split('='))
  const t = parti.find(([k]) => k === 't')?.[1]
  const firme = parti.filter(([k]) => k === 'v1').map(([, v]) => v)
  if (!t || firme.length === 0) return false
  if (Math.abs(Date.now() / 1000 - Number(t)) > toleranza) return false

  let valida = false
  for (const segreto of segreti) {
    const atteso = createHmac('sha256', chiave(segreto)).update(`${t}.`).update(corpo).digest()
    for (const firma of firme) {
      const ricevuta = Buffer.from(firma, 'hex')
      if (ricevuta.length === atteso.length && timingSafeEqual(ricevuta, atteso)) valida = true
    }
  }
  return valida
}

Esempi eseguiti contro la firma reale di Mailronix. Se la verifica fallisce rispondi 401; dopo aver accettato l'evento rispondi 200 subito e lavora in seguito.

Eventi e contenuto

Ogni corpo ha la stessa busta; il contenuto di data cambia secondo il tipo.

{
  "id": "evt_01j9x4k2m7q8r5t3v6w1y0z2ab",
  "type": "email.bounced",
  "api_version": "2026-10-22",
  "created_at": "2026-10-22T14:03:11Z",
  "brand_id": "6f1c7d0e-5a3b-4e8f-9c21-0b7d4a1e3f52",
  "data": {
    "email_log_id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e",
    "recipient": "persona@example.com",
    "category": "transactional",
    "bounce_type": "permanent"
  }
}
  • id: l'identificativo dell'evento. Usalo per riconoscere i duplicati.
  • type: uno dei tipi elencati sotto, oppure webhook.test per la consegna di prova.
  • api_version: la versione del formato.
  • created_at: quando è avvenuto l'evento, in UTC.
  • brand_id: il brand a cui appartiene l'evento (null solo in webhook.test).
  • Gli eventi email.* portano in data email_log_id, recipient e category. email.bounced aggiunge bounce_type (permanent, transient o undetermined): un rimbalzo annunciato come transient e poi riclassificato permanent produce un secondo email.bounced.
  • Gli eventi contact.* portano in data contact_id ed email. contact_id può essere null in contact.unsubscribed, per esempio quando la disiscrizione arriva da una revoca: gestisci il caso.

Tipi di evento

email.sent
webhookGuide.eventTypes.email.sent
email.delivered
webhookGuide.eventTypes.email.delivered
email.bounced
webhookGuide.eventTypes.email.bounced
email.complained
webhookGuide.eventTypes.email.complained
email.failed
webhookGuide.eventTypes.email.failed
email.suppressed
webhookGuide.eventTypes.email.suppressed
contact.confirmed
webhookGuide.eventTypes.contact.confirmed
contact.unsubscribed
webhookGuide.eventTypes.contact.unsubscribed

Le aperture non sono disponibili: Mailronix non le rileva, per scelta di privacy. Gli eventi email.clicked arrivano solo per i marchi che hanno acceso il tracciamento dei click e solo per i destinatari che hanno acconsentito; descrivono un click rilevato (scanner e anteprime possono generarne) e portano l'host della destinazione, non l'URL. La revoca blocca nuove rilevazioni e non rende retroattivamente illecito l'evento già raccolto: eventi anteriori già accodati possono arrivare dopo, entro 30 giorni di conservazione della coda. La cancellazione del contatto elimina gli eventi e le consegne accodate secondo la procedura prevista. Il cliente destinatario del webhook resta responsabile delle proprie copie e della gestione dei diritti su di esse.

Ritentativi, duplicati e ordine

  • Una consegna non riuscita viene ritentata fino a dieci volte in quasi quattro giorni: subito, poi dopo 10 secondi, 1 minuto, 5 minuti, 30 minuti, 2 ore, 6 ore, 12 ore, 24 ore e 48 ore.
  • Ogni evento arriva almeno una volta, non esattamente una: può arrivare due volte, per esempio se rispondi dopo il limite di 10 secondi. Conserva gli id già elaborati e ignora i duplicati.
  • L'ordine di arrivo non è garantito: un email.delivered può arrivare dopo un email.bounced. Per ordinare gli eventi usa created_at, non l'ora in cui li ricevi.
  • Se un evento esaurisce i tentativi e negli ultimi tre giorni nessuna consegna a quell'endpoint è riuscita, l'endpoint viene disattivato e il proprietario riceve un'email. Dalla pagina Webhook puoi riattivarlo (serve la password) e rinviare i singoli eventi. Le consegne si conservano 30 giorni.

Ruotare il segreto

Dalla pagina Webhook puoi ruotare il segreto di un endpoint (serve la password); il segreto nuovo compare una sola volta. Per 24 ore ogni consegna porta due firme, quella del segreto nuovo e quella del precedente: tieni accettati entrambi i segreti in quel periodo e aggiorna il ricevitore senza perdere consegne. Se il vecchio segreto è trapelato, scegli di revocarlo subito: da quel momento conta solo quello nuovo.

Provare il ricevitore

Alla creazione e con l'azione «Invia prova», Mailronix invia un evento webhook.test con la stessa busta e la stessa firma degli eventi veri, senza dati di destinatari. Se la prova fallisce, l'endpoint viene salvato ma resta disattivato.

Limiti

Gli endpoint attivi per account sono 1 con il piano Free, 5 con Starter e 10 con Growth. Gli endpoint si configurano solo dalla console, con la sessione e mai con una chiave API.

Crea un account gratuito