Audin Docs
API REST (partner)

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.

Scarica .md

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

StrumentoModelloQuando
Ingestion webhookTu 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 RESTTu chiami le risorse (/leads, /deals, …)Vuoi controllo fine sulle singole risorse, leggere e scrivere con gli id Audin, orchestrare flussi complessi lato tuo.
DatasourceAudin importa in bulkCarichi 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:

  1. Un token segreto per-Account nell'URL — l'endpoint è POST https://api.audin.ai/webhooks/ingest/<token>, dove <token> (formato aud_ing_…) è una credenziale dedicata all'ingestion.
  2. 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:

CampoTipoObbligatorioNote
idstringIdentificativo dell'evento lato tuo sistema. È la chiave di idempotency: ripetere un id già processato non riesegue l'azione.
typeenumTipo dell'evento (vedi tabella sotto).
occurred_atstring (ISO 8601)noIstante in cui l'evento è avvenuto nel tuo sistema. Solo per audit.
suppress_triggersbooleannoSe true, salta automazioni e assegnazioni (vedi Backfill). Default false.
dataobjectPayload 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

typeEntitàEffetto
lead/createdLeadCrea un nuovo lead. Fallisce se l'external_id esiste già.
lead/updatedLeadAggiorna un lead esistente. Fallisce se l'external_id non esiste.
deal/createdDealCrea un'opportunità, agganciandola al lead padre.
deal/updatedDealAggiorna un'opportunità esistente (campi e/o stage).
comment/createdCommentoAggiunge una nota a un lead o a un deal.

lead/created e lead/updated

Stesso schema data per entrambi:

CampoTipoObbligatorioNote
external_idstringIdentificativo del lead nel tuo sistema (chiave di match).
full_namestringnoNome completo.
emailstringnoEmail del lead.
phone_numberstringnoNumero in formato E.164 (es. +393334445566).
custom_paramsobjectnoCampi 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

CampoTipoObbligatorioNote
external_idstringIdentificativo del deal nel tuo sistema (chiave di match).
titlestringnoTitolo dell'opportunità.
amountnumbernoImporto.
currencystringnoValuta (es. EUR).
lead_external_idstringnoexternal_id del lead padre a cui agganciare il deal.
stage_idstring (UUID)noStage di destinazione per UUID. Vedi Risoluzione stage e owner.
stage_namestringnoStage per nome (in alternativa a stage_id).
owner_idstring (UUID)noAssegnatario per UUID.
owner_namestringnoAssegnatario per nome (in alternativa a owner_id).
custom_fieldsobjectnoCampi 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

CampoTipoObbligatorioNote
contentstringTesto del commento.
external_idstringnoIdentificativo del commento nel tuo sistema. Se presente, viene usato per la deduplica: ripetere lo stesso external_id non crea un doppione.
author_namestringnoNome dell'autore originale (conservato come metadato).
lead_external_idstringno*external_id del lead a cui agganciare il commento.
deal_external_idstringno*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:

CasoEsito
*/created con external_id nuovoCrea il record.
*/created con external_id già esistente409 already_exists.
*/updated con external_id esistenteAggiorna il record.
*/updated con external_id inesistente422 not_found.
deal/comment con padre (lead_external_id/deal_external_id) mancante422 parent_not_found.

Poiché deal e commenti si agganciano a un'entità padre, invia gli eventi in quest'ordine:

  1. lead/*
  2. deal/* (richiede il lead padre)
  3. 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
}
CampoValoriSignificato
statusprocessedL'evento è stato accettato.
entityLead | Deal | CommentEntità interessata.
idstringid Audin del record risultante.
outcomecreated | updated | noneEffetto applicato (none su una deduplica).
deduplicatedbooleantrue 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"
  }
}
codeHTTPSignificatoAzione
invalid_payload400Envelope o data non validi (campo mancante, type sconosciuto).Correggi il payload e ritenta. Lo message può indicare il campo.
401Header X-API-Key mancante o invalido.Verifica la chiave.
webhook_auth_failed403Token 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_exists409*/created su un external_id già esistente.Usa */updated, oppure ignora se è un replay.
not_found422*/updated su un external_id inesistente.Invia prima il */created corrispondente.
parent_not_found422Entità padre (lead/deal) non ancora presente in Audin.Invia prima l'evento del padre (rispetta l'ordine).
unresolved_reference422stage_name/owner_name ambiguo o non trovato.Usa l'UUID, o un nome univoco ed esistente.
internal500Errore 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

On this page