
# Webhook

I webhook consentono a <span data-t="appName">Your AI Connector</span> di notificare automaticamente gli altri strumenti aziendali ogni volta che accade qualcosa di importante: la creazione di un nuovo contatto, la prenotazione di un appuntamento, la ricezione di un messaggio. Invece di controllare manualmente gli aggiornamenti, i sistemi connessi ricevono una notifica istantanea nel momento in cui si verifica un evento.


---

## Cosa sono i webhook?

Pensa a un webhook come a un messaggio di testo automatico tra due app. Quando accade qualcosa in <span data-t="appName">Your AI Connector</span> (come l'iscrizione di un nuovo contatto), la piattaforma invia istantaneamente una notifica a un altro sistema a tua scelta. Devi fornire un indirizzo web (chiamato "URL del webhook") a cui inviare queste notifiche; solitamente questo viene fornito dal tuo CRM, dalla piattaforma di automazione o dallo sviluppatore.

> **I webhook inviano dati solo IN USCITA da <span data-t="appName">Your AI Connector</span>.** Un webhook è una strada a senso unico *da* <span data-t="appName">Your AI Connector</span> *verso* i tuoi altri strumenti. **Non esiste un URL webhook che invii lead, contatti o messaggi ALL'INTERNO della piattaforma.** Per inserire un nuovo lead — da un modulo web, dal tuo CRM o da GoHighLevel — il tuo sistema effettua invece una **chiamata API**. Consulta [Accesso API](api-access.md) (l'operazione *Crea un contatto*) e [Funnel](funnels.md). L'unica cosa di cui hai bisogno per la direzione in entrata è la tua **chiave API**, che si trova nella sua sezione dedicata: consulta [Accesso API](api-access.md#generating-your-api-key). La pagina **Webhook** descritta qui è esclusivamente per la direzione in uscita.

::: note
**Nota:** La configurazione dei webhook comporta alcune impostazioni tecniche. Se non ti senti a tuo agio, condividi questa pagina con il tuo sviluppatore o utilizza una piattaforma di automazione come Zapier, Make o Pabbly, che forniscono URL di webhook senza richiedere alcuna programmazione.
:::


Gli utilizzi comuni includono:

- Sincronizzazione dei nuovi contatti con il tuo CRM.
- Attivazione di un flusso di lavoro in Zapier, Make o Pabbly quando viene applicato un tag.
- Notifica al tuo team su Slack quando viene richiesto l'intervento umano.
- Aggiornamento del sistema di calendario quando viene prenotato un appuntamento.
- Registrazione dei riepiloghi delle conversazioni nel tuo database.

---

## Configurazione dei webhook

1. Nella barra laterale sinistra, fai clic su **Impostazioni** (icona a forma di ingranaggio).
2. Nella barra laterale Impostazioni, sotto il gruppo **Integrazioni**, fai clic su **Webhook**.


Su un account in cui non sono ancora stati configurati webhook, la pagina si presenta così:


3. Fai clic su **New webhook** in alto a destra. Si aprirà un modulo direttamente nella pagina:


4. Compila:
   - **URL dell'endpoint** — l'indirizzo web a cui <span data-t="appName">Your AI Connector</span> invierà le notifiche degli eventi. Lo ottieni dal tuo sistema esterno (CRM, piattaforma di automazione o server personalizzato).
   - **Nome** — un'etichetta che riconoscerai in seguito (ad es. "Avvisi Slack" o "Sincronizzazione CRM"). Solo per tuo riferimento.

> **Il tuo URL del webhook deve essere un indirizzo `https://` raggiungibile pubblicamente.** Gli indirizzi `http://` semplici, `localhost` o gli indirizzi di rete privata e quelli interni alla piattaforma vengono rifiutati al momento del salvataggio. Per testare dal tuo computer, usa un tunnel pubblico (webhook.site o ngrok) invece di localhost.

5. In **Eventi**, fai clic sugli eventi che vuoi che questo webhook riceva: tutti i 22 sono elencati in [I 22 eventi webhook](#the-22-webhook-events).
6. *(Facoltativo)* Attiva **Riprova consegne non riuscite** se vuoi che <span data-t="appName">Your AI Connector</span> continui a tentare in caso di errore temporaneo; vedi [Riprovare le consegne non riuscite](#retrying-failed-deliveries).
7. Fai clic su **Crea webhook**. Apparirà nell'elenco sotto il modulo e potrai fare clic su **Test** sulla sua riga in qualsiasi momento per inviare un payload di esempio al tuo endpoint.

> **Autorizzazione necessaria.** L'aggiunta, la modifica o il test dei webhook richiedono l'autorizzazione "modifica" per le Integrazioni (i membri del team con sola visualizzazione vedranno un avviso di sola lettura invece del modulo).

> **La firma di un webhook** richiede che sia già stato salvato: apri la riga di un webhook esistente per modificarlo e il pannello **Segreto di firma** apparirà in fondo al modulo di modifica. Una bozza nuova di zecca non salvata non ha ancora l'opzione di firma; vedi [Payload firmati](#signed-payloads-verifying-a-webhook-really-came-from-us) qui sotto.

---

## Un webhook per tutti i tuoi account cliente (Agenzie)

Se gestisci un'agenzia, non devi ricreare lo stesso webhook su ogni account cliente. Nell'account agenzia, il modulo webhook presenta un interruttore aggiuntivo: **Attiva anche per tutti gli account cliente**. Attivalo e questo webhook riceverà anche gli eventi che si verificano su ogni account cliente sotto la tua agenzia: un unico endpoint per l'intera agenzia.

Come funziona:

- **Il blocco `user` ti indica a quale cliente appartiene un evento.** Ogni notifica contiene già un blocco `user` che identifica l'account in cui si è verificato l'evento, in modo che la tua automazione possa instradare i dati per cliente.
- **Le impostazioni del tuo webhook si applicano ovunque.** Gli eventi selezionati, il segreto di firma e l'impostazione di riprova vengono utilizzati anche per le consegne agli account cliente.
- **Nessuna doppia consegna.** Se un account cliente ha un proprio webhook che punta allo stesso URL, quello verrà utilizzato per gli eventi di quell'account: lo stesso evento non arriverà mai due volte allo stesso endpoint.
- **I clienti non lo vedono.** Il webhook non appare nella pagina Webhook dell'account cliente e i clienti non possono disattivarlo: spetta a te gestirlo.
- **L'affidabilità è monitorata per singolo account cliente.** Se il tuo endpoint continua a fallire, viene disattivato automaticamente solo per l'account le cui consegne non sono andate a buon fine (vedi [Affidabilità dei webhook](#webhook-reliability)), non per l'intera agenzia contemporaneamente.

L'interruttore appare solo negli account agenzia. È supportata anche l'impostazione tramite API: vedi il campo `apply_to_sub_accounts` nelle [API Webhook](../api/webhooks.md#one-subscription-for-all-client-accounts-agencies).

---

## Eventi trigger disponibili

Puoi abilitare o disabilitare ciascuno dei 22 eventi webhook in modo indipendente. Quando si verifica un evento, <span data-t="appName">Your AI Connector</span> invia una notifica al tuo URL webhook con i dati pertinenti. Ogni evento, il suo significato e il codice `event` che inserisce nel payload sono elencati insieme in [I 22 eventi webhook](#the-22-webhook-events) più avanti in questa pagina.

> **Buono a sapersi:** **Attività creata**, **Attività aggiornata** e **Attività completata** sono completamente selezionabili e vengono salvate correttamente. Anche **Riepilogo giornaliero creato** è una recente aggiunta. Vedi [Webhook Attività completata](#task-completed-webhook) di seguito per la struttura di quel payload.

---

## Trigger webhook basati su tag

`subscribed_to_tags` non limita gli eventi di un webhook a un tag. Limita solo quali tag producono una notifica di riepilogo della conversazione. Per ricevere una richiesta quando viene applicato un tag specifico, imposta un URL webhook su quel tag nella scheda **Tag** dell'agente (o della campagna).

Il modulo webhook stesso non ha un selettore di tag, né durante la creazione di un nuovo webhook né durante la modifica di uno esistente, quindi `subscribed_to_tags` può essere letto o modificato solo tramite l'[API Webhook](../api/webhooks.md) o chiedendo assistenza.

> **Buono a sapersi:** la modifica di un webhook esistente che ha un elenco `subscribed_to_tags` (rinominarlo, modificarne gli eventi, attivare/disattivare i tentativi) non cancella più tale elenco: poiché il modulo non ha un selettore di tag da inviare, il salvataggio da questa pagina ora lascia l'elenco esistente intatto. (Questo era un vero bug prima del **21 luglio 2026**: il salvataggio dal modulo webhook cancellava l'elenco perché inviava sempre un elenco di tag vuoto. Se un webhook ha perso il suo elenco `subscribed_to_tags` prima di quella data, dovrà essere riconfigurato tramite l'API.)

### Genera riepilogo per i contatti con tag

Laddove un webhook ha un elenco `subscribed_to_tags`, puoi attivare **Genera riepilogo**. Quando abilitato, <span data-t="appName">Your AI Connector</span> genera automaticamente un riepilogo della conversazione per il contatto quando uno di quei tag viene applicato e lo include nei dati del webhook: contesto completo senza una richiesta separata.

---

## Test del webhook

1. Apri **Impostazioni → Integrazioni → Webhook**.
2. Nella riga del tuo webhook, fai clic su **Test**.
3. Controlla il tuo sistema esterno per confermare che abbia ricevuto i dati di test.
4. Esamina il formato dei dati per assicurarti che il tuo sistema possa analizzarli correttamente.

Per un test completo end-to-end, invia un messaggio che attiverebbe uno dei tuoi eventi configurati (una trasmissione o un messaggio in arrivo su un canale connesso) e verifica che il webhook venga attivato con i dati reali.

::: tip
**Suggerimento:** Utilizza uno strumento come [webhook.site](https://webhook.site) o [RequestBin](https://requestbin.com) durante lo sviluppo per ispezionare i dati grezzi del webhook prima di collegare il tuo sistema di produzione.
:::


### Cosa costituisce una consegna riuscita

Che tu faccia clic su **Test** o che l'evento si attivi realmente, inviamo la stessa cosa:

- Una richiesta **POST** (mai GET), con il corpo come JSON e `Content-Type: application/json`.
- Le intestazioni elencate in [Payload firmati](#signed-payloads-verifying-a-webhook-really-came-from-us). Le intestazioni di firma sono incluse solo dopo aver impostato un segreto di firma.

Consideriamo la consegna riuscita quando:

- Il tuo endpoint risponde con **qualsiasi stato 2xx** (200, 201, 204: vanno tutti bene).
- Risponde **entro 30 secondi**.

Alcune cose che sorprendono:

- **Il corpo della risposta viene ignorato.** Non è necessario restituire alcun JSON particolare. Un 200 vuoto è sufficiente.
- **I reindirizzamenti contano come errore.** Non li seguiamo, quindi un 301 o 302 (incluso un reindirizzamento con barra finale, o da http a https) viene registrato come consegna fallita. Salva l'URL finale, non uno che reindirizza.
- **Le stringhe di query sono pienamente supportate.** `https://your-app.com/hook?token=abc123` viene inviato esattamente come lo hai salvato, quindi inserire un token nella stringa di query funziona tanto bene quanto inserirlo nel percorso.
- **Il tuo URL deve essere `https://` e raggiungibile pubblicamente.** Gli indirizzi che appartengono all'infrastruttura di <span data-t="appName">Your AI Connector</span> vengono rifiutati, ma i tuoi endpoint su Google Cloud Functions, Cloud Run, App Engine, Firebase Hosting o ovunque altro vanno bene.
- **Un firewall o un livello di protezione dai bot davanti al tuo endpoint può bloccarci.** Il caso più comune è Cloudflare: se la tua zona ha la modalità "Bot Fight Mode" o una sfida gestita attiva, la nostra richiesta riceve una pagina di sfida "Just a moment..." con un 403 invece di raggiungere il tuo server — e una richiesta server-to-server non può mai superare una sfida del browser, quindi sia il pulsante **Test** che gli eventi reali falliscono allo stesso modo. Il pulsante Test ti dirà quando ciò accade ("Cloudflare sta mostrando una sfida bot alla nostra richiesta"). Risolvi il problema in Cloudflare con una regola di Sicurezza / WAF che ignora le sfide per il tuo percorso webhook (o per l'user agent `Webhook-Delivery/1.0`), quindi clicca di nuovo su **Test**.
- **Se il tuo firewall necessita invece di una whitelist di IP** (ad esempio il piano gratuito di Cloudflare, dove la semplice modalità Bot Fight Mode non può essere ignorata da una regola WAF, ma una regola di accesso IP impostata su Consenti viene eseguita prima), possiamo aiutarti: ogni consegna, sia dal pulsante **Test** che da un evento live, viene inviata da un indirizzo IPv4 fisso (nessun intervallo, nessun IPv6, nessuna rotazione). Contatta l'assistenza e ti forniremo l'indirizzo da inserire nella whitelist. Mantieni la [verifica della firma](#signed-payloads-verifying-a-webhook-really-came-from-us) come tuo controllo di attendibilità effettivo, poiché convalida ogni payload indipendentemente dalla sua provenienza.
- **Il risultato del Test ti dice esattamente cosa ha risposto il tuo endpoint.** Un test fallito ora mostra il motivo reale (lo stato HTTP restituito dal tuo endpoint, un timeout, o che non siamo riusciti affatto a raggiungere l'indirizzo) invece di un errore generico, e un test su un webhook salvato viene inviato firmato quando la firma è attiva, esattamente come un evento live.

### Utilizzo di n8n, Make o Zapier ("Test URL" vs "Production URL")

Le piattaforme di automazione solitamente forniscono due diversi indirizzi webhook, il che spesso crea confusione:

- Un **URL di test** (in n8n contiene `/webhook-test/`). Questo riceve dati solo mentre stai osservando attivamente l'area di lavoro e hai appena fatto clic su **Listen for test event** (o **Test workflow**). Cattura un singolo evento e poi smette di ascoltare; quindi, fare clic su **Test** in <span data-t="appName">Your AI Connector</span> più volte di seguito cattura solo il primo, e solo se la finestra di ascolto è attiva in quel preciso momento. Per testare: fai prima clic su **Listen for test event** in n8n, poi torna a <span data-t="appName">Your AI Connector</span> e fai clic su **Test** una volta.
- Un **URL di produzione** (in n8n contiene `/webhook/`, senza `-test`). Questo è quello da incollare in <span data-t="appName">Your AI Connector</span> per gli eventi dal vivo. Funziona solo una volta che il tuo flusso di lavoro è impostato su **Active**. Se il flusso di lavoro non è attivo, n8n rifiuta la richiesta con un errore "404 / webhook not registered", anche se <span data-t="appName">Your AI Connector</span> ha inviato i dati correttamente.

In breve: testa con l'URL di test mentre sei in ascolto, ma affinché il webhook continui a funzionare con i contatti reali, salva l'**URL di produzione** in <span data-t="appName">Your AI Connector</span> e assicurati che il workflow sia **Active**.

---

## Formato dati webhook

Quando un webhook viene attivato, <span data-t="appName">Your AI Connector</span> invia dati strutturati (JSON) al tuo URL del webhook. Se utilizzi una piattaforma di automazione come Zapier o Make, questi dati vengono analizzati automaticamente. Se stai creando un'integrazione personalizzata:

```json
{
  "event": "contactCreated",
  "contact": { "id": "<contact-id>", "first_name": "Jane", "...": "..." },
  "campaign": { "id": "<campaign-id>", "name": "AI Receptionist", "status": "Live" },
  "agent": { "id": "<agent-id>", "name": "Front Desk" },
  "user": { "id": "<account-id>", "email": "owner@example.com" }
}
```

| Campo | Descrizione |
|---|---|
| `event` | L'esatta stringa dell'evento che ha attivato la notifica (ad esempio, `contactCreated`, `booked`). Questa **non** è l'etichetta visualizzata nell'elenco degli eventi; ogni etichetta e il relativo codice corrispondente si trovano in [I 22 eventi webhook](#the-22-webhook-events). |
| `contact` | Il contatto a cui si riferisce l'evento, o `null` per gli eventi non legati a un contatto (come `creditsRecharged`). |
| `campaign` | La campagna a cui appartiene il contatto, o `null` se non ce n'è una. |
| `agent` | L'agente che gestisce la conversazione, o `null` se non ce n'è uno. |
| `user` | Informazioni di identità di base per l'account che possiede i dati. |

> **`campaign` o `agent` — solitamente uno, non entrambi.** Se il tuo account utilizza gli agenti, i tuoi contatti sono assegnati a un agente anziché a una campagna, quindi `campaign` arriva come `null` e `agent` ti indica chi l'ha gestito. Gli account più vecchi basati su campagne vedono l'inverso. Leggi quello che è compilato; non dare per scontato che `campaign` sia sempre presente.

> **Il blocco `agent` è arrivato il 15 agosto 2026.** Si affianca a `campaign` negli eventi legati a una conversazione — una chat conclusa, non disturbare, una ripresa, un annullamento dell'archiviazione, una pausa dell'IA, un nuovo messaggio, un riepilogo della conversazione e il webhook che puoi impostare su un tag — e contiene `id` e `name` dell'agente che gestisce la conversazione, oppure `null` quando non è coinvolto alcun agente. È puramente aggiuntivo: ogni campo che ricevi già rimane invariato, quindi un ricevitore creato prima di tale data continuerà a funzionare senza bisogno di aggiornamenti.

Alcuni eventi aggiungono il proprio blocco di primo livello. Ad esempio, **Appointment Booked** aggiunge un blocco `appointment` (vedi [Webhook Appointment Booked](#appointment-booked-webhook)), **New Message** aggiunge un blocco `message` completo con il testo (vedi [Webhook New Message](#new-message-webhook)), mentre **Deliveries** e **Reads** aggiungono un breve blocco `message` contenente solo l'ID e lo stato del messaggio (vedi [Webhook Deliveries and Reads](#deliveries-and-reads-webhook)).

> **Deliveries e Reads indicano a quale messaggio si riferiscono, ma non il contenuto.** Contengono un blocco `message` con l' `id` e lo `status` del messaggio — e quell' `id` è lo stesso `messageId` restituito dall'[endpoint di invio messaggi](../api/messages.md#send-a-message), così puoi associare una conferma di consegna o di lettura all'esatto messaggio inviato — ma non il corpo del messaggio. **Replies** non contiene alcun blocco `message`. Se ti servono le parole inviate o ricevute, iscriviti anche a **New Message**.

> **Due cose da sapere prima di scrivere il tuo ricevitore.** Non c'è alcun campo `timestamp` e nessun wrapper `data`. Ogni blocco si trova al livello principale dell'oggetto JSON, come mostrato sopra.

### I 22 eventi webhook

I 22 eventi webhook, con l'etichetta visualizzata che selezioni nell'app e il codice `event` inviato nel payload. Il codice `event` è una breve stringa che **non** corrisponde all'etichetta visualizzata, quindi fai corrispondere il tuo ricevitore al codice, non all'etichetta:

| Etichetta visualizzata (nell'app) | Codice `event` nel payload | Significato |
|---|---|---|
| Contact Created | `contactCreated` | Un nuovo contatto viene aggiunto al tuo account (manualmente, tramite importazione o tramite API). |
| Contact Paused | `contact_paused` | Una conversazione con un contatto viene messa in pausa (il bot smette di rispondere). |
| Contact Resumed | `contact_resumed` | Una conversazione con un contatto in pausa viene ripresa. |
| Contact Do Not Disturb | `contact_do_not_disturb_changed` | L'impostazione "Non disturbare" di un contatto viene attivata. |
| Contact Unarchived | `contact_unarchived` | Un contatto archiviato invia un nuovo messaggio, tornando così nella tua casella di posta attiva. |
| New Message | `new_message` | Qualsiasi messaggio aggiunto a una conversazione su qualsiasi canale — sia i messaggi inviati dal contatto che quelli inviati dal tuo AI o dal tuo team. Questo è l'unico evento che contiene il testo effettivo del messaggio (vedi [Webhook New Message](#new-message-webhook)). |
| Replies | `replied` | Un contatto risponde a un messaggio. |
| Reads | `read` | Un contatto legge un messaggio (sui canali che supportano le conferme di lettura). Contiene l'ID del messaggio letto — vedi [Webhook Deliveries and Reads](#deliveries-and-reads-webhook). |
| Deliveries | `delivered` o `undelivered` | Un messaggio viene consegnato correttamente a un contatto (`undelivered` se la consegna fallisce). Contiene l'ID del messaggio — vedi [Webhook Deliveries and Reads](#deliveries-and-reads-webhook). |
| Human Alerted | `humanAlerted` | Il bot AI determina di non poter gestire una conversazione e la segnala per l'intervento umano. |
| Chat Concluded | `chat_concluded` | Il bot AI decide che una conversazione è giunta al termine (appuntamento fissato, lead squalificato, ecc.). |
| Appointment Booked | `booked` | Un contatto prenota un appuntamento tramite il sistema di prenotazione. |
| Credits Spent | `creditsSpent` | I crediti vengono detratti dal tuo account. |
| Credits Recharged | `creditsRecharged` | I crediti vengono aggiunti al tuo account tramite ricarica automatica o acquisto manuale. |
| Low Credit Balance | `lowCreditBalance` su una consegna **Test**, `Low Credit Balance` su una reale | Un avviso preventivo che il tuo saldo crediti è sceso sotto la soglia di allerta (100 crediti, a meno che tu non ne abbia impostata una diversa). Destinato alle agenzie, i cui sub-account spendono tutti da un unico pool. Contiene `balance`, `threshold` e `account_email` invece di un blocco contatto, viene inviato al massimo una volta ogni 24 ore finché il saldo rimane basso e si riattiva non appena il saldo torna sopra la soglia. |
| Task Created | `taskCreated` | Un'attività viene creata. |
| Task Updated | `taskUpdated` | Un'attività cambia senza passare a una fase di completamento. |
| Task Completed | `taskCompleted` | Un'attività passa a una fase configurata come fase di completamento. |
| Daily Summary Created | `dailySummaryCreated` | Viene generato il tuo report di riepilogo giornaliero. |
| Channel Connected | `channelConnected` | **Non ancora inviato — selezionabile, ma al momento non viene emesso. Non basare lo sviluppo su questo.** Destinato al momento in cui un canale di messaggistica termina la connessione. |
| Broadcast Started | `broadcastStarted` | Un broadcast inizia l'invio (il suo stato cambia in Sending). Si attiva una volta per avvio, incluso quando un broadcast in pausa viene ripreso. Contiene un blocco `broadcast` invece di un blocco contatto: id, nome, canale, stato, stato precedente, la lista a cui è rivolto (`list_id`, `list_name`, `is_smart_list`), `scheduled_at`, `total_contacts`. |
| Broadcast Completed | `broadcastCompleted` | Un broadcast termina (il suo stato cambia in Sent o Failed). Stesso blocco `broadcast` più `completed_at` e, quando disponibile, `completion_summary` (`total_sent`, `permanently_failed`, `unique_replied`, `failure_rate`, `had_errors`). Usa questi due per collegare una Smart Broadcast List a strumenti esterni. |

Altri due codici non appaiono mai in quell'elenco perché non vi sei iscritto: `contact_tags_updated`, inviato da un URL webhook impostato su un singolo tag, e `summary_generated`, inviato quando viene scritto un riepilogo della chat per un tag nell'elenco `subscribed_to_tags` di un webhook.

> **Canale connesso non è ancora inviato.** Appare nell'elenco degli eventi, ma al momento nulla lo emette. Non basare alcuno sviluppo su di esso.

Le notifiche basate su tag e attività utilizzano le proprie strutture separate. Vedi [Tag contatto aggiornati](#contact-tags-updated-webhook) e [Attività completata](#task-completed-webhook).

---

## Webhook di creazione contatto

Inviato quando viene attivato l'evento **Contatto creato** (un nuovo contatto viene aggiunto manualmente, tramite importazione o tramite API).

### Nome evento

`contactCreated`

### Formato del payload

```json
{
  "event": "contactCreated",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null,
    "is_bot_active": true,
    "ad_referral": null
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  }
}
```

| Campo | Descrizione |
|---|---|
| `event` | Sempre `contactCreated` per questo evento. |
| `contact.id` | L'ID univoco del nuovo contatto. |
| `contact.email` / `contact.phone_number` | Email e telefono del contatto, se noti (entrambi potrebbero essere vuoti a seconda del canale). |
| `contact.first_name` / `contact.last_name` | Nome del contatto, se noto. |
| `contact.human_alerted` / `contact.human_alert_reason` | Se il contatto è contrassegnato per l'attenzione umana e perché. |
| `contact.is_bot_active` | Se il bot AI è attualmente attivo su questo contatto. |
| `contact.ad_referral` | Attribuzione dell'annuncio Meta Click-to-WhatsApp, o `null` — vedi [Attribuzione dell'annuncio Click-to-WhatsApp](click-to-whatsapp-attribution.md). |
| `campaign` | La campagna sotto la quale è stato creato il contatto, o `null`. |
| `agent` | L'agente assegnato al contatto, o `null`. |
| `user` | Informazioni di identità di base per l'account che possiede il contatto. |

> **Il campione "Test" e un evento reale hanno un aspetto leggermente diverso.** Il pulsante di test invia dati segnaposto (John Doe, una campagna di esempio). Un evento reale di contatto creato contiene i dettagli effettivi del contatto e alcuni campi potrebbero essere vuoti a seconda del canale.

---

## Webhook Nuovo messaggio

Questo webhook si attiva ogni volta che un messaggio viene aggiunto a una conversazione, su qualsiasi canale. Copre entrambe le direzioni: i messaggi che il contatto ti invia e i messaggi che la tua IA, il tuo team o una campagna inviano al contatto. È l'unico webhook che include il testo del messaggio, quindi è quello da utilizzare quando desideri replicare le conversazioni in un sistema esterno.

### Nome evento

`new_message`

### Formato del payload

```json
{
  "event": "new_message",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null,
    "is_bot_active": true,
    "ad_referral": null
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<message-id>",
    "body": "Hi, are you open on Saturday?",
    "direction": "inbound",
    "status": "received",
    "created_at": "2026-07-30T17:27:06.000Z",
    "channel": "whatsapp_web"
  }
}
```

| Campo | Descrizione |
|---|---|
| `event` | Sempre `new_message` per questo evento. Nota che questa è l'esatta stringa inviata — non è l'etichetta visualizzata "New Message". |
| `contact` | Il contatto a cui appartiene la conversazione del messaggio. Stessa forma di [Contact Created](#contact-created-webhook). |
| `agent` | L'agente che gestisce la conversazione (`id` e `name`), o `null` se non è coinvolto alcun agente. |
| `user` | Informazioni di identità di base per l'account che possiede la conversazione. |
| `message.id` | L'ID univoco del messaggio. |
| `message.body` | Il testo del messaggio. Vuoto per un messaggio che contiene solo un allegato (immagine, nota vocale, documento). |
| `message.direction` | `inbound` per un messaggio dal contatto, `outbound` per uno inviato dal tuo AI o dal tuo team dalla casella di posta, e `outbound-api` per uno inviato da una campagna, un broadcast, un invio di template o l'API. |
| `message.status` | Dove si trova il messaggio nel suo ciclo di vita: `received` per i messaggi in entrata, e `queued` / `sent` / `delivered` / `read` / `failed` / `undelivered` per quelli in uscita. Questo è lo stato nel momento in cui il messaggio è stato creato, quindi un messaggio in uscita solitamente arriva qui come `queued` o `sent` e raggiunge `delivered` in seguito — usa gli eventi **Deliveries** e **Reads** se ti servono quelle transizioni successive. Contengono lo stesso `message.id` di questo blocco, così puoi associare la transizione a questo messaggio (vedi [Webhook Deliveries and Reads](#deliveries-and-reads-webhook)). |
| `message.created_at` | Quando il messaggio è stato creato, in UTC (ISO 8601). |
| `message.channel` | Il canale attraverso cui è passato il messaggio, ad esempio `whatsapp`, `whatsapp_web`, `sms`, `instagram`, `messenger`, `telegram`, `email` o `custom`. |

> **Non c'è ancora alcun blocco `campaign` in questo payload.** New Message invia `contact`, `agent`, `user` e `message`. Il blocco `agent` è stato aggiunto il **15 agosto 2026** e ti indica quale agente gestisce la conversazione; se hai bisogno anche del contesto della campagna, cerca il contatto tramite l'API usando `contact.id`.

> **I record interni dell'IA non attivano questo webhook.** Oltre ai messaggi reali, la piattaforma mantiene le proprie righe di contabilità in una conversazione (le chiamate agli strumenti dell'IA e i record dei turni interni). Questi non vengono mai inviati: riceverai solo i messaggi che sono stati effettivamente inviati o ricevuti.

---

## Webhook Deliveries and Reads

Questi due eventi riportano cosa è successo a un messaggio dopo che ha lasciato <span data-t="appName">Your AI Connector</span>: **Deliveries** si attiva quando un messaggio raggiunge il contatto (o fallisce nel farlo), e **Reads** si attiva quando il contatto lo apre, sui canali che supportano le conferme di lettura.

Entrambi contengono un blocco `message` con l'ID del messaggio a cui si riferisce l'evento, così puoi associare l'aggiornamento all'esatto messaggio che hai inviato.

### Nomi degli eventi

`delivered` e `undelivered` per **Deliveries**, `read` per **Reads**.

### Formato del payload

```json
{
  "event": "delivered",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "ad_referral": null
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<message-id>",
    "status": "delivered"
  }
}
```

| Campo | Descrizione |
|---|---|
| `event` | `delivered` o `undelivered` per **Deliveries**, `read` per **Reads**. |
| `contact` | Il contatto a cui è stato inviato il messaggio. |
| `campaign` | La campagna a cui appartiene il contatto, o `null`. |
| `agent` | L'agente che gestisce la conversazione, o `null`. |
| `user` | Informazioni di identità di base per l'account che possiede i dati. |
| `message.id` | L'ID del messaggio a cui si riferisce questo aggiornamento. È lo stesso valore che l'[endpoint di invio messaggi](../api/messages.md#send-a-message) restituisce come `messageId`, e lo stesso `message.id` che contiene una notifica di [New Message](#new-message-webhook). |
| `message.status` | Il nuovo stato, sempre la stessa stringa di `event` (`delivered`, `undelivered` o `read`). |

> **Come associare un aggiornamento al messaggio inviato.** Memorizza l' `messageId` che ricevi quando invii un messaggio tramite l'API. Quando arriva una notifica di **Deliveries** o **Reads**, cerca quell'ID memorizzato rispetto a `message.id` nel payload — quella è la tua conferma di consegna o di lettura per quell'esatto messaggio.

> **Qui non c'è il testo del messaggio.** Il blocco `message` contiene solo l'ID e lo stato. Iscriviti a [New Message](#new-message-webhook) se ti serve anche il corpo del messaggio.

> **Il blocco `message` è presente solo quando sappiamo di quale messaggio si tratta.** Nel raro caso di un aggiornamento che non possiamo collegare a un messaggio memorizzato, il blocco viene omesso del tutto invece di essere inviato vuoto — quindi verifica che `message` esista prima di leggere `message.id`.

> **Una notifica per ogni cambio di stato.** Un singolo messaggio in uscita normalmente produce una notifica `delivered` e poi, sui canali con conferme di lettura, una `read`. Un invio fallito produce invece `undelivered`.

---

## Webhook Appuntamento prenotato

Si attiva quando un contatto prenota un appuntamento. Si attiva allo stesso modo sia che l'AI lo abbia prenotato durante una conversazione, che tu lo abbia prenotato a mano o che sia arrivato tramite l'API.

### Nome evento

`booked`

### Formato del payload

```json
{
  "event": "booked",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith"
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com"
  },
  "appointment": {
    "appointment_id": "<appointment-id>",
    "start_time": "2026-07-20T15:00:00.000Z",
    "end_time": "2026-07-20T15:30:00.000Z",
    "status": "confirmed",
    "room_name": "Room 1",
    "description": "Discovery call",
    "summary": "30 min intro",
    "google_calendar_event_id": null,
    "event": {
      "id": "<service-id>",
      "event_name": "Intro Call",
      "slot_duration": 30,
      "location": "Zoom",
      "meeting_link": "https://...",
      "event_type": "online"
    }
  }
}
```

| Campo | Descrizione |
|---|---|
| `event` | Sempre `booked` per questo evento. |
| `contact` | La persona che ha prenotato. `email` e `phone_number` potrebbero essere vuoti a seconda del canale. |
| `appointment.appointment_id` | L'ID univoco della prenotazione. |
| `appointment.start_time` / `end_time` | Inizio e fine dello slot prenotato, in UTC (ISO 8601). |
| `appointment.status` | Lo stato attuale della prenotazione. |
| `appointment.room_name` | La stanza in cui è stata effettuata la prenotazione, se utilizzata. |
| `appointment.description` / `summary` | Dettagli a testo libero acquisiti con la prenotazione. |
| `appointment.google_calendar_event_id` | L'ID di Google Calendar per l'evento sincronizzato. Spesso è `null` nel webhook Appuntamento prenotato, perché l'evento del calendario viene creato nello stesso momento in cui viene inviata la notifica: recupera l'appuntamento tramite il suo `appointment_id` un momento dopo se necessario, e aspettati un `null` permanente sugli account senza Google Calendar collegato. |
| `appointment.event` | Il servizio prenotato: nome, durata dello slot, posizione, link alla riunione, tipo. |

> **`google_calendar_event_id` è spesso `null` in questo webhook, ed è normale.** L'evento di Google Calendar viene creato nello stesso momento in cui viene inviata questa notifica, quindi l'ID solitamente non è ancora pronto. Recupera l'appuntamento tramite il suo `appointment_id` un momento dopo se ne hai bisogno. Rimane `null` in modo permanente se l'account non ha un Google Calendar collegato, quindi non aspettarlo all'infinito.

> **Il pulsante "Test" non include il blocco `appointment`.** Usalo per confermare che il tuo endpoint risponda, quindi effettua una prenotazione reale per vedere il payload completo.

> **Due casi in cui questo webhook non viene attivato:** appuntamenti importati da un calendario esterno e prenotazioni che arrivano tramite l'integrazione Formitable.

---

## Webhook di aggiornamento dei tag del contatto

Si attiva quando un tag viene **applicato** a un contatto e tale tag ha un URL webhook configurato sull'agente o sulla campagna a cui appartiene il contatto.

### Nome evento

`contact_tags_updated`

### Quando viene attivato

- Un tag viene applicato a un contatto a cui è assegnato un agente, una campagna o entrambi.
- Almeno uno dei tag applicati ha un URL webhook impostato nella scheda Tag di quell'agente o campagna.

Se il contatto li ha entrambi e i tag della campagna contengono URL webhook, questi hanno la priorità; altrimenti vengono utilizzati quelli dell'agente.

Se nello stesso aggiornamento vengono applicati più tag con URL webhook diversi, viene inviata una richiesta per ogni URL, contenente solo i tag associati a quell'URL.

**La rimozione di un tag non invia mai una richiesta.** La maggior parte degli utenti punta questi URL a un'azione (riscuotere un deposito, prenotare uno slot, avvisare un rappresentante), quindi la rimozione di un tag da un contatto veniva utilizzata per rieseguire quell'azione. Ora non è più possibile. Una rimozione viene comunque visualizzata in `removed_tags` quando avviene nello stesso aggiornamento di un'applicazione che punta allo stesso URL, in modo che un'automazione che legge entrambi gli array mantenga il quadro completo; ciò che non vedrà mai è una richiesta causata dalla sola rimozione. (Modificato il **12 agosto 2026**. Prima di tale data, anche le rimozioni inviavano una richiesta.)

### Formato del payload

```json
{
  "event": "contact_tags_updated",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "is_bot_active": true,
    "ad_referral": {
      "ctwa_clid": "ARAbc123...",
      "source_id": "120210000000000",
      "source_type": "ad",
      "source_url": "https://fb.me/xxxx",
      "headline": "Get 20% off today",
      "body": "Message us now to claim your discount",
      "channel": "whatsapp"
    }
  },
  "added_tags": ["qualified-lead"],
  "removed_tags": ["new-lead"],
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  }
}
```

| Campo | Descrizione |
|---|---|
| `event` | Sempre `contact_tags_updated` per questo webhook. |
| `contact.id` | L'ID univoco del contatto i cui tag sono cambiati. |
| `contact.email` / `contact.phone_number` | L'email/telefono del contatto, se noto. |
| `contact.first_name` / `contact.last_name` | Il nome del contatto. |
| `contact.human_alerted` | Indica se il contatto è attualmente segnalato per l'attenzione umana. |
| `contact.is_bot_active` | Indica se il bot IA è attualmente attivo nella conversazione di questo contatto. |
| `contact.ad_referral` | Presente solo quando il contatto ti ha raggiunto per la prima volta tramite un annuncio o post Meta Click-to-WhatsApp (CTWA). `null` altrimenti. |
| `added_tags` | Array dei nomi dei tag applicati in questo aggiornamento. Mai vuoto: un'applicazione è ciò che attiva la richiesta. |
| `removed_tags` | Array dei nomi dei tag rimossi nello stesso aggiornamento, se presenti. Una rimozione da sola non invia nulla. |
| `agent` | L'agente che gestisce la conversazione del contatto (`id` e `name`), oppure `null` se non è coinvolto alcun agente. Aggiunto il **15 agosto 2026**. |
| `user` | Informazioni di identità di base per l'account a cui appartiene il contatto. |

### Test di un webhook di tag

Accanto al campo dell'URL del webhook nella scheda Tag è presente un pulsante **Test**. Invia immediatamente un payload di esempio a quell'URL, in modo da poter confermare che la tua automazione lo riceva prima di attendere una conversazione reale.

Il test invia la stessa forma `contact_tags_updated` mostrata sopra, utilizzando un contatto segnaposto, con il tag che stai testando in `added_tags` e un `removed_tags` vuoto. Ciò che la tua automazione vede nel test è ciò che vedrà in produzione.

Due cose da sapere:

- **Salva prima il tag.** Il test cerca il tag in base al suo nome salvato, quindi un tag nuovo di zecca o una ridenominazione non salvata non possono ancora essere testati. Il pulsante rimane disattivato finché il nome sullo schermo non corrisponde a quello salvato.
- **Un test fallito non conta contro il tuo webhook.** I test non contribuiscono mai allo spegnimento automatico dopo ripetuti fallimenti descritto in [Affidabilità webhook](#webhook-reliability).

Se il test fallisce, il messaggio ti indica cosa ha risposto il tuo endpoint (ad esempio un `404` o un `500`), il che è solitamente sufficiente per individuare un URL errato o un flusso di lavoro che non è attivo.

---

## Webhook di completamento attività

> **Solo per riferimento.** I webhook delle attività (come dati) sono documentati qui per gli sviluppatori; gli eventi **Attività creata**, **Attività aggiornata** e **Attività completata** sono selezionabili nell'elenco standard degli eventi nel modulo webhook come qualsiasi altro evento: vedi [Eventi trigger disponibili](#available-trigger-events) e [I 22 eventi webhook](#the-22-webhook-events).

Questo payload viene inviato quando un'attività passa a una fase contrassegnata come fase di completamento. Un'attività che si sposta tra fasi non di completamento invia invece il formato `taskUpdated`.

### Nome evento

`taskCompleted`

### Quando viene attivato

- Un'attività viene aggiornata.
- Il suo valore `stage` è cambiato rispetto al valore precedente.
- La nuova fase è configurata come fase di completamento nelle impostazioni delle fasi attività dell'account.

### Formato del payload

```json
{
  "event": "taskCompleted",
  "contact": {
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null
  },
  "user": {
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<task-id>",
    "title": "Follow up with Jane",
    "description": "Confirm pricing and send proposal",
    "type": "follow_up",
    "priority": "high",
    "stage": "<stage-id>",
    "due_date": "2026-01-20T15:00:00Z",
    "source": "ai",
    "source_detail": "<source-detail>",
    "campaign_id": "<campaign-id>",
    "linked_human_alert": "<human-alert-id>",
    "tags": ["qualified-lead"],
    "notes": "Customer requested a callback"
  }
}
```

| Campo | Descrizione |
|---|---|
| `event` | Sempre `taskCompleted` per questo webhook. Viene inviato lo stesso formato di payload di `taskUpdated` quando un'attività cambia senza entrare in una fase di completamento. |
| `contact` | Il contatto collegato all'attività, se presente. `null` se non collegato. |
| `contact.human_alert_reason` | Il motivo per cui il contatto è stato contrassegnato per l'attenzione umana, se applicabile. |
| `user` | Informazioni di identità di base per l'account a cui appartiene l'attività. |
| `message.id` | L'ID univoco dell'attività. |
| `message.title` / `description` | Il titolo e la descrizione dell'attività. |
| `message.type` | Il tipo di attività (ad esempio, `follow_up`, `call`, `custom`). |
| `message.priority` | La priorità dell'attività (`low`, `medium`, `high`). |
| `message.stage` | L'ID della fase in cui si trova ora l'attività. |
| `message.due_date` | La data di scadenza dell'attività, se impostata. |
| `message.source` | Cosa ha creato l'attività (`ai`, `manual`, `api`). |
| `message.source_detail` | Dettagli aggiuntivi sulla fonte. |
| `message.campaign_id` | L'ID della campagna collegata, o `null`. |
| `message.linked_human_alert` | L'ID dell'avviso umano collegato, se presente. |
| `message.tags` | Tag applicati all'attività. |
| `message.notes` | Note a formato libero sull'attività. |

---

## Disattivare (o eliminare) un webhook

Ogni webhook ha un interruttore on/off, proprio sulla sua riga. Spegnerlo (**off**) impedisce la ricezione di eventi, ma mantiene tutto ciò che hai configurato: l'URL, gli eventi, qualsiasi segreto di firma. Riaccendilo e riprenderà da dove era rimasto; nulla di ciò che è accaduto mentre era spento verrà consegnato in seguito.

Utilizza questa funzione quando desideri sospendere temporaneamente le consegne: ad esempio, se il tuo endpoint è in fase di ricostruzione, se stai eseguendo il debug di un'integrazione troppo rumorosa o se stai mettendo in pausa un'automazione.

**Eliminare** un webhook (l'icona del cestino sulla sua riga) lo rimuove definitivamente, incluso il suo segreto di firma. Se vuoi solo interrompere le consegne, spegnilo invece: l'eliminazione serve quando hai finito completamente con l'endpoint.

> **Questo non è lo stesso che disattivare automaticamente un webhook.** Se disabilitiamo il tuo webhook dopo ripetuti errori (vedi [Affidabilità dei Webhook](#webhook-reliability)), l'interruttore qui sopra non lo riattiverà. Una volta corretto l'endpoint, modifica il webhook e salvalo con un URL diverso (qualsiasi modifica all'URL lo riabilita), oppure chiama l'[endpoint di riabilitazione](../api/webhooks.md) tramite API, o chiedi al supporto e lo riattiveremo noi per te.

---

## Payload firmati (Verifica che un webhook provenga realmente da noi)

Chiunque conosca il tuo URL webhook potrebbe inviargli una richiesta falsa. Se agisci automaticamente sui webhook — aggiornando la fatturazione, creando record CRM — attivare la **firma** ti consente di verificare che ogni richiesta provenga effettivamente da noi.

La firma è **opzionale e disattivata per impostazione predefinita**, e si attiva per ogni webhook, dalla vista di modifica di quel webhook (apri la riga di un webhook salvato).

### Attivazione della firma

1. Apri il webhook (Impostazioni → Integrazioni → Webhook → clicca sulla riga del tuo webhook).
2. Nella sezione **Segreto di firma**, clicca su **Genera**.
3. Copia il segreto (inizia con `whsec_`) e salvalo nel tuo sistema ricevente. Trattalo come una password.

Puoi tornare a visualizzare, copiare, ruotare o disattivare il segreto in qualsiasi momento dallo stesso pannello.

### Cosa inviamo

Una volta attivata la firma, ogni consegna per quel webhook contiene questi due header HTTP aggiuntivi:

| Header | Significato |
|---|---|
| `X-Webhook-Signature` | La firma, nel formato `v1=<hex>`. |
| `X-Webhook-Timestamp` | Quando l'abbiamo inviato, come timestamp Unix in secondi. |

Questi tre sono presenti su **ogni** consegna, firmata o meno:

| Header | Significato |
|---|---|
| `X-Webhook-Delivery` | Un ID univoco per questo evento. Rimane lo stesso durante i tentativi, quindi è ciò su cui effettuare la deduplicazione. |
| `X-Webhook-Attempt` | Quale tentativo è questo (`1` è il primo tentativo). |
| `X-Webhook-Event` | Il nome dell'evento, così puoi instradare senza leggere il corpo. |

### Come verificare

La firma è un HMAC-SHA256 della stringa `<timestamp>.<raw request body>`, utilizzando il tuo segreto di firma come chiave.

**Verifica rispetto al corpo della richiesta grezza: i byte esatti che hai ricevuto.** Se il tuo framework analizza il JSON e lo ri-serializza prima del controllo, i byte possono cambiare e la firma non corrisponderà.

Esempio in Node.js:

```js
const crypto = require("crypto");

function verify(rawBody, headers, secret) {
  const timestamp = headers["x-webhook-timestamp"];
  const signature = headers["x-webhook-signature"]; // "v1=<hex>"

  // Reject anything older than 5 minutes so a captured request can't be replayed later.
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

  const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");

  return crypto.timingSafeEqual(Buffer.from(signature.replace("v1=", "")), Buffer.from(expected));
}
```

Esempio in Python:

```python
import hashlib, hmac, time

def verify(raw_body: bytes, headers, secret: str) -> bool:
    timestamp = headers["X-Webhook-Timestamp"]
    signature = headers["X-Webhook-Signature"].replace("v1=", "")

    # Reject anything older than 5 minutes so a captured request can't be replayed later.
    if abs(time.time() - int(timestamp)) > 300:
        return False

    expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256).hexdigest()

    return hmac.compare_digest(signature, expected)
```

> **Confronta le firme con una funzione a tempo costante** (`timingSafeEqual` / `compare_digest`), non con `==`. Non ha alcun costo e previene una sottile classe di attacchi.

### Rotazione del segreto

Fai clic su **Ruota** per sostituire il segreto. Il passaggio è immediato: la consegna successiva viene firmata esclusivamente con il nuovo segreto. Se il tuo endpoint è attivo, accetta **sia** il vecchio che il nuovo segreto per alcuni minuti mentre distribuisci quello nuovo.

Disattivare la firma interrompe semplicemente l'invio delle intestazioni di firma.

---

## Riprovare le consegne fallite

Per impostazione predefinita, una consegna che fallisce non viene riprovata: se il tuo sistema è inattivo in quel momento, l'evento andrà perso.

Attiva **Riprova consegne fallite** su un webhook (nel modulo di creazione/modifica) e continueremo a riprovare:

| Tentativo | Quando |
|---|---|
| 1 | Immediatamente |
| 2 | 1 minuto dopo |
| 3 | 5 minuti dopo |
| 4 | 30 minuti dopo |
| 5 | 2 ore dopo |

Ciò copre circa **2 ore e 40 minuti**, quindi un webhook può sopravvivere a una finestra di manutenzione o a una breve interruzione da parte tua.

**Cosa viene riprovato:** problemi temporanei, come il server che restituisce un errore 5xx, un timeout o un errore di connessione.

**Cosa non viene riprovato:** se il tuo endpoint rifiuta la richiesta stessa (qualsiasi 4xx), non riproviamo: inviare nuovamente la stessa richiesta produrrebbe solo lo stesso rifiuto.

**Quali eventi vengono ritentati:** webhook dei tag (`contact_tags_updated`), i tre eventi delle attività e il riepilogo giornaliero. Gli altri vengono inviati una sola volta, quindi per quelli l'interruttore non ha nulla su cui agire. Ogni evento contiene comunque `X-Webhook-Delivery`, quindi una regola di deduplicazione li copre tutti.

> **Attiva i tentativi solo se il tuo endpoint è idempotente.** I tentativi significano che lo stesso evento può arrivare più di una volta. Usa l'intestazione `X-Webhook-Delivery` per riconoscere una ripetizione: rimane invariata in ogni tentativo per lo stesso evento, così puoi ignorare in sicurezza un ID che hai già gestito.

I tentativi interagiscono con lo spegnimento automatico dopo ripetuti fallimenti (vedere [Affidabilità dei webhook](#webhook-reliability)) nel modo desiderato: il contatore dei fallimenti conta un'**intera consegna**, solo dopo che ogni tentativo è stato esaurito, non ogni singolo tentativo.

---

## Affidabilità dei webhook

- <span data-t="appName">Your AI Connector</span> invia webhook tramite una connessione sicura (HTTPS). Assicurati che l'indirizzo web fornito utilizzi HTTPS.
- Se il tuo sistema restituisce un errore, la consegna viene considerata non riuscita.
- Monitora l'uptime del tuo sistema ricevente per evitare di perdere eventi.
- Per flussi di lavoro critici, attiva [Riprovare le consegne non riuscite](#retrying-failed-deliveries) e considera anche un meccanismo di fallback.

> **I webhook vengono disattivati automaticamente dopo ripetuti errori.** Se l'URL del tuo webhook fallisce ripetutamente (circa 5 errori consecutivi, o 3 consecutivi per errori di configurazione), <span data-t="appName">Your AI Connector</span> smette automaticamente di inviare eventi a quell'URL. Per ripristinarlo una volta che l'endpoint è tornato operativo: modifica il webhook e salvalo con un URL diverso (qualsiasi modifica all'URL lo riabilita), oppure usa l'[endpoint di riabilitazione](../api/webhooks.md) tramite API; salvare nuovamente con lo stesso URL non è sufficiente. Anche il supporto può riabilitarlo per te.

---

## Risoluzione dei problemi

| Problema | Soluzione |
|---|---|
| Il webhook non si attiva | Per prima cosa, controlla che il webhook non sia **disattivato** nella sua riga. Quindi conferma che siano selezionati gli eventi corretti e che il tuo URL sia raggiungibile da Internet. |
| L'evento di test funziona ma gli eventi reali no | Assicurati che il tipo di evento specifico sia abilitato. Se ti aspettavi una richiesta quando viene applicato un tag, nota che `subscribed_to_tags` non limita gli eventi di un webhook a un tag: restringe solo quali tag producono una notifica di riepilogo della conversazione. Per ricevere una richiesta quando viene applicato un tag specifico, imposta un URL webhook su quel tag nella scheda **Tag** dell'agente (o della campagna): vedere [Webhook di aggiornamento tag contatto](#contact-tags-updated-webhook). |
| Non arriva nulla in n8n / Make / Zapier | Probabilmente stai utilizzando l'**URL di test** della piattaforma, che rimane in ascolto per un singolo evento subito dopo aver fatto clic su "Listen for test event". Per gli eventi live, salva l'**URL di produzione** e imposta il flusso di lavoro su **Attivo**. |
| Ricezione di eventi duplicati | Controlla la presenza di più webhook che puntano allo stesso URL. Se **Riprova consegne fallite** è attivo, è prevista una ripetizione ogni volta che il tuo endpoint ha accettato un evento ma non ha risposto in tempo: esegui la deduplicazione su `X-Webhook-Delivery`. |
| Il controllo della firma fallisce sempre | Quasi sempre perché il corpo è stato ri-serializzato prima del controllo. Verifica rispetto al corpo della richiesta **raw**, firma `<timestamp>.<body>` e conferma di utilizzare il segreto corrente se lo hai ruotato di recente. |
| I tentativi non avvengono | I tentativi sono disattivati a meno che non siano abilitati su quel webhook specifico. Non riproviamo le risposte 4xx. |
| Il blocco `campaign` è sempre `null` | Previsto se il tuo account utilizza agenti: i contatti risiedono presso un agente anziché una campagna. Leggi invece il blocco `agent`: vedere [Formato dati webhook](#webhook-data-format). |
| I dati sono vuoti o malformati | Verifica che il tuo sistema ricevente accetti JSON. Controlla i log del server per errori di analisi. |
| L'URL del webhook restituisce errori | Testa il tuo URL con uno strumento come Postman o [webhook.site](https://webhook.site). |
| Il webhook ha smesso di attivarsi completamente dopo un'interruzione | I fallimenti ripetuti disabilitano automaticamente un webhook. Salvare nuovamente non lo riabilita: correggi il tuo endpoint, quindi contatta l'assistenza. |
| Salva o Test restituisce un errore di autorizzazione | Hai bisogno dell'autorizzazione "modifica" per le Integrazioni. Chiedi al proprietario dell'account di concedertela. |
| L'elenco `subscribed_to_tags` di un webhook è tornato vuoto | `subscribed_to_tags` non limita gli eventi di un webhook a un tag: restringe solo quali tag producono una notifica di riepilogo della conversazione. La modifica dal modulo webhook non cancella più quell'elenco (corretto il 21 luglio 2026). Se un webhook ha perso il suo elenco prima di tale data, imposta nuovamente `subscribed_to_tags` tramite l'[API Webhook](../api/webhooks.md): vedere [Trigger webhook basati su tag](#tag-based-webhook-triggers). |

---

## Prossimi passi

- [Integrazione GoHighLevel](ghl-integration.md) — usa i webhook per integrare <span data-t="appName">Your AI Connector</span> con GHL.
- [Accesso API](api-access.md) — combina i webhook con l'API per automazioni potenti.
- [Utilizzo dei tag per etichettare i contatti](../get-started/creating-tags.md) — imposta tag che attivano i tuoi webhook.
