Guida ai webhook WhatsApp: eventi, sicurezza e nuovi tentativi
Come funzionano i webhook WhatsApp: eventi di messaggi e stati, gestore affidabile, firma di Meta, nuovi tentativi, idempotenza e recupero degli eventi persi.
Di OmniChannels.ai Editorial Team · Revisione di BroadNet Messaging Solutions Team
Integrazione
Risposta breve
Un webhook WhatsApp è un endpoint HTTPS sul vostro server che riceve eventi: stati di consegna dei messaggi che inviate e messaggi che i clienti vi mandano. Con OmniChannels.ai gli stati arrivano come SUBMITTED, SENT, DELIVERED, READ, FAILED o REJECTED. Salvate il corpo grezzo, rispondete subito con 2xx, deduplicate per ID del messaggio ed elaborate in modo asincrono. Meta firma i propri webhook; la nostra documentazione non definisce alcun header di firma, quindi proteggete l'endpoint a livello di trasporto e di applicazione.
In questa pagina
- Che cosa sono i webhook WhatsApp e perché usarli?
- Quali eventi e stati riceverò?
- Come configuro l'endpoint?
- Com'è fatto il payload?
- Come scrivo un gestore affidabile?
- Come proteggo un webhook WhatsApp?
- Cosa succede quando la consegna fallisce?
- Come recupero gli eventi mancanti?
- Esempio pratico: la pipeline di notifica di un rivenditore
- Quali sono gli errori comuni?
- Come vi aiuta OmniChannels.ai
Punti chiave
- I webhook inviano stati e messaggi in arrivo al vostro endpoint HTTPS, così non dovete fare polling; gli stati WhatsApp sono normalizzati in SUBMITTED, SENT, DELIVERED, READ, FAILED e REJECTED.
- Un gestore affidabile compie tre azioni in ordine: salva l'evento grezzo, restituisce 2xx, poi elabora in modo asincrono e idempotente.
- Gli stati possono arrivare fuori ordine o due volte, quindi assegnate loro un rango e non lasciate mai che un SENT in ritardo sovrascriva un DELIVERED già memorizzato.
- Meta firma i webhook inviati alle app con un header X-Hub-Signature-256, ma la specifica dell'API di OmniChannels.ai non definisce alcuna firma dei webhook, quindi usate HTTPS, un percorso non indovinabile e la convalida del corpo.
- Se alcuni eventi sono andati persi, leggete lo stato WhatsApp per batch dall'endpoint bulk-insights invece di reinviare i messaggi.
Questa guida è per gli ingegneri che devono ricevere in modo affidabile gli eventi WhatsApp: stati di consegna dei messaggi che inviano e messaggi in arrivo dai clienti. Spiega come funzionano i webhook, cosa costruire nel gestore, in cosa la sicurezza differisce tra i webhook di Meta e i nostri e cosa fare quando gli eventi si perdono.
Che cosa sono i webhook WhatsApp e perché usarli?
I webhook WhatsApp sono callback HTTP. Quando un messaggio cambia stato o un cliente vi scrive, la piattaforma invia una POST con corpo JSON al vostro endpoint. Non dovete fare polling e vedete gli eventi appena accadono.
Contano due famiglie di eventi:
- Eventi di stato per i messaggi che inviate: in coda, inviato, consegnato, letto, fallito.
- Messaggi in arrivo dai clienti, che aprono o prolungano la finestra di assistenza clienti di 24 ore. Vedi la nostra guida alla finestra.
Una chiamata di invio vi dice solo che i messaggi sono stati messi in coda. Il webhook è il luogo in cui scoprite cosa è accaduto a ogni destinatario.
Quali eventi e stati riceverò?
Su OmniChannels.ai ogni canale riporta gli stessi stati normalizzati, quindi un solo gestore può servire WhatsApp, SMS e gli altri.
| Stato | Significato | Finale? |
|---|---|---|
SUBMITTED |
Accettato dalla piattaforma e messo in coda | No |
SENT |
Consegnato al canale | No |
DELIVERED |
Confermato sul dispositivo del destinatario | Di solito; può seguire READ |
READ |
Aperto dal destinatario, dove il canale riporta le letture | Sì |
FAILED |
Non consegnato; l'evento riporta il motivo dove disponibile | Sì |
REJECTED |
Rifiutato, ad esempio per contenuto bloccato o mittente non registrato | Sì |
Trattate gli stati come una progressione che può arrivare fuori ordine e aspettatevi nuovi valori nel tempo. Non andate in errore davanti a uno stato che non riconoscete. Vedi stati di consegna dei messaggi spiegati.
Come configuro l'endpoint?
Esponete un endpoint HTTPS, comunicate l'URL al provider, poi testate con il vostro numero.
- Create un endpoint che accetti
POSTcon un corpo JSON, ad esempiohttps://api.example.com/webhooks/omnichannels. - Inviate l'URL al nostro team o all'amministratore del vostro account perché lo configuri sul vostro account. I reseller possono avere un webhook separato per sotto-account.
- Inviate un messaggio di prova al vostro numero e verificate che gli eventi arrivino.
Durante lo sviluppo, un tunnel come ngrok dà al vostro server locale un URL HTTPS pubblico. Se collegate direttamente anche un'app a Meta, la verifica dell'endpoint di Meta è un passaggio separato: una richiesta GET con un token di verifica e un valore hub.challenge, a cui rispondete 200 con il challenge, come descritto nella documentazione di Meta sull'endpoint webhook.
Com'è fatto il payload?
Varia per canale. La specifica dell'API non definisce un unico schema di webhook, quindi registrate prima il corpo grezzo e mappate i campi che vi servono da eventi reali sul vostro account. L'esempio mostra il tipo di informazioni che porta un evento di consegna ed è solo illustrativo.
{
"messageId": "2603121407537573731",
"channel": "SMS",
"destination": "447700900123",
"status": "DELIVERED",
"timestamp": "2026-10-10T09:15:42Z",
"reason": null
}
Non scrivete codice basato su questi nomi di campo senza verificare un evento reale. Chiedete al vostro tecnico di attivazione payload di esempio per canale e conservateli come fixture di test. Per la documentazione più ampia, vedi il riferimento sui webhook.
Come scrivo un gestore affidabile?
Fate tre cose in ordine: salvate l'evento grezzo, confermate con un 2xx, poi elaborate in modo asincrono. Il gestore qui sotto segue lo schema della nostra documentazione.
import express from "express";
const app = express();
// Catturate il corpo grezzo per memorizzarlo esattamente come ricevuto.
app.post(
"/webhooks/omnichannels",
express.json({ verify: (req, _res, buf) => { req.rawBody = buf.toString("utf8"); } }),
async (req, res) => {
try {
await db.webhookEvents.insert({ receivedAt: new Date(), body: req.rawBody });
} catch (err) {
return res.sendStatus(500); // salvataggio fallito: lasciate che l'evento venga ritentato
}
res.sendStatus(200); // confermate subito
queue.publish("status-events", req.body); // il lavoro vero si svolge altrove
},
);
// Worker: elaborazione idempotente
async function processEvent(event) {
const id = event.messageId ?? event.message_id ?? event.id; // mappate per canale
const status = event.status;
const rank = { SUBMITTED: 1, SENT: 2, DELIVERED: 3, READ: 4, FAILED: 4, REJECTED: 4 };
const current = await db.messages.findOne({ providerId: id });
if (!current) return; // messaggio sconosciuto: registratelo e indagate
if ((rank[status] ?? 0) <= (rank[current.status] ?? 0)) return; // duplicato o evento superato
await db.messages.update({ providerId: id }, { status, updatedAt: new Date() });
}
from datetime import datetime, timezone
from flask import Flask, request
app = Flask(__name__)
RANK = {"SUBMITTED": 1, "SENT": 2, "DELIVERED": 3, "READ": 4, "FAILED": 4, "REJECTED": 4}
@app.post("/webhooks/omnichannels")
def omnichannels_webhook():
raw = request.get_data(as_text=True)
try:
db.webhook_events.insert({"received_at": datetime.now(timezone.utc), "body": raw})
except Exception:
return "", 500 # salvataggio fallito: lasciate che l'evento venga ritentato
queue.publish("status-events", raw) # elaborate in modo asincrono
return "", 200 # confermate subito
Gli oggetti db e queue sono il vostro storage e la vostra coda di job. La mappa rank è ciò che rende idempotente l'elaborazione: un evento duplicato o superato non è un avanzamento, quindi viene ignorato.
Regole per un gestore affidabile
- Rispondete entro pochi secondi. Non svolgete lavoro pesante prima di rispondere.
- Restituite
2xxsolo dopo aver salvato l'evento. Se il salvataggio fallisce, restituite5xx. - Deduplicate per ID del messaggio. Lo stesso stato può arrivare più di una volta.
- Non reinviate mai un messaggio dal gestore. Decidete i nuovi tentativi in un job separato, dopo aver controllato lo stato.
- Conservate il corpo grezzo per la risoluzione dei problemi e per rielaborare gli eventi dopo una correzione.
Come proteggo un webhook WhatsApp?
Dipende da chi invia al vostro endpoint. Meta firma i webhook che invia alle app registrate presso Meta. La specifica dell'API di OmniChannels.ai non definisce alcun header di firma dei webhook, quindi non aspettatevene uno.
| Meta verso la vostra app | OmniChannels.ai verso il vostro endpoint | |
|---|---|---|
| Firma | Header X-Hub-Signature-256, secondo la documentazione di Meta |
Nessuna definita nella specifica dell'API |
| Verifica | HMAC-SHA256 del payload grezzo con il segreto dell'app, confrontato con l'header | Non applicabile |
| I vostri controlli | Verificare la firma a ogni POST |
HTTPS con certificato valido, un percorso non indovinabile, convalida rigorosa del corpo |
Per lo schema di Meta, la documentazione di Meta indica di generare un hash HMAC-SHA256 dal payload JSON usando il segreto dell'app e di confrontarlo con il valore dopo sha256= nell'header X-Hub-Signature-256. L'HMAC stesso è definito nell'RFC 2104. Calcolatelo sui byte grezzi, non su un oggetto ri-serializzato, e confrontate in tempo costante.
Per il nostro endpoint:
- Usate solo HTTPS, con un certificato valido.
- Usate un percorso lungo e non indovinabile e cambiatelo se trapela.
- Convalidate la forma del corpo e rifiutate tutto ciò che è inatteso.
- Trattate gli eventi come notifiche. Prima di un'azione irreversibile, come un rimborso o un blocco antifrode, confermate lo stato con una chiamata di polling.
Cosa succede quando la consegna fallisce?
I nuovi tentativi dipendono da chi invia. La documentazione di Meta dice che riprova una consegna fallita con frequenza decrescente fino a 7 giorni, il che può produrre notifiche duplicate. È un motivo per essere idempotenti anche se vedete raramente duplicati. Per gli eventi della nostra piattaforma, confermate il comportamento dei nuovi tentativi con il vostro tecnico di attivazione invece di dare per scontato che coincida con quello di Meta.
In ogni caso, costruite sia per la perdita sia per la duplicazione: il vostro endpoint può essere fuori servizio durante un deploy e una regola del firewall può scartare le richieste in silenzio.
Come recupero gli eventi mancanti?
Interrogate il batch, non reinviate il messaggio.
| Esigenza | Chiamata | Note |
|---|---|---|
| Leggere lo stato WhatsApp per destinatario | GET /whatsapp/message/bulk-insights |
Filtra un batch per status o destination; paginato con page e size |
| Reinviare i rapporti di consegna SMS | POST /sms/resendDlr |
Filtra per startDate, endDate, senderId e messageStatus |
curl "https://api.broadnet.me/whatsapp/message/bulk-insights?batch_Id=2609091405000000001&page=0&size=100" \
-H "Authorization: Bearer $BROADNET_TOKEN"
batch_Id è l'ID restituito dalla chiamata di invio e page parte da zero. Eseguite una riconciliazione notturna che legge i batch del giorno prima e colma le lacune.
Checklist di risoluzione dei problemi
- L'URL è configurato sull'account o sul sotto-account giusto?
- L'endpoint è raggiungibile in HTTPS con un certificato valido?
- Risponde
2xxrapidamente o va in timeout? - Una regola di firewall o WAF blocca le richieste?
- Registrate il corpo grezzo prima di analizzarlo, così un errore del parser non può nascondere l'evento?
Esempio pratico: la pipeline di notifica di un rivenditore
«Souq Rafiq» (nome di fantasia), un rivenditore degli Emirati, invia aggiornamenti sugli ordini via WhatsApp e vuole uno stato accurato nel proprio strumento di gestione degli ordini.
- Gli ordini vengono inviati con
sendbulke ilbatchIdviene memorizzato sull'ordine. Vedi inviare un messaggio WhatsApp via API. - L'endpoint webhook scrive ogni evento in una tabella, poi restituisce
200. - Un worker assegna il rango agli stati e aggiorna lo stato del messaggio dell'ordine.
- Gli eventi
FAILEDcreano un'attività per l'assistenza con il motivo e si valuta un fallback SMS secondo il fallback tra canali. - I messaggi in arrivo dai clienti vengono instradati alla casella condivisa (shared inbox), così gli operatori possono rispondere dentro la finestra.
- Un job notturno chiama
bulk-insightsper i batch del giorno prima e corregge ciò che è stato perso.
Quali sono gli errori comuni?
- Lavoro pesante prima di rispondere, che causa timeout e consegne ripetute.
- Confermare prima di salvare, il che fa perdere eventi quando il salvataggio fallisce.
- Fidarsi dell'ordine. Un
SENTin ritardo che sovrascriveDELIVERED. - Scrivere codice basato sul payload illustrativo invece che su eventi reali.
- Ri-serializzare il JSON prima di verificare una firma, il che cambia i byte.
- Reinviare dal gestore, il che può creare cicli.
- Limiti: questa guida descrive il comportamento documentato da noi. Politica dei nuovi tentativi e campi del payload per il vostro account vanno confermati durante l'attivazione.
Come vi aiuta OmniChannels.ai
OmniChannels.ai invia al vostro webhook stati di consegna e messaggi in arrivo per WhatsApp, SMS, RCS e altri canali in un unico formato normalizzato, con webhook separati per sotto-account per i reseller. BroadNet è un Meta Business Solution Provider ufficiale, quindi i requisiti webhook di Meta sono gestiti per voi e voi lavorate con la nostra API. Leggete il riferimento sui webhook e la documentazione dell'API WhatsApp, oppure scoprite come gli eventi compaiono nella casella condivisa.
Domande frequenti
Che cos'è un webhook WhatsApp?
Un webhook WhatsApp è un URL sul vostro server che la piattaforma richiama con una POST HTTP ogni volta che accade qualcosa, come un messaggio consegnato, letto o fallito, o un cliente che vi scrive. Sostituisce il polling. Esponete un endpoint HTTPS, lo comunicate al provider ed elaborate gli eventi JSON che riceve.
Come si verifica la firma di un webhook WhatsApp?
Per un webhook che Meta invia direttamente alla vostra app, la documentazione di Meta indica di calcolare un HMAC-SHA256 del payload grezzo con il segreto dell'app e confrontarlo con l'header X-Hub-Signature-256. Per il webhook di OmniChannels.ai la specifica dell'API non definisce alcun header di firma, quindi affidatevi a HTTPS, a un percorso non indovinabile e alla convalida del corpo.
Cosa succede se il mio endpoint webhook è fuori servizio?
La documentazione di Meta dice che riprova le consegne fallite con frequenza decrescente fino a 7 giorni, il che può produrre duplicati. Per gli eventi della nostra piattaforma, confermate il comportamento dei nuovi tentativi con il vostro tecnico di attivazione e usate l'endpoint bulk-insights per leggere lo stato WhatsApp per destinatario di un batch. Per gli SMS, l'endpoint resendDlr reinvia i rapporti.
Come gestisco gli eventi webhook duplicati?
Rendete idempotente l'elaborazione. Cercate il messaggio dal suo ID, confrontate il rango dello stato in arrivo con quello memorizzato e ignorate gli eventi che non sono un avanzamento. Applicare due volte lo stesso evento deve avere lo stesso effetto di una sola volta. Conservate il corpo grezzo di ogni evento così potete rielaborarlo dopo aver corretto un bug.
Con quale rapidità deve rispondere il mio endpoint?
Entro pochi secondi. Salvate l'evento grezzo, restituite un 2xx e svolgete il lavoro vero in una coda o in un worker. Non chiamate altri servizi, non inviate messaggi e non eseguite query pesanti prima di rispondere. Se il salvataggio fallisce, restituite un 5xx così il mittente può riprovare, invece di confermare un evento che avete perso.
Posso usare un webhook per inviare automaticamente una risposta?
Sì, ma non dall'interno del gestore. Confermate l'evento, poi decidete la risposta in un job separato. Dentro la finestra di assistenza clienti di 24 ore potete inviare un messaggio libero; fuori serve un template approvato. Non reinviate mai un messaggio dal gestore del webhook stesso, per evitare cicli e duplicati.
Fonti
Continuate a leggere
Altre guideIntegrazione
Inviare un messaggio WhatsApp via API: cURL, Node, Python, PHP
Come inviare un messaggio WhatsApp con una API: esempi in cURL, Node.js, Python e PHP per template e messaggi di sessione, con stati ed errori.
10 min di lettura
Integrazione
Integrazione WhatsApp CRM: 3 modi per collegare e sincronizzare
Integrazione WhatsApp CRM: connettori, middleware o API e webhook, con flusso dei dati, mappatura dei campi, sincronizzazione del consenso e checklist.
10 min di lettura
WhatsApp
Messaggi gratuiti WhatsApp Business API nel 2026: cosa non costa
Messaggi gratuiti della WhatsApp Business API nel 2026: 1.000 messaggi di servizio per numero, finestra di punto di ingresso gratuito di 72 ore.
9 min di lettura
