Webhook: Setup, Eventi e Verifica Firma

Ricevi gli eventi email in tempo reale tramite webhook

I webhook sono callback HTTP che avvisano la tua applicazione quando accade qualcosa (email consegnata, aperta, respinta, e così via). Invece di interrogare l'API, è Tratto a inviarti gli eventi.

Registrare un Webhook

cURL

curl -X POST https://api.tratto.email/v1/webhooks \
  -H "Authorization: Bearer tratto_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url":"https://yourapi.com/webhooks/tratto",
    "events":["sent","delivered","opened","clicked","bounced","complained","unsubscribed"]
  }'

Risposta: 201 Created:

{
  "data": {
    "id": "wh_abc123",
    "secret": "whsec_5f3a9c1e8b2d..."
  }
}

Conserva il secret. Viene restituito solo qui e alla rotazione: non esiste un endpoint che te lo ridia. L'elenco dei webhook restituisce un secretPrefix troncato per identificarli, non il valore completo.

Eventi Webhook

Tratto invia richieste POST al tuo URL quando si verificano questi eventi:

EventoSignificato
sentEmail accettata dal server di posta destinatario
deliveredIl server di posta ha confermato la consegna
openedIl destinatario ha aperto l'email (tracciamento pixel)
clickedIl destinatario ha cliccato un link
bouncedIl server di posta ha rifiutato la consegna
complainedIl destinatario ha segnalato il messaggio come spam
unsubscribedIl destinatario ha cliccato per disiscriversi

Sottoscrivere un evento fuori da questa lista viene rifiutato in fase di registrazione.

Payload del Webhook

{
  "id": "evt_abc123",
  "type": "delivered",
  "emailId": "email_xyz789",
  "recipient": "[email protected]",
  "occurredAt": "2025-06-30T12:00:10Z",
  "data": {}
}

data contiene i dettagli specifici dell'evento ed è un oggetto vuoto quando non ce ne sono. Usa id per deduplicare: i retry consegnano lo stesso evento più di una volta.

Verifica Firma Webhook

Ogni consegna porta un header X-Tratto-Signature. Non è un hash nudo: contiene un timestamp e la firma.

X-Tratto-Signature: t=1784977714054,v1=0b37dd97144dcdf176572a1b...
X-Tratto-Webhook-Id: wh_abc123

La stringa firmata è il timestamp e il corpo grezzo uniti da un punto:

{timestamp}.{rawBody}

La verifica ha quindi quattro passi: estrarre t e v1, rifiutare i timestamp fuori dalla finestra di tolleranza, ricalcolare l'HMAC su {t}.{rawBody} e confrontare con v1 a tempo costante.

Verifica della Firma dei Webhook contiene le implementazioni funzionanti per Node, runtime edge, Python e PHP.

Firmare il solo corpo, o confrontare direttamente l'header con un digest, non corrisponderà mai. Sono i due errori che vediamo più spesso.

Prevenire i Replay Attack

Usa il campo t dell'header della firma, non occurredAt del payload. t è coperto dalla firma e registra quando la consegna è stata firmata; occurredAt registra quando è avvenuto l'evento, e i due valori divergono nei retry.

Il controllo di tolleranza è già incluso nelle implementazioni in Verifica della Firma dei Webhook.

Consegne e Retry

Timeout della richiesta10 secondi
Successoqualsiasi risposta 2xx
Tentativifino a 5
Backoff5s, 30s, 5min, 30min, 2h
Disattivazione automaticadopo 10 fallimenti consecutivi

Due conseguenze da tenere presenti:

  • Conferma prima di elaborare. Tutto ciò che supera i 10 secondi conta come fallimento e verrà ritentato.
  • Gestisci i duplicati. Deduplica sul campo id dell'evento.

Un webhook disattivato per fallimenti ripetuti ha status: "disabled". Ruotarne il secret azzera il contatore e lo riabilita.

Ruotare il Secret

curl -X POST https://api.tratto.email/v1/webhooks/wh_abc123/rotate-secret \
  -H "Authorization: Bearer tratto_live_..."

Risposta:

{
  "data": {
    "secret": "whsec_new..."
  }
}

La rotazione ha effetto immediato: non esiste una finestra di sovrapposizione e il secret precedente smette di funzionare appena viene emesso quello nuovo. Per ruotare senza perdere consegne, pubblica prima un endpoint che accetti entrambi i secret, poi ruota, poi rimuovi il vecchio. Vedi Rotazione del secret.

Evento di Test

curl -X POST https://api.tratto.email/v1/webhooks/wh_abc123/test \
  -H "Authorization: Bearer tratto_live_..."

Risposta:

{
  "data": {
    "queued": true
  }
}

Il test viene messo in coda, non consegnato in modo sincrono: un 200 qui significa che è stato accettato per l'invio, non che il tuo endpoint ha risposto. Controlla le consegne per l'esito.

Il test invia un evento delivered il cui data è { "isTest": true }, così il tuo handler può distinguerlo dal traffico reale.

Elenco dei Webhook

curl https://api.tratto.email/v1/webhooks \
  -H "Authorization: Bearer tratto_live_..."

Risposta:

{
  "data": [
    {
      "id": "wh_abc123",
      "url": "https://yourapi.com/webhooks/tratto",
      "events": ["delivered", "bounced"],
      "status": "active",
      "secretPrefix": "whsec_5f3a9c…",
      "failureCount": 0,
      "createdAt": "2025-06-30T12:00:00Z"
    }
  ]
}

failureCount conta i fallimenti consecutivi. Tienilo d'occhio: a 10 il webhook viene disattivato.

Consegne del Webhook

curl "https://api.tratto.email/v1/webhooks/wh_abc123/deliveries?limit=50" \
  -H "Authorization: Bearer tratto_live_..."

Paginazione a cursore con after e limit (default 50, massimo 100).

Risposta:

{
  "data": [
    {
      "id": "del_001",
      "webhookId": "wh_abc123",
      "eventType": "delivered",
      "status": "success",
      "httpStatus": 200,
      "responseBody": "{\"ok\":true}",
      "retryCount": 0,
      "attemptedAt": "2025-06-30T12:00:10Z"
    },
    {
      "id": "del_002",
      "webhookId": "wh_abc123",
      "eventType": "bounced",
      "status": "scheduled",
      "httpStatus": 500,
      "responseBody": "Internal Server Error",
      "retryCount": 2,
      "attemptedAt": "2025-06-30T12:05:00Z"
    }
  ],
  "pagination": { "hasMore": false, "nextCursor": null }
}

status vale success, failed o scheduled: scheduled significa che un retry è ancora in attesa. responseBody è troncato ai primi 1000 caratteri della tua risposta, ed è il modo più rapido per capire perché una consegna è stata rifiutata.

Eliminare un Webhook

curl -X DELETE https://api.tratto.email/v1/webhooks/wh_abc123 \
  -H "Authorization: Bearer tratto_live_..."

Restituisce 204 No Content. L'eliminazione è immediata e non reversibile; le consegne in coda per quel webhook si interrompono.


Prossimi Passi


Modifica questa pagina su GitHub

Ultimo aggiornamento