Comportamento della consegna
Il payload standard, il limite di 5 secondi, il motivo per cui non sono previsti nuovi tentativi e il significato di ogni stato di consegna.
La consegna dei webhook è volutamente semplice, e questa semplicità ha conseguenze per il tuo ricevitore: un solo tentativo HTTP, cinque secondi, nessun nuovo tentativo. Leggi questa pagina prima di decidere quante operazioni eseguire in modo sincrono nel tuo gestore.
Il payload standard
Ogni evento tranne listing.submission arriva con la stessa struttura al livello principale, con i campi specifici dell'evento annidati in data.
{ "event": "connection.location_connected", "timestamp": "2026-08-25T14:32:10Z", "account_id": 11073, "location_id": "279381", "data": { "platform": "google", "connected_account_id": "ba03bc4b-9f8c-4d3b-8e93-9628034c63cc" }}I campi facoltativi all'interno di data vengono omessi quando sono vuoti, anziché essere inviati come null. Scrivi il codice in modo da gestire i casi imprevisti: tratta allo stesso modo una chiave assente e un valore null esplicito, e non dare mai per scontato che una chiave documentata come facoltativa sia presente.
Due eccezioni
Il limite di 5 secondi
Ogni consegna consiste in un singolo POST con un timeout di connessione di 5 secondi e un timeout di lettura di 5 secondi. Se il tuo endpoint non risponde in tempo, il tentativo viene abbandonato e registrato come timeout.
Questo limite di tempo si applica all'intera esecuzione del tuo gestore. L'unica soluzione sicura è:
- Verifica la firma.
- Salva il payload in un sistema di archiviazione persistente: una coda, una tabella, un registro.
- Restituisci
200.
Tutte le altre operazioni (arricchimento dei dati, distribuzione a più destinatari, chiamate alla REST API, qualsiasi operazione che coinvolga terze parti) devono essere eseguite dopo il prelievo dalla coda.
Non vengono effettuati nuovi tentativi
Ogni consegna viene tentata esattamente una volta. Non sono previsti intervalli di attesa progressivi, code per nuovi tentativi o code per le consegne non riuscite. Se il tuo endpoint non è disponibile per due minuti, gli eventi generati in quei due minuti vanno persi. Non arriveranno in seguito.
Due conseguenze da chiarire esplicitamente:
- I reindirizzamenti non vengono seguiti. I reindirizzamenti sono completamente disabilitati, quindi una risposta
301o302del tuo endpoint viene registrata come consegna non riuscita, senza seguire il reindirizzamento a un secondo URL. Imposta come URL dei webhook l'URL finale. Fai attenzione ai reindirizzamenti dal dominio senza prefisso awwwe a quelli che aggiungono una barra finale, che molti server web applicano per impostazione predefinita. - Solo
2xxviene considerato una consegna riuscita.3xx,4xxe5xxvengono tutti registrati come errori di consegna.
Duplicati e ordine
- Puoi ricevere lo stesso evento due volte e lo stesso id per due modifiche diverse. Gli identificatori all'interno di
data(un id di interazione, un id di elemento di un post, un id di account collegato) identificano la risorsa, non la modifica.interaction.reviewviene emesso di nuovo con lo stesso id di interazione ogni volta che la recensione cambia e nessun payload contiene una versione o un campo con la data dell'ultimo aggiornamento, quindi un gestore che scarta definitivamente gli eventi in base a id +eventelimina modifiche effettive senza segnalarlo. Rileva invece i duplicati esatti: calcola un hash dei byte del corpo originale e ignora le ripetizioni dello stesso hash entro una finestra temporale breve e limitata (minuti, non per sempre). Un corpo diverso per lo stesso id è una nuova modifica, non un duplicato. Poi rileggi la risorsa tramite l'API REST e considera quella lettura come fonte autorevole; usa l'id della risorsa come chiave per la scrittura, invece di saltarla. - L'ordine non è garantito e
timestampnon risolve il problema. Gli eventi provengono da diversi flussi indipendenti e vengono consegnati man mano che arrivano, quindi unlocal_post.publishedpuò arrivare prima dellocal_post.createdche ti aspettavi per primo. Non ordinare due modifiche alla stessa risorsa in base atimestamp: viene assegnato quando viene preparata la consegna, non quando è avvenuta la modifica, e il payload non contiene alcuna versione o numero di sequenza. Quando l'ordine è rilevante, rileggi la risorsa e usa ciò che restituisce l'API. - A
profile.updatedviene applicato un debounce che limita le consegne a una per sede ogni 60 secondi, sul fronte iniziale. Si tratta di una soppressione effettiva, non di un ritardo: la prima modifica apre la finestra e viene consegnata, ogni modifica all'interno della finestra viene scartata e non arriva mai, echanged_fieldsdescrive solo la modifica che ha aperto la finestra. L'evento ti arriva quindi all'inizio della finestra, perciò una rilettura attivata dal suo arrivo può vedere soltanto quella prima modifica. Pianifica una seconda rilettura dopo la chiusura della finestra, almeno 60 secondi dopo l'evento, ed esegui anche una riconciliazione periodica delle sedi, perché la notifica stessa può andare persa: un solo tentativo, nessun nuovo tentativo. Il debounce non viene applicato a nient'altro.
Recupero dopo un evento non ricevuto
Non sono previsti nuovi tentativi né la riproduzione degli eventi, quindi per ogni famiglia serve una lettura autorevole a cui poter ricorrere. Esegui la riconciliazione a intervalli programmati, non solo quando qualcosa sembra non funzionare.
Esiti della consegna
Ogni tentativo, anche quando non viene inviata alcuna richiesta, viene registrato con uno stato. Queste sono le stringhe esatte.
Una lista di controllo per il ricevitore
- Verifica la firma di ogni richiesta; se non corrisponde, restituisci
401e non elaborare nulla. - Calcola l'hash dei byte del corpo originale, mai di un oggetto serializzato di nuovo.
- Restituisci
2xxin un tempo ben inferiore a 5 secondi; metti l'elaborazione in coda. - Usa gli ID contenuti in
datacome chiave per ogni scrittura dell'handler, in modo che una ripetizione produca lo stesso risultato, ma non considerare mai un ID ripetuto come un'indicazione che non ci sia nulla da fare. - Non dedurre l'ordine degli eventi dall'ordine di arrivo e non ordinarli in base a
timestamp. - Normalizza
location_idcome stringa alla ricezione. - Ignora i valori di
eventche non riconosci e restituisci comunque200. - Rendi disponibile l'URL dei webhook come URL finale, senza reindirizzamenti.
- Riconcilia periodicamente i dati con quelli dell'API REST; non sono previsti nuovi tentativi su cui fare affidamento.