API dei Webhook
I webhook consentono alla piattaforma di notificare i tuoi altri sistemi nel momento in cui accade qualcosa: un nuovo contatto, una risposta, un appuntamento prenotato e altro ancora. Questa API gestisce le sottoscrizioni stesse: quali URL ricevono quali eventi. Per sapere come ricevere e verificare i payload che il tuo endpoint ottiene, consulta Webhook.
Tutti i percorsi seguenti sono relativi all’URL di base dell’API:
https://api.youraiconnector.com/v1
Ogni richiesta deve essere autenticata. Consulta Autenticazione per i quattro metodi accettati. Gli esempi qui utilizzano l’intestazione X-API-Key (e una forma di parametro di query per cURL).
Nota: I webhook devono essere abilitati per il tuo account. In caso contrario, questi endpoint restituiranno un 403.
Come vengono indirizzate le sottoscrizioni
Ogni sottoscrizione ha un id e un name opzionale. Entrambi possono essere utilizzati come {webhookId} nel percorso per aggiornare, eliminare, testare, verificare lo stato e riabilitare.
Preferisci il nome. Gli ID delle sottoscrizioni sono posizionali, quindi possono cambiare dopo l’eliminazione di un’altra sottoscrizione. Se imposti un
namestabile durante la creazione di una sottoscrizione, indirizzala tramite il nome per evitare sorprese.
Elenca le sottoscrizioni
GET /webhooks
cURL
curl "https://api.youraiconnector.com/v1/webhooks?apiKey=YOUR_API_KEY"
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/webhooks",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
Risposta
{
"success": true,
"webhooks": [
{
"id": "0",
"name": "Order updates hook",
"url": "https://hooks.example.com/incoming",
"subscribed_to": ["Contact Created", "Replies"],
"subscribed_to_tags": [],
"created_at": "2026-06-09T12:00:00.000Z",
"signing_enabled": true,
"signing_secret_created_at": "2026-07-15T09:30:00.000Z",
"retries_enabled": true,
"enabled": true,
"apply_to_sub_accounts": false
}
]
}
signing_enabled e retries_enabled sono opzioni attivabili per abbonamento, entrambe disattivate a meno che non vengano abilitate. Vedi Payload firmati e Tentativi di invio.
apply_to_sub_accounts è l’opzione di ereditarietà dell’agenzia: vedi Un unico abbonamento per tutti gli account cliente. Disattivata per impostazione predefinita e inerte sugli account che non hanno account cliente.
enabled è l’interruttore di accensione/spegnimento dell’abbonamento: vedi Disattivazione di un abbonamento. Gli abbonamenti disattivati rimangono elencati qui.
Il segreto di firma non viene mai incluso qui: leggilo da GET /webhooks/{id}/signing-secret.
Elenca i tipi di evento sottoscrivibili
Restituisce le stringhe esatte che puoi utilizzare in subscribed_to. Usalo per scoprire i nomi degli eventi validi invece di inserirli nel codice.
GET /webhooks/events
cURL
curl "https://api.youraiconnector.com/v1/webhooks/events" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/events", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/webhooks/events",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
Risposta
La risposta è {"success": true, "events": [...]}, dove events contiene attualmente 22 stringhe esatte: Contact Created, Human Alerted, Appointment Booked, Replies, Reads, Deliveries, Credits Spent, Credits Recharged, Low Credit Balance, Contact Paused, Contact Do Not Disturb, Contact Unarchived, New Message, Contact Resumed, Chat Concluded, Task Created, Task Updated, Task Completed, Daily Summary Created, Channel Connected, Broadcast Started e Broadcast Completed (Channel Connected è accettato in subscribed_to ma al momento non viene emesso da nulla, quindi non basare nulla su di esso).
Per il significato di ogni evento e il codice event inviato nel payload, vedi I 22 eventi webhook. Questo endpoint è l’elenco autorevole in ogni momento: leggilo in tempo reale invece di codificare i nomi in modo rigido.
Crea una sottoscrizione
POST /webhooks
| Campo | Obbligatorio | Descrizione |
|---|---|---|
url |
Sì | URL HTTPS che riceverà i payload degli eventi tramite POST. Deve essere raggiungibile pubblicamente. |
subscribed_to |
Sì | Un array non vuoto di nomi di eventi (vedi /webhooks/events). |
name |
No | Un nome visualizzato. Utilizzabile anche come {webhookId} in seguito. Per impostazione predefinita è un nome con timestamp. |
subscribed_to_tags |
No | ID dei tag che restringono quali tag producono una notifica di riepilogo della conversazione. Non limita gli eventi dell’abbonamento a tali tag: 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). |
retries_enabled |
No | Booleano, predefinito false. Consente di attivare i tentativi per le consegne non riuscite. |
generate_signing_secret |
No | Booleano, predefinito false. Crea un segreto di firma HMAC con l’abbonamento. Il segreto viene restituito una volta, come signing_secret di primo livello nella risposta. |
enabled |
No | Booleano, predefinito true. Passa false per creare l’abbonamento disattivato. Vedi Disattivazione di un abbonamento. |
apply_to_sub_accounts |
No | Booleano, predefinito false. Su un account agenzia, true fa sì che questo abbonamento riceva anche eventi da ogni account cliente: vedi Un unico abbonamento per tutti gli account cliente. |
Regole URL: L’URL deve utilizzare
https://ed essere raggiungibile pubblicamente.http://semplice,localhost, indirizzi di rete privata e indirizzi interni alla piattaforma vengono rifiutati con un400.
cURL
curl -X POST "https://api.youraiconnector.com/v1/webhooks?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.example.com/incoming",
"subscribed_to": ["Contact Created", "Replies"],
"name": "Order updates hook"
}'
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://hooks.example.com/incoming",
subscribed_to: ["Contact Created", "Replies"],
name: "Order updates hook",
}),
});
const data = await res.json();
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/webhooks",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"url": "https://hooks.example.com/incoming",
"subscribed_to": ["Contact Created", "Replies"],
"name": "Order updates hook",
},
)
data = res.json()
Risposta
{
"success": true,
"webhook_id": "1",
"webhook": {
"id": "1",
"name": "Order updates hook",
"url": "https://hooks.example.com/incoming",
"subscribed_to": ["Contact Created", "Replies"],
"subscribed_to_tags": [],
"created_at": "2026-06-09T12:00:00.000Z"
}
}
Aggiornare una sottoscrizione
Fornisci almeno uno tra url, subscribed_to, name, subscribed_to_tags, retries_enabled, enabled o apply_to_sub_accounts. I campi omessi mantengono i loro valori correnti. subscribed_to e subscribed_to_tags sono sostituzioni, non unioni.
PUT /webhooks/{webhookId}
L’aggiornamento di un abbonamento non altera mai il suo segreto di firma: gestiscilo tramite le rotte del segreto di firma.
Quando l’URL cambia, la consegna per il nuovo URL viene riabilitata automaticamente, offrendo a un endpoint precedentemente non funzionante un nuovo inizio.
cURL
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/Order%20updates%20hook" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.example.com/v2/incoming",
"subscribed_to": ["Replies", "Chat Concluded"]
}'
JavaScript
const res = await fetch(
`https://api.youraiconnector.com/v1/webhooks/${encodeURIComponent("Order updates hook")}`,
{
method: "PUT",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://hooks.example.com/v2/incoming",
subscribed_to: ["Replies", "Chat Concluded"],
}),
}
);
const data = await res.json();
Python
import requests
res = requests.put(
"https://api.youraiconnector.com/v1/webhooks/Order updates hook",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"url": "https://hooks.example.com/v2/incoming",
"subscribed_to": ["Replies", "Chat Concluded"],
},
)
data = res.json()
Risposta
{
"success": true,
"webhook_id": "0",
"webhook": {
"id": "0",
"name": "Order updates hook",
"url": "https://hooks.example.com/v2/incoming",
"subscribed_to": ["Replies", "Chat Concluded"],
"subscribed_to_tags": [],
"created_at": "2026-06-09T12:00:00.000Z"
}
}
Un ID o un nome sconosciuto restituisce 404 con { "success": false, "error": "Webhook not found" }.
Eliminare una sottoscrizione
Rimuove la sottoscrizione in modo che il suo URL smetta di ricevere payload. I suoi contatori di integrità della consegna vengono azzerati, quindi riaggiungere lo stesso URL in seguito inizierà con un record pulito.
DELETE /webhooks/{webhookId}
cURL
curl -X DELETE "https://api.youraiconnector.com/v1/webhooks/0" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0", {
method: "DELETE",
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.delete(
"https://api.youraiconnector.com/v1/webhooks/0",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
Risposta
{
"success": true
}
Inviare un payload di test
Invia un payload di esempio all’URL della sottoscrizione in modo da poter verificare il ricevitore end-to-end. Facoltativamente, passare un event per controllare quale tipo di evento il campione simula. Le consegne di test non influiscono mai sui contatori di integrità della sottoscrizione.
POST /webhooks/{webhookId}/test
La risposta restituisce sempre 200 e riporta l’esito con un flag delivered: un test fallito non restituisce uno stato di errore. Quando delivered è false, la risposta include i dettagli dell’errore.
| Campo | Obbligatorio | Descrizione |
|---|---|---|
event |
No | Tipo di evento da simulare (deve essere uno tra /webhooks/events). Il valore predefinito è un evento di consegna. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/test?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "event": "Contact Created" }'
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/test", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ event: "Contact Created" }),
});
const data = await res.json();
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/webhooks/0/test",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"event": "Contact Created"},
)
data = res.json()
Risposta (consegnata)
{
"success": true,
"webhook_id": "0",
"delivered": true
}
Risposta (fallita)
{
"success": true,
"webhook_id": "0",
"delivered": false,
"failure_type": "permanent",
"status_code": 404,
"error_message": "Request failed with status code 404"
}
failure_type è uno tra permanent, temporary, timeout, network o unknown.
Verifica lo stato della consegna
Restituisce il record dello stato della consegna per l’URL della sottoscrizione: quante consegne sono riuscite e quante sono fallite, se la consegna è attualmente in pausa dopo ripetuti errori e i dettagli dell’ultimo errore. Restituisce "health": null quando non è ancora stato tentato alcun invio.
GET /webhooks/{webhookId}/health
cURL
curl "https://api.youraiconnector.com/v1/webhooks/0/health" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/health", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/webhooks/0/health",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
Risposta
{
"success": true,
"webhook_id": "0",
"url": "https://hooks.example.com/incoming",
"health": {
"consecutive_failures": 0,
"total_failures": 2,
"total_successes": 120,
"is_disabled": false,
"disabled_at": null,
"disabled_reason": null,
"last_failure": null,
"last_success_at": "2026-06-09T12:00:00.000Z",
"created_at": "2026-05-01T08:00:00.000Z",
"updated_at": "2026-06-09T12:00:00.000Z"
}
}
Quando is_disabled è true, la consegna all’URL è stata sospesa automaticamente dopo ripetuti errori. Correggi il tuo ricevitore, quindi riabilitalo (qui sotto).
Riabilita la consegna
Riprende la consegna per un webhook il cui URL è stato sospeso automaticamente dopo ripetuti errori. Questo resetta il flag di sospensione e i contatori degli errori, ma non tenta una consegna: utilizza l’endpoint di test in seguito per confermare che il tuo ricevitore sia di nuovo funzionante.
POST /webhooks/{webhookId}/reenable
cURL
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/reenable?apiKey=YOUR_API_KEY"
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/reenable", {
method: "POST",
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/webhooks/0/reenable",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
Risposta
{
"success": true,
"webhook_id": "0"
}
Disattivazione di un abbonamento
enabled è l’interruttore di accensione/spegnimento dell’abbonamento. Disattivarlo interrompe le consegne mantenendo intatti l’URL, l’elenco degli eventi e il segreto di firma.
# Off
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"enabled": false}'
# Back on
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'
- L’assenza indica che è attivo. Un abbonamento creato prima dell’esistenza di questo campo non ha alcun valore
enabledmemorizzato e viene consegnato normalmente.GET /webhooksriporta sempre un booleano concreto. - Gli abbonamenti disattivati sono ancora elencati da
GET /webhooks: è così che li trovi per riattivarli. - Un tentativo in coda prima della disattivazione non riprende: il tentativo rilegge l’abbonamento al momento dell’invio e viene eliminato se è disattivato.
- Nulla di ciò che è stato soppresso durante la disattivazione viene riprodotto quando lo riattivi.
Distinto dalla disattivazione automatica dopo ripetuti errori, che viene segnalata da
GET /webhooks/{id}/healthcomeis_disablede cancellata conPOST /webhooks/{id}/reenable.enabledè l’interruttore dell’account;is_disabledè il nostro. Nessuno dei due prevale sull’altro: un abbonamento deve essere sia attivo che non disattivato automaticamente per essere consegnato.
Un unico abbonamento per tutti gli account cliente (agenzie)
Su un account agenzia, imposta apply_to_sub_accounts: true su un abbonamento (al momento della creazione o tramite PUT) e questo riceverà anche gli eventi che si verificano su ognuno degli account cliente dell’agenzia: un unico endpoint copre l’intera agenzia, invece di dover ricreare l’abbonamento su ogni account cliente.
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"apply_to_sub_accounts": true}'
Come funziona:
- Il blocco
userdistingue gli account. Il bloccouserdi ogni payload identifica l’account su cui si è effettivamente verificato l’evento, in modo che il ricevitore possa instradare per cliente. - Le impostazioni dell’abbonamento dell’agenzia si applicano ovunque. Il suo elenco di eventi, il segreto di firma e l’opzione di riprova vengono utilizzati anche per le consegne ereditate.
- L’abbonamento dell’account cliente allo stesso URL ha la precedenza. Se un account cliente ha il proprio abbonamento che punta allo stesso URL, quello viene utilizzato per gli eventi di tale account: lo stesso evento non viene mai consegnato due volte allo stesso endpoint.
- Gli account cliente non lo vedono. Gli abbonamenti ereditati non compaiono nell’elenco webhook dell’account cliente e il cliente non può disattivarli: solo l’agenzia li gestisce.
- L’integrità della consegna viene monitorata per account cliente. Un endpoint che continua a fallire viene disabilitato automaticamente per l’account le cui consegne non sono riuscite, non per l’intera agenzia.
subscribed_to_tagsnon viene ereditato. L’elenco dei tag fa riferimento ai tag dell’agenzia, che non esistono sugli account cliente: la restrizione del riepilogo della conversazione si applica solo agli eventi dell’agenzia.- Inerte altrove. Su un account senza account cliente, il flag viene memorizzato correttamente ma non esegue alcuna azione.
Intestazioni su ogni consegna
Queste tre intestazioni vengono inviate su ogni consegna, indipendentemente dal fatto che la sottoscrizione sia firmata o meno:
| Intestazione | Significato |
|---|---|
X-Webhook-Delivery |
ID stabile per l’evento logico. Identico tra i tentativi: usalo per la deduplicazione. |
X-Webhook-Attempt |
Numero del tentativo (basato su 1). |
X-Webhook-Event |
Il nome dell’evento. |
Payload firmati
La firma è facoltativa, disattivata per impostazione predefinita e impostata per ogni sottoscrizione. Quando una sottoscrizione ha un segreto di firma, ogni consegna include due intestazioni aggiuntive oltre alle tre inviate su ogni consegna (X-Webhook-Delivery, X-Webhook-Attempt e X-Webhook-Event):
| Intestazione | Significato |
|---|---|
X-Webhook-Signature |
v1=<hex>: HMAC-SHA256 della stringa "<timestamp>.<raw request body>", codificata con il segreto di firma per webhook che crei e ruoti su GET/POST/DELETE /v1/webhooks/{webhookId}/signing-secret. |
X-Webhook-Timestamp |
Ora di invio, in secondi Unix. Vincolata alla firma, quindi non può essere alterata indipendentemente. |
Per verificare, ricalcola l’HMAC-SHA256 sul corpo grezzo (raw body) con il tuo segreto e confrontalo con l’intestazione. Verifica rispetto al corpo della richiesta grezzo. La riesecuzione della serializzazione del JSON analizzato modifica i byte e interrompe il confronto. Rifiuta le consegne il cui timestamp è al di fuori di una finestra di freschezza (300 secondi è un valore predefinito ragionevole) per prevenire il replay e confronta con una funzione a tempo costante (timing-safe).
Vedi Payload firmati per esempi completi di verifica in Node e Python.
La firma non è la stessa cosa dell’autenticazione API. L’API REST stessa si autentica con chiavi API anziché con OAuth (OAuth 2.1 esiste per i server MCP che registri come strumenti bot) e non esistono ancora pacchetti SDK ufficiali per npm o PyPI: chiama gli endpoint con qualsiasi client HTTP.
Leggi il segreto di firma
GET /webhooks/{id}/signing-secret
curl "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
Risposta
{
"success": true,
"webhook_id": "0",
"signing_enabled": true,
"signing_secret": "whsec_1a2b3c...",
"signing_secret_created_at": "2026-07-15T09:30:00.000Z"
}
Quando la firma è disattivata, signing_enabled è false e signing_secret è null.
Genera o ruota il segreto di firma
POST /webhooks/{id}/signing-secret
Crea un segreto (attivando la firma) o sostituisce quello esistente. Restituisce il nuovo segreto.
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
Risposta
{
"success": true,
"webhook_id": "0",
"signing_enabled": true,
"signing_secret": "whsec_9f8e7d...",
"signing_secret_created_at": "2026-07-15T10:00:00.000Z"
}
La rotazione ha effetto immediato: la consegna successiva viene firmata solo con il nuovo segreto. Accetta brevemente entrambi i segreti mentre distribuisci la modifica a un endpoint attivo.
Puoi anche generare un segreto al momento della creazione passando "generate_signing_secret": true a POST /webhooks; la risposta includerà quindi un campo signing_secret di primo livello.
Disattiva la firma
DELETE /webhooks/{id}/signing-secret
curl -X DELETE "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
Risposta
{
"success": true,
"webhook_id": "0",
"signing_enabled": false
}
Tutte e tre le rotte per il segreto di firma richiedono l’autorizzazione edit per le integrazioni, incluso
GET: il segreto è una credenziale che può falsificare le consegne, quindi non viene esposto ai ruoli di sola lettura.
Riprova
Opzionale, disattivato per impostazione predefinita e impostato per sottoscrizione tramite il booleano retries_enabled su POST /webhooks o PUT /webhooks/{id}.
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"retries_enabled": true}'
Quando abilitata, una consegna fallita viene riprovata a 1m, 5m, 30m e 2h dopo il primo tentativo (circa 2h40m di copertura).
- Riprovato: risposte 5xx, timeout e errori di connessione.
- Non riprovato: qualsiasi 4xx. Il ricevente sta rifiutando la richiesta stessa, quindi riprodurla invariata non farebbe altro che riprodurre il rifiuto.
I tentativi rendono possibile la consegna duplicata: un endpoint che ha elaborato un evento ma è andato in timeout prima di rispondere lo vedrà di nuovo. Esegui la deduplicazione su X-Webhook-Delivery, che è costante tra i tentativi. Ecco perché i tentativi sono opzionali.
I contatori delivery-health conteggiano un’intera consegna, non ogni tentativo: un errore viene registrato solo una volta esauriti tutti i tentativi, quindi abilitare le riprove non fa scattare prima la disabilitazione automatica.
Errori
Tutti gli errori utilizzano il formato standard:
{
"success": false,
"error": "Webhook not found"
}
Casi comuni: un URL non consentito, un subscribed_to vuoto/non valido o campi mancanti restituiscono 400; un ID o un nome sconosciuto restituisce 404; e un 403 indica che i webhook non sono abilitati per il tuo account. Consulta Errori per l’elenco completo.
Passaggi successivi
- Webhooks (ricezione dei payload) — configura il tuo ricevitore e comprendi la struttura del payload.
- Autenticazione — i quattro modi per autenticare una richiesta.
- Errori e limiti di frequenza — codici di stato e il limite di 300 richieste/min.