Integrazione DeepAgent → n8n → Go High Level

Integrazione Post-Call Webhook

Scritto da Product

Ultimo aggiornamento 29 giorni fa

Cosa copre questa guida:

  • Configurazione del post-call webhook in DeepAgent

  • Setup completo del workflow n8n con JSON importabile

  • Integrazione GHL API v2: contatti, pipeline, tag, note

  • Gestione errori, testing e deployment in produzione


1. Architettura dell'integrazione

L'integrazione segue un flusso lineare event-driven: quando una chiamata AI termina, DeepAgent invia un webhook POST a n8n, che elabora i dati e li sincronizza con Go High Level tramite API REST v2.

Flusso dei dati

DeepAgent              n8n Workflow                  Go High Level
    │                       │                               │
    │  POST-CALL WEBHOOK ──▶ [Webhook Trigger]              │
    │  (JSON payload)        │                               │
    │                   ├─ [Code] Estrarre dati              │
    │                   │                                    │
    │                   ├─ [HTTP] Cercare contatto ──▶ GET /contacts/search
    │                   │                                    │
    │                   ├─ [Switch] Esiste?                  │
    │                   │   ├─ SI → PATCH contatto  ▶ PATCH /contacts/{id}
    │                   │   └─ NO → Creare contatto ▶ POST /contacts/
    │                   │                                    │
    │                   ├─ [HTTP] Aggiungere nota ──▶ POST /contacts/{id}/notes
    │                   │                                    │
    │                   └─ [HTTP] Aggiungere tag  ──▶ PUT /contacts/{id}/tags

Azioni disponibili tramite n8n + GHL API

AzioneEndpoint GHL API v2

Creare/aggiornare contatti

POST /contacts/ | PATCH /contacts/{id}

Aggiungere a pipeline

POST /opportunities/

Prenotare appuntamenti

POST /calendars/events/appointments

Inviare SMS/email di follow-up

POST /conversations/messages

Aggiornare custom field

PATCH /contacts/{id}

Aggiungere tag post-chiamata

PUT /contacts/{id}/tags

Creare nota con riepilogo

POST /contacts/{id}/notes


2. Prerequisiti

2.1 Go High Level

  • Account GHL con accesso API v2 attivo

  • Private Integration Token (Settings → Integrations → Private Integrations → Create)

  • Location ID del sotto-account di riferimento

  • Pipeline ID e Stage ID (se vuoi creare opportunità)

  • Calendar ID (se vuoi prenotare appuntamenti)

  • Custom Field già creati nel sotto-account (opzionale)

⚠️ IMPORTANTE: API v2 + Version Header

GHL API v2 richiede SEMPRE l'header Version: 2021-07-28 in ogni richiesta. Senza questo header, le chiamate falliranno. La base URL è: https://services.leadconnectorhq.com

2.2 DeepAgent

  • Agente DeepAgent configurato e funzionante

  • Post-call webhook attivo sull'agente

  • Data Collection configurata nel prompt (call_summary, call_status, ecc.)

2.3 n8n

  • Istanza n8n attiva (self-hosted o cloud)

  • Webhook URL accessibile pubblicamente (HTTPS)

  • Credenziali HTTP Header Auth configurate per GHL


3. Configurazione di Go High Level

3.1 Creare il Private Integration Token

  1. Vai su Settings → Integrations → Private Integrations

  2. Clicca su "Create" e assegna un nome (es: "DeepAgent n8n Integration")

  3. Seleziona gli scope necessari:

    • contacts.readonly, contacts.write

    • opportunities.readonly, opportunities.write

    • calendars/events.write (per appuntamenti)

    • conversations/message.write (per SMS/email)

  4. Copia il token generato e conservalo in modo sicuro

Buona Pratica

Crea un token dedicato per l'integrazione n8n, non usare token condivisi con altre applicazioni. Questo permette di revocare l'accesso senza impattare altri sistemi.

3.2 Trovare il Location ID

Il Location ID è l'ID del sotto-account GHL. Lo trovi in:

  • Settings → Business Profile → l'URL contiene il location ID

  • Oppure via API: GET /locations/search

3.3 Preparare i Custom Field (opzionale)

Se vuoi salvare dati specifici della chiamata (es: risultato, sentimento, durata), crea i custom field in GHL prima:

  • Settings → Custom Fields → Add Field

  • Crea campi come: ai_call_outcome, ai_call_summary, ai_sentiment_score

  • Annota i field key (es: contact.ai_call_outcome)

4. Configurazione di DeepAgent

4.1 Attivare il Post-Call Webhook

  1. Vai al pannello DeepAgent → Conversational AI → il tuo agente

  2. Sezione "Post-call webhook" → attivare

  3. Inserisci l'URL del webhook n8n (la otterrai al passaggio 5)

Formato URL webhook n8n:

https://tuo-n8n.com/webhook/deepagent-ghl-response

4.2 Struttura del Payload Webhook

Quando la chiamata termina, DeepAgent invia un payload JSON con questa struttura:

{
  "callId": "call_01jz...",
  "agentId": "agent_01jz...",
  "phoneNumber": "+39321234567",
  "status": "completed",
  "callDuration": 180,
  "callTranscription": "Trascrizione completa...",
  "callSummary": "Riepilogo breve...",
  "sentimentScore": 8,
  "sentimentLabel": "positive",
  "additionalData": {
    "payload": {
      "metadata": {
        "dynamicVariables": {
          "user_name": "Marco",
          "user_email": "marco@example.com",
          "contact_id": "ghl_contact_id_se_disponibile"
        }
      }
    },
    "analysis": {
      "data_collection_results": {
        "call_summary": { "value": "..." },
        "call_status": { "value": "answered" },
        "appointment_date": { "value": "2026-02-15T15:00" }
      },
      "evaluation_criteria_results": {
        "success": { "result": "success" }
      }
    }
  }
}

4.3 Configurare la Data Collection

Nel prompt dell'agente DeepAgent, assicurati di avere i seguenti campi di data collection configurati:

CampoDescrizioneEsempio di Valore

call_status

Risultato della chiamata

answered, no-answer, busy

call_summary

Riepilogo max 200 char

"Cliente interessato a..."

user_need

Esigenza principale del lead

"Vuole demo del prodotto"

appointment_date

Data appuntamento (ISO)

2026-02-15T15:00

call_feedback

Feedback sulle performance

"Agente efficace..."


5. Workflow n8n — Configurazione Completa

Il workflow n8n è composto da 7 nodi principali. Di seguito la configurazione dettagliata di ogni nodo.

5.1 Nodo 1: Webhook Trigger

Riceve il payload post-call da DeepAgent.

Tipo: Webhook
Metodo: POST
Path: deepagent-ghl-response
Response Mode: Using 'Respond to Webhook' node

URL risultante:
  Test: https://tuo-n8n.com/webhook-test/deepagent-ghl-response
  Prod: https://tuo-n8n.com/webhook/deepagent-ghl-response

⚠️ URL di Test vs Produzione

Usa la Test URL durante lo sviluppo. Quando attivi il workflow, n8n passa automaticamente alla Production URL. Aggiorna l'URL nel pannello DeepAgent di conseguenza.

5.2 Nodo 2: Code — Estrarre Dati

Questo nodo JavaScript estrae tutti i dati rilevanti dal payload DeepAgent e li normalizza in un formato pulito per i nodi successivi.

// Code Node - "Estrarre Dati Chiamata"
// Mode: Run Once for All Items

const body = $input.first().json.body;
const analysis = body.additionalData?.analysis;
const dynVars = body.additionalData?.payload?.metadata?.dynamicVariables || {};
const dcr = analysis?.data_collection_results || {};

// Normalizzare telefono (rimuovere spazi, assicurare +)
let phone = (body.phoneNumber || dynVars.user_phone || '').replace(/\s/g, '');
if (phone && !phone.startsWith('+')) phone = '+' + phone;

return [{
  json: {
    // Dati della chiamata
    callId: body.callId,
    status: body.status || 'unknown',
    duration: body.callDuration || 0,
    sentimentScore: body.sentimentScore,
    sentimentLabel: body.sentimentLabel,
    transcript: body.callTranscription || '',

    // Dati dell'utente
    phone: phone,
    name: dynVars.user_name || '',
    lastName: dynVars.user_lastname || '',
    email: dynVars.user_email || '',
    company: dynVars.user_company || '',
    existingContactId: dynVars.contact_id || '',

    // Analisi AI
    summary: dcr.call_summary?.value || body.callSummary || 'Nessun riepilogo',
    callStatus: dcr.call_status?.value || body.status,
    userNeed: dcr.user_need?.value || '',
    appointmentDate: dcr.appointment_date?.value || '',
    feedback: dcr.call_feedback?.value || '',
    success: analysis?.evaluation_criteria_results?.success?.result === 'success',

    // Tag da assegnare
    tags: [
      'ai-called',
      `outcome-${dcr.call_status?.value || body.status}`,
      body.sentimentScore >= 7 ? 'hot-lead' :
        body.sentimentScore >= 4 ? 'warm-lead' : 'cold-lead'
    ].filter(Boolean),

    // Timestamp
    calledAt: new Date().toISOString()
  }
}];

5.3 Nodo 3: HTTP Request — Cercare Contatto GHL

Cerca il contatto in GHL tramite numero di telefono. Se il contatto esiste già, lo aggiorniamo; altrimenti ne creiamo uno nuovo.

Tipo: HTTP Request
Metodo: GET
URL: https://services.leadconnectorhq.com/contacts/search/duplicate

Headers:
  Authorization: Bearer {{ $credentials.ghlApiKey }}
  Version: 2021-07-28
  Content-Type: application/json

Query Parameters:
  locationId: YOUR_LOCATION_ID
  number: {{ $json.phone }}

Settings:
  Retry on Fail: true
  Max Retries: 3
  Wait Between Retries: 2000ms
  Continue on Fail: true  // Gestione 404

5.4 Nodo 4: IF — Contatto trovato?

Verifica se la ricerca ha restituito un contatto esistente.

Tipo: IF
Condizione: {{ $json.contact.id }} → is not empty

Output TRUE  → Nodo 5a (Aggiornare Contatto)
Output FALSE → Nodo 5b (Creare Contatto)

5.5a Nodo 5a: HTTP Request — Aggiornare Contatto Esistente

Tipo: HTTP Request
Metodo: PUT
URL: https://services.leadconnectorhq.com/contacts/{{ $('IF').item.json.contact.id }}

Headers:
  Authorization: Bearer {{ $credentials.ghlApiKey }}
  Version: 2021-07-28

Body (JSON):
{
  "tags": {{ JSON.stringify($('Estrarre Dati Chiamata').item.json.tags) }},
  "customFields": [
    { "key": "ai_call_outcome",
      "field_value": "{{ $('Estrarre Dati Chiamata').item.json.callStatus }}" },
    { "key": "ai_call_summary",
      "field_value": "{{ $('Estrarre Dati Chiamata').item.json.summary }}" },
    { "key": "ai_sentiment_score",
      "field_value": "{{ $('Estrarre Dati Chiamata').item.json.sentimentScore }}" },
    { "key": "ai_last_called",
      "field_value": "{{ $('Estrarre Dati Chiamata').item.json.calledAt }}" }
  ]
}

5.5b Nodo 5b: HTTP Request — Creare Nuovo Contatto

Tipo: HTTP Request
Metodo: POST
URL: https://services.leadconnectorhq.com/contacts/

Headers:
  Authorization: Bearer {{ $credentials.ghlApiKey }}
  Version: 2021-07-28

Body (JSON):
{
  "locationId": "YOUR_LOCATION_ID",
  "firstName": "{{ $('Estrarre Dati Chiamata').item.json.name }}",
  "lastName": "{{ $('Estrarre Dati Chiamata').item.json.lastName }}",
  "email": "{{ $('Estrarre Dati Chiamata').item.json.email }}",
  "phone": "{{ $('Estrarre Dati Chiamata').item.json.phone }}",
  "companyName": "{{ $('Estrarre Dati Chiamata').item.json.company }}",
  "tags": {{ JSON.stringify($('Estrarre Dati Chiamata').item.json.tags) }},
  "source": "DeepAgent AI Call",
  "customFields": [
    { "key": "ai_call_outcome",
      "field_value": "{{ $('Estrarre Dati Chiamata').item.json.callStatus }}" },
    { "key": "ai_call_summary",
      "field_value": "{{ $('Estrarre Dati Chiamata').item.json.summary }}" }
  ]
}

5.6 Nodo 6: Merge + HTTP Request — Creare Nota

Dopo aver creato o aggiornato il contatto, aggiungiamo una nota con il riepilogo della chiamata AI.

// Prima: Merge node per unire i due rami (SI/NO)
Tipo: Merge
Mode: Append

// Poi: HTTP Request - Creare Nota
Tipo: HTTP Request
Metodo: POST
URL: https://services.leadconnectorhq.com/contacts/{{ $json.contact.id }}/notes

Headers:
  Authorization: Bearer {{ $credentials.ghlApiKey }}
  Version: 2021-07-28

Body (JSON):
{
  "body": "🤖 Chiamata AI - {{ $('Estrarre Dati Chiamata').item.json.calledAt }}\n\n" +
    "Risultato: {{ $('Estrarre Dati Chiamata').item.json.callStatus }}\n" +
    "Durata: {{ Math.round($('Estrarre Dati Chiamata').item.json.duration/60) }} min\n" +
    "Sentimento: {{ $('Estrarre Dati Chiamata').item.json.sentimentLabel }} " +
    "({{ $('Estrarre Dati Chiamata').item.json.sentimentScore }}/10)\n\n" +
    "Riepilogo: {{ $('Estrarre Dati Chiamata').item.json.summary }}\n\n" +
    "Esigenza: {{ $('Estrarre Dati Chiamata').item.json.userNeed }}\n\n" +
    "Feedback: {{ $('Estrarre Dati Chiamata').item.json.feedback }}"
}

5.7 Nodo 7: Respond to Webhook

Risponde al webhook di DeepAgent con HTTP 200 per confermare la ricezione.

Tipo: Respond to Webhook
Response Code: 200

Response Body (JSON):
{
  "success": true,
  "message": "Call data synced to GHL",
  "contactId": "{{ $json.contact.id }}"
}

6. Configurazione delle Credenziali in n8n

6.1 Creare la Credenziale GHL

  1. In n8n, vai su Settings → Credentials → Add Credential

  2. Tipo: Header Auth

  3. Configura:

Name: GHL API v2
Header Name: Authorization
Header Value: Bearer YOUR_GHL_PRIVATE_INTEGRATION_TOKEN

// Aggiungi anche un header extra per la versione:
// In ogni nodo HTTP Request, aggiungi manualmente:
Header: Version = 2021-07-28

Alternativa: Credenziale Custom

Puoi creare una credenziale "Generic Credential Type" → "Header Auth" con due header: Authorization e Version. Questo evita di aggiungere il Version header manualmente in ogni nodo.


7. Estensioni Opzionali

7.1 Creare Opportunità nella Pipeline

Dopo aver creato/aggiornato il contatto, puoi aggiungere un'opportunità nella pipeline di GHL:

Metodo: POST
URL: https://services.leadconnectorhq.com/opportunities/

Body:
{
  "pipelineId": "YOUR_PIPELINE_ID",
  "locationId": "YOUR_LOCATION_ID",
  "name": "AI Call - {{ $json.name }} {{ $json.lastName }}",
  "stageId": "YOUR_STAGE_ID",
  "status": "open",
  "contactId": "{{ $json.contact.id }}",
  "monetaryValue": 0,
  "source": "DeepAgent"
}

7.2 Prenotare Appuntamento

Se l'agente AI ha raccolto una data di appuntamento:

// Aggiungi un IF node dopo il Code:
// Condizione: appointmentDate is not empty

Metodo: POST
URL: https://services.leadconnectorhq.com/calendars/events/appointments

Body:
{
  "calendarId": "YOUR_CALENDAR_ID",
  "locationId": "YOUR_LOCATION_ID",
  "contactId": "{{ $json.contact.id }}",
  "startTime": "{{ $json.appointmentDate }}",
  "endTime": "calculated_end_time",
  "title": "Appuntamento AI - {{ $json.name }}",
  "appointmentStatus": "confirmed"
}

7.3 Inviare SMS di Follow-up

Metodo: POST
URL: https://services.leadconnectorhq.com/conversations/messages

Body:
{
  "type": "SMS",
  "contactId": "{{ $json.contact.id }}",
  "message": "Ciao {{ $json.name }}, grazie per la chiamata! " +
    "Come abbiamo discusso, {{ $json.summary }}. A presto!"
}

8. Testing e Debug

8.1 Test con cURL

Simula un webhook post-call di DeepAgent per testare il workflow senza effettuare una chiamata reale:

curl -X POST https://tuo-n8n.com/webhook-test/deepagent-ghl-response \
  -H "Content-Type: application/json" \
  -d '{
  "callId": "test_call_001",
  "agentId": "agent_test",
  "phoneNumber": "+39321234567",
  "status": "completed",
  "callDuration": 120,
  "callTranscription": "Trascrizione di test...",
  "callSummary": "Riepilogo chiamata di prova",
  "sentimentScore": 8,
  "sentimentLabel": "positive",
  "additionalData": {
    "payload": {
      "metadata": {
        "dynamicVariables": {
          "user_name": "Marco",
          "user_lastname": "Rossi",
          "user_email": "marco.test@example.com"
        }
      }
    },
    "analysis": {
      "data_collection_results": {
        "call_summary": { "value": "Lead interessato al prodotto" },
        "call_status": { "value": "answered" },
        "user_need": { "value": "Demo del prodotto" }
      },
      "evaluation_criteria_results": {
        "success": { "result": "success" }
      }
    }
  }
}'

8.2 Checklist di Verifica

Verifica

Come verificare

Il webhook riceve i dati correttamente

Controllare execution log n8n

Il Code node estrae tutti i campi

Ispezionare l'output del nodo

La ricerca contatto GHL funziona

Verificare risposta HTTP 200

Contatto creato/aggiornato in GHL

Controllare in GHL Contacts

Tag applicati correttamente

Verificare i tag nel contatto

Custom field aggiornati

Aprire il contatto in GHL

Nota aggiunta al contatto

Sezione Notes in GHL

Il webhook risponde 200

Controllare la curl response

8.3 Debug dei Problemi Comuni

Problema

Causa

Probabile Soluzione

401 Unauthorized

Token non valido o scaduto

Rigenerare il Private Integration Token

422 Unprocessable

Manca il Version header

Aggiungere Version: 2021-07-28

400 Bad Request

locationId mancante

Aggiungere locationId nel body

Contatto duplicato

Ricerca per telefono fallita

Normalizzare il formato +39...

Tag non applicati

Formato tag errato

Passare un array di stringhe

Custom field vuoto

Key errata

Usare la key dalle impostazioni del field

Webhook timeout

n8n troppo lento nella risposta

Usare responseMode: lastNode


9. Deployment in Produzione

9.1 Checklist Pre-Deployment

  1. Testa il workflow almeno 5 volte con dati simulati via cURL

  2. Verifica che i contatti vengano creati/aggiornati correttamente in GHL

  3. Conferma che note e tag vengano assegnati correttamente

  4. Testa con una chiamata reale dall'agente DeepAgent

  5. Verifica la gestione degli errori (disconnetti GHL temporaneamente)

9.2 Attivazione

  1. In n8n, attiva il workflow (toggle ON)

  2. Copia la Production Webhook URL

  3. Aggiorna l'URL nel pannello DeepAgent → Post-call webhook

  4. Effettua una chiamata di prova e verifica il flusso end-to-end

9.3 Monitoraggio

Dopo il deployment, monitora:

  • n8n Execution History: verifica che non ci siano errori ricorrenti

  • Rate limits GHL: max 100 richieste per 10 secondi per app

  • Costi chiamate: traccia il campo metadata.cost per monitorare i costi

  • Volumi: se superi 200.000 API call/giorno su GHL, contatta il supporto

Raccomandazione Finale

Configura una notifica Slack/email nel workflow n8n per errori critici (nodo Error Trigger → Slack/Email). Questo ti permette di intervenire rapidamente in caso di problemi senza dover controllare manualmente l'execution history.


10. Riferimento Rapido — GHL API v2 Endpoints

Base URL: https://services.leadconnectorhq.com

Header richiesti in OGNI chiamata:

Authorization: Bearer YOUR_PRIVATE_INTEGRATION_TOKEN
Content-Type: application/json
Version: 2021-07-28

MetodoEndpointDescrizione

GET

/contacts/search/duplicate

Cercare contatto per telefono/email

POST

/contacts/

Creare nuovo contatto

PUT

/contacts/{id}

Aggiornare contatto (sovrascrive)

POST

/contacts/{id}/notes

Aggiungere nota al contatto

POST

/contacts/{id}/tags

Aggiungere tag al contatto

DELETE

/contacts/{id}/tags

Eliminare tag dal contatto

POST

/opportunities/

Creare opportunità nella pipeline

POST

/calendars/events/appointments

Creare appuntamento

POST

/conversations/messages

Inviare SMS/email

Documentazione ufficiale

  • GHL API v2: https://marketplace.gohighlevel.com/docs/