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:
| Evento | Significato |
|---|---|
sent | Email accettata dal server di posta destinatario |
delivered | Il server di posta ha confermato la consegna |
opened | Il destinatario ha aperto l'email (tracciamento pixel) |
clicked | Il destinatario ha cliccato un link |
bounced | Il server di posta ha rifiutato la consegna |
complained | Il destinatario ha segnalato il messaggio come spam |
unsubscribed | Il 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_abc123La 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 richiesta | 10 secondi |
| Successo | qualsiasi risposta 2xx |
| Tentativi | fino a 5 |
| Backoff | 5s, 30s, 5min, 30min, 2h |
| Disattivazione automatica | dopo 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
iddell'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
- Inviare email? Vai a Invia Email
- Tracciare lo stato? Vedi Status Email
- Ricevere webhook su Firebase, Vercel o Cloudflare? Vedi Deployment
- Usare i webhook nei flow? Vedi Flow
Modifica questa pagina su GitHub
Ultimo aggiornamento