Ingestion webhook
Spingi lead, deal e commenti dal tuo sistema verso Audin con un singolo endpoint tipizzato e idempotente — upsert per external_id, ereditando automazioni e assegnazioni.
Versione Markdown di questa pagina
Scarica o copia il contenuto di questa pagina in formato .md — utile per fornirlo a un agente AI che integra questa specifica feature.
L'ingestion webhook è un singolo endpoint che riceve eventi tipizzati dal
tuo sistema (lead/created, deal/updated, …) e li scrive nel CRM Audin,
ereditando gli stessi effetti delle scritture native: automazioni (workflow),
assegnazione del lead, storico delle modifiche. Ogni evento porta un tuo
identificativo (external_id) con cui Audin fa upsert: lo stesso record nel
tuo sistema corrisponde sempre allo stesso record in Audin.
Quando usarlo
| Strumento | Modello | Quando |
|---|---|---|
| Ingestion webhook | Tu spingi eventi tipizzati (push) | Hai già un sistema sorgente (gestionale, form, altro CRM) e vuoi mantenerlo allineato ad Audin per external_id, lasciando ad Audin il match e gli effetti collaterali. |
| API REST | Tu chiami le risorse (/leads, /deals, …) | Vuoi controllo fine sulle singole risorse, leggere e scrivere con gli id Audin, orchestrare flussi complessi lato tuo. |
| Datasource | Audin importa in bulk | Carichi periodicamente liste/file (es. import CSV) senza una semantica evento-per-evento. |
L'ingestion webhook è la scelta giusta quando la fonte di verità è il tuo sistema e vuoi un canale unico, idempotente e tipizzato per riversare i cambiamenti in Audin.
Ogni chiamata all'ingestion webhook viene registrata e resta consultabile nella sezione Sviluppatori del dashboard: payload ricevuto, esito, eventuale errore e record Audin risultante. È il posto dove diagnosticare un evento rifiutato.
Autenticazione
L'ingestion webhook richiede due fattori, entrambi appartenenti allo stesso Account:
- Un token segreto per-Account nell'URL — l'endpoint è
POST https://api.audin.ai/webhooks/ingest/<token>, dove<token>(formatoaud_ing_…) è una credenziale dedicata all'ingestion. - L'Account API Key nell'header
X-API-Key(la stessa usata da tutta l'API REST partner, vedi Autenticazione).
Se il token e l'API Key non si riferiscono allo stesso Account — o il token è
mancante/errato — la richiesta viene rifiutata con 403 webhook_auth_failed.
Le scritture che richiedono un riferimento a un utente (es. createdBy,
ownerId) sono risolte automaticamente sull'owner dell'Account.
curl -X POST https://api.audin.ai/webhooks/ingest/<token> \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{ "id": "evt_001", "type": "lead/created", "data": { "external_id": "L-42" } }'Il token di ingestion
Il token (aud_ing_…) è un segreto: chi lo possiede insieme all'API Key può
scrivere nel tuo CRM. Trattalo come una credenziale — non condividerlo, non
inserirlo in URL pubblici o log, conservalo in modo sicuro lato server.
- Ottenerlo / consultarlo: dalla pagina Sviluppatori → Webhook di ingestion del dashboard. L'URL completo (token incluso) è ora sempre visibile e copiabile da quella pagina: non è più mostrato una sola volta alla generazione, puoi recuperarlo in qualsiasi momento. Resta comunque un segreto: trattalo come una credenziale.
- Rotazione: rigenerare il token invalida immediatamente l'URL precedente. Aggiorna il sistema sorgente con il nuovo URL prima — o subito dopo — la rigenerazione per evitare interruzioni.
Envelope dell'evento
Ogni richiesta è un singolo evento (non un batch) con questa struttura:
| Campo | Tipo | Obbligatorio | Note |
|---|---|---|---|
id | string | sì | Identificativo dell'evento lato tuo sistema. È la chiave di idempotency: ripetere un id già processato non riesegue l'azione. |
type | enum | sì | Tipo dell'evento (vedi tabella sotto). |
occurred_at | string (ISO 8601) | no | Istante in cui l'evento è avvenuto nel tuo sistema. Solo per audit. |
suppress_triggers | boolean | no | Se true, salta automazioni e assegnazioni (vedi Backfill). Default false. |
data | object | sì | Payload specifico per type (schema sotto). |
{
"id": "evt_8f3a",
"type": "lead/updated",
"occurred_at": "2026-06-16T10:00:00Z",
"suppress_triggers": false,
"data": {
"external_id": "L-42",
"email": "mario@acme.example.com"
}
}In alternativa al campo suppress_triggers puoi usare l'header
X-Suppress-Triggers: true. I due meccanismi sono equivalenti: se uno dei due
è attivo, le automazioni vengono saltate.
Tipi di evento
type | Entità | Effetto |
|---|---|---|
lead/created | Lead | Crea un nuovo lead. Fallisce se l'external_id esiste già. |
lead/updated | Lead | Aggiorna un lead esistente. Fallisce se l'external_id non esiste. |
deal/created | Deal | Crea un'opportunità, agganciandola al lead padre. |
deal/updated | Deal | Aggiorna un'opportunità esistente (campi e/o stage). |
comment/created | Commento | Aggiunge una nota a un lead o a un deal. |
lead/created e lead/updated
Stesso schema data per entrambi:
| Campo | Tipo | Obbligatorio | Note |
|---|---|---|---|
external_id | string | sì | Identificativo del lead nel tuo sistema (chiave di match). |
full_name | string | no | Nome completo. |
email | string | no | Email del lead. |
phone_number | string | no | Numero in formato E.164 (es. +393334445566). |
custom_params | object | no | Campi personalizzati liberi (coppie chiave/valore). |
{
"id": "evt_lead_1",
"type": "lead/created",
"data": {
"external_id": "L-42",
"full_name": "Mario Rossi",
"email": "mario@acme.example.com",
"phone_number": "+393334445566",
"custom_params": { "origine": "fiera-2026", "interesse": "impianti" }
}
}deal/created e deal/updated
| Campo | Tipo | Obbligatorio | Note |
|---|---|---|---|
external_id | string | sì | Identificativo del deal nel tuo sistema (chiave di match). |
title | string | no | Titolo dell'opportunità. |
amount | number | no | Importo. |
currency | string | no | Valuta (es. EUR). |
lead_external_id | string | no | external_id del lead padre a cui agganciare il deal. |
stage_id | string (UUID) | no | Stage di destinazione per UUID. Vedi Risoluzione stage e owner. |
stage_name | string | no | Stage per nome (in alternativa a stage_id). |
owner_id | string (UUID) | no | Assegnatario per UUID. |
owner_name | string | no | Assegnatario per nome (in alternativa a owner_id). |
custom_fields | object | no | Campi personalizzati liberi. |
{
"id": "evt_deal_1",
"type": "deal/created",
"data": {
"external_id": "D-77",
"title": "Preventivo impianto",
"amount": 3500,
"currency": "EUR",
"lead_external_id": "L-42",
"stage_name": "Nuovo",
"owner_name": "Giulia Bianchi"
}
}Il deal si aggancia al lead padre tramite lead_external_id (l'external_id
del lead, non un id Audin). Se il lead padre non è ancora presente in
Audin, l'evento viene rifiutato: invia prima l'evento lead/* corrispondente
(vedi Ordine consigliato).
comment/created
| Campo | Tipo | Obbligatorio | Note |
|---|---|---|---|
content | string | sì | Testo del commento. |
external_id | string | no | Identificativo del commento nel tuo sistema. Se presente, viene usato per la deduplica: ripetere lo stesso external_id non crea un doppione. |
author_name | string | no | Nome dell'autore originale (conservato come metadato). |
lead_external_id | string | no* | external_id del lead a cui agganciare il commento. |
deal_external_id | string | no* | external_id del deal a cui agganciare il commento. |
* Un commento richiede esattamente uno tra lead_external_id e
deal_external_id. L'entità padre indicata deve già esistere in Audin.
{
"id": "evt_comment_1",
"type": "comment/created",
"data": {
"external_id": "C-9",
"content": "Il cliente preferisce essere richiamato di pomeriggio.",
"author_name": "Reception",
"lead_external_id": "L-42"
}
}Risoluzione stage e owner
Per i deal puoi indicare stage e assegnatario in due modi, mai con un default silenzioso:
- Per UUID (
stage_id/owner_id) — autoritativo. È l'identificativo esatto della risorsa Audin. - Per nome (
stage_name/owner_name) — Audin risolve il nome all'interno del tuo Account.
Se un nome è ambiguo (più corrispondenze) o non trovato, l'evento viene
rifiutato con un errore esplicito (unresolved_reference): non viene mai
applicato un valore di ripiego.
Gli stage delle pipeline e gli operatori del tuo Account sono visibili nel
dashboard. Gli UUID corrispondenti si recuperano via API REST con
GET /pipelines (stage di una pipeline) e GET /platform-users (operatori) —
vedi Lettura & sistema e
Pipeline & deal.
Se ometti sia stage_id sia stage_name per un deal/created, il deal entra
nello stage iniziale della pipeline di vendita di default dell'Account.
Ordine e semantica
La semantica created / updated è stretta sull'external_id:
| Caso | Esito |
|---|---|
*/created con external_id nuovo | Crea il record. |
*/created con external_id già esistente | 409 already_exists. |
*/updated con external_id esistente | Aggiorna il record. |
*/updated con external_id inesistente | 422 not_found. |
deal/comment con padre (lead_external_id/deal_external_id) mancante | 422 parent_not_found. |
Poiché deal e commenti si agganciano a un'entità padre, invia gli eventi in quest'ordine:
lead/*deal/*(richiede il lead padre)comment/*(richiede il lead o il deal padre)
Idempotency & retry
L'id dell'envelope è la chiave di idempotency, per Account:
- Se un evento con lo stesso
idè già stato processato con successo, Audin non riesegue l'azione e risponde con lo stesso esito, marcato"deduplicated": true. - Un evento fallito può essere ritentato con lo stesso
id: alla riuscita verrà processato normalmente.
Questo rende sicuro il retry su timeout o errore di rete: usa sempre lo stesso
id per lo stesso evento sorgente.
Backfill
Per importazioni storiche (backfill) imposta suppress_triggers: true (o
l'header X-Suppress-Triggers: true): gli eventi vengono scritti senza
attivare automazioni né assegnazioni automatiche. Utile per ricaricare uno
storico senza generare notifiche, chiamate o workflow indesiderati.
curl -X POST https://api.audin.ai/webhooks/ingest/<token> \
-H "X-API-Key: $API_KEY" \
-H "X-Suppress-Triggers: true" \
-H "Content-Type: application/json" \
-d '{ "id": "backfill_001", "type": "lead/created", "data": { "external_id": "L-1001" } }'Risposta
In caso di successo l'endpoint risponde 200 con il riepilogo dell'evento
processato:
{
"status": "processed",
"entity": "Lead",
"id": "9b1c2d3e-…",
"outcome": "created",
"deduplicated": false
}| Campo | Valori | Significato |
|---|---|---|
status | processed | L'evento è stato accettato. |
entity | Lead | Deal | Comment | Entità interessata. |
id | string | id Audin del record risultante. |
outcome | created | updated | none | Effetto applicato (none su una deduplica). |
deduplicated | boolean | true se l'evento era già stato processato (nessuna ri-esecuzione). |
Codici di errore
Gli errori dell'ingestion webhook usano l'envelope con code/message
(la stessa forma delle rotte autenticate con API Key):
{
"success": false,
"error": {
"code": "unresolved_reference",
"message": "Stage \"Nuovo\" non trovato"
}
}code | HTTP | Significato | Azione |
|---|---|---|---|
invalid_payload | 400 | Envelope o data non validi (campo mancante, type sconosciuto). | Correggi il payload e ritenta. Lo message può indicare il campo. |
| — | 401 | Header X-API-Key mancante o invalido. | Verifica la chiave. |
webhook_auth_failed | 403 | Token nell'URL mancante/errato, oppure token e X-API-Key non riferiti allo stesso Account. | Verifica di usare l'URL corretto (con il token aggiornato) e l'API Key dello stesso Account. Se hai rigenerato il token, aggiorna l'URL. |
already_exists | 409 | */created su un external_id già esistente. | Usa */updated, oppure ignora se è un replay. |
not_found | 422 | */updated su un external_id inesistente. | Invia prima il */created corrispondente. |
parent_not_found | 422 | Entità padre (lead/deal) non ancora presente in Audin. | Invia prima l'evento del padre (rispetta l'ordine). |
unresolved_reference | 422 | stage_name/owner_name ambiguo o non trovato. | Usa l'UUID, o un nome univoco ed esistente. |
internal | 500 | Errore interno. | Ritenta con backoff esponenziale (stesso id). |
Lo status code è la fonte di verità per la logica di retry: i 4xx
(eccetto 429) non sono ritentabili senza correggere la richiesta; i 5xx
sono ritentabili con backoff. Ogni esito è comunque tracciato nella sezione
Sviluppatori del dashboard.
Esempio end-to-end
Riversa un lead, la sua opportunità e una nota — nell'ordine corretto:
# 1. Lead
curl -X POST https://api.audin.ai/webhooks/ingest/<token> \
-H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
-d '{
"id": "evt_l_1",
"type": "lead/created",
"data": {
"external_id": "L-42",
"full_name": "Mario Rossi",
"email": "mario@acme.example.com",
"phone_number": "+393334445566"
}
}'
# 2. Deal agganciato al lead via lead_external_id
curl -X POST https://api.audin.ai/webhooks/ingest/<token> \
-H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
-d '{
"id": "evt_d_1",
"type": "deal/created",
"data": {
"external_id": "D-77",
"title": "Preventivo impianto",
"amount": 3500,
"currency": "EUR",
"lead_external_id": "L-42",
"stage_name": "Nuovo"
}
}'
# 3. Commento sul lead
curl -X POST https://api.audin.ai/webhooks/ingest/<token> \
-H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
-d '{
"id": "evt_c_1",
"type": "comment/created",
"data": {
"external_id": "C-9",
"content": "Richiamare di pomeriggio.",
"author_name": "Reception",
"lead_external_id": "L-42"
}
}'// L'URL contiene il token segreto per-Account (aud_ing_…) ottenuto dalla
// pagina "Sviluppatori → Webhook di ingestion": tienilo lato server.
const INGEST_URL = process.env.AUDIN_INGEST_WEBHOOK_URL; // …/webhooks/ingest/aud_ing_…
const ingest = (event) =>
fetch(INGEST_URL, {
method: "POST",
headers: {
"X-API-Key": process.env.AUDIN_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify(event),
}).then((r) => r.json());
// 1. Lead → 2. Deal → 3. Commento (l'ordine conta: deal e commento
// richiedono che il padre esista già).
await ingest({
id: "evt_l_1",
type: "lead/created",
data: {
external_id: "L-42",
full_name: "Mario Rossi",
email: "mario@acme.example.com",
phone_number: "+393334445566",
},
});
await ingest({
id: "evt_d_1",
type: "deal/created",
data: {
external_id: "D-77",
title: "Preventivo impianto",
amount: 3500,
currency: "EUR",
lead_external_id: "L-42",
stage_name: "Nuovo",
},
});
await ingest({
id: "evt_c_1",
type: "comment/created",
data: {
external_id: "C-9",
content: "Richiamare di pomeriggio.",
author_name: "Reception",
lead_external_id: "L-42",
},
});Prossimo passo
Pipeline & deal
Pipeline e stage, deal con righe prodotto e termini di pagamento, attività e relativi template — la parte operativa del CRM Audin.
Outbound Webhooks
Ricevi notifiche in tempo reale quando un lead viene creato, aggiornato o eliminato in Audin — eventi firmati HMAC, consegnati con retry durabile verso i tuoi endpoint HTTPS.