{
  "id": "QMMhXuo8wRplcxJr",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Summarize sales calls into GoHighLevel notes with Deepgram, Gemini, and Sheets",
  "tags": [],
  "nodes": [
    {
      "id": "57761cef-9015-4cc9-bab7-dcbfc3807f1b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3408,
        1104
      ],
      "parameters": {
        "width": 480,
        "height": 768,
        "content": "## Summarize sales calls into GoHighLevel notes with Deepgram, Gemini, and Sheets\n\n### How it works\n\n1. The workflow triggers via a webhook and verifies if the contact exists in GoHighLevel (GHL).\n2. It processes binary data to obtain a transcript and fetches specific user notes from GHL.\n3. An LLM analyzes the gathered information to generate an appropriate response.\n4. The execution results are logged in a Google Sheet for record-keeping.\n5. A final response is sent back to the originating webhook.\n\n### Setup steps\n\n- - [ ] Configure the Webhook trigger URL in your external application.\n- - [ ] Provide valid API credentials for GoHighLevel (LeadConnector).\n- - [ ] Set up the Deepgram API key for transcription services.\n- - [ ] Connect your Google account to access the designated Sheets document.\n- - [ ] Configure the Google Gemini Chat Model credentials.\n\n### Customization\n\nYou can modify the system prompt within the Gemini node to change the tone or format of the generated response."
      },
      "typeVersion": 1
    },
    {
      "id": "db089cee-69d1-4b09-896e-903e2988e45d",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3968,
        1280
      ],
      "parameters": {
        "color": 7,
        "width": 864,
        "height": 288,
        "content": "## Webhook and contact verification\n\nHandles the incoming webhook request and performs initial contact verification in GHL."
      },
      "typeVersion": 1
    },
    {
      "id": "f814ee74-1ab4-474c-8699-4eec16bac94f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4864,
        1248
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 320,
        "content": "## Transcribe and retrieve notes\n\nProcesses the input binary file to get a transcript and retrieves relevant user notes."
      },
      "typeVersion": 1
    },
    {
      "id": "8060414f-4f22-4d70-a3b7-772904cb011a",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5536,
        1232
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 528,
        "content": "## Process notes via LLM\n\nEvaluates the data and generates a response using the Gemini LLM."
      },
      "typeVersion": 1
    },
    {
      "id": "02317c9c-fb3f-4dd8-b675-2151faa1e2f9",
      "name": "When Webhook Received",
      "type": "n8n-nodes-base.webhook",
      "position": [
        4016,
        1408
      ],
      "parameters": {
        "path": "68760bea-9d0c-4f17-8045-68c7ff55c597",
        "options": {
          "rawBody": false
        },
        "httpMethod": "POST",
        "responseMode": "responseNode",
        "authentication": "headerAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "f1925889-0bd3-484c-8d3b-5245ae7e733f",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        6560,
        1376
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.5
    },
    {
      "id": "d1370c7b-cb20-4b8a-bf76-6797ffdfcc01",
      "name": "Generate LLM Response",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        5648,
        1376
      ],
      "parameters": {
        "text": "=User Previous Notes:\n{{ \n  ($('Fetch User Notes').item.json.notes && $('Fetch User Notes').item.json.notes[0]?.id && $('Fetch User Notes').item.json.notes[0]?.dateAdded) \n    ? ($('Fetch User Notes').item.json.notes\n        .filter(note => note.dateAdded >= $now.minus({ days: 30 }).toISO())\n        .map(note => `[${note.dateAdded.substring(0, 10)}] ${note.bodyText}`)\n        .join('\\n\\n') || \"there are no previous notes for this Contact\")\n    : \"there are no previous notes for this Contact\"\n}}\n\nTranscript:\n{{ $('Transcribe Audio via Deepgram').item.json.body.results.channels[0].alternatives[0].transcript }}",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "You are an expert CRM Data Entry and Interaction Analyst.\nYour core objective is to analyze a client's \"Previous Notes\" alongside a new \"Sales Call Transcript\" and synthesize a precise, structured interaction note to be appended to their CRM record. \n\n### 1. DEFINITIONS\n* \"Historical Continuity\": The relationship between the client's past interactions and today's call. Is this a follow-up on an existing project/issue, or an entirely unrelated request?\n* \"Interaction Context\": The specific reason the client is engaging *today*. Skip static demographic profile data; focus purely on their current objective, problem, or request.\n* \"Materialized Things\": Concrete, tangible assets and transactional facts verified or created during the call. This includes specific products, hardware, shipping details, tracking requirements, exact fees, and specific account numbers or IDs verified on the call.\n* \"Resolution\": The absolute final state of the call and explicitly stated next steps for both the agent and the client.\n\n### 2. INSTRUCTIONS\n1. Analyze the \"User Previous Notes\" and the \"Transcript\" thoroughly.\n2. Determine the Historical Continuity: Assess if the current call relates to any of the past notes. \n3. Extract the core intent of today's call and the final outcome.\n4. Extract all concrete \"Materialized Things\" discussed (what is being sold, shipped, returned, or billed, including exact numbers).\n5. Be concise, highly objective, and use bullet points. Write this as a professional audit trail for a sales team.\n6. Do not hallucinate data. If a specific data point is not explicitly mentioned in the transcript, omit it rather than guessing.\n\n### 3. REQUIRED OUTPUT FORMAT\nOutput your CRM note strictly in the following format:\n\n## \ud83c\udfaf Call Context & Intent\n* **Historical Link:** [Explicitly state if this is a continuation of a past note (briefly reference the topic/date) OR if it is a completely new, unrelated inquiry.]\n* **Primary Objective:** [What specific action did the client want to take today?]\n* **Key Discussion Points:** [1-2 brief bullets on the main negotiation or process discussed]\n\n## \ud83d\udce6 Transactional Details (Materialized Things)\n* **Products/Assets:** [Specific physical items, software, devices, or upgrades involved]\n* **Verified Data:** [Specific ZIP codes, IDs, or phone numbers verified on the call]\n* **Financials:** [Specific fees, potential charges, or exact costs mentioned]\n* **Logistics:** [Shipping addresses, return labels, or timeline expectations (e.g., \"3-5 business days\")]\n\n## \u2705 Resolution & Next Steps\n* **Agent Action:** [What did the agent do or promise to do?]\n* **Client Action:** [What is the client required to do next? e.g., \"Drop old phone in USPS box\"]\n* **Final Status:** [Brief status, e.g., \"Exchange Processed Successfully\" or \"Awaiting Client Confirmation\"]"
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.9
    },
    {
      "id": "c4b3b315-0292-401c-b80a-e7c9b9257d23",
      "name": "Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        5648,
        1568
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-3.1-flash-lite"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "49e829af-5fbe-4817-9bec-6df5adeb6823",
      "name": "Fetch GHL Contacts",
      "type": "n8n-nodes-base.highLevel",
      "position": [
        4464,
        1392
      ],
      "parameters": {
        "filters": {
          "query": "={{ $json.body.mobile_number }}"
        },
        "options": {},
        "operation": "getAll",
        "requestOptions": {}
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "37f97e37-dd1b-47bf-acfc-f43264c6ae1c",
      "name": "Transcribe Audio via Deepgram",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        5136,
        1376
      ],
      "parameters": {
        "url": "https://api.deepgram.com/v1/listen?model=nova-2&smart_format=true",
        "method": "POST",
        "options": {
          "response": {
            "response": {
              "neverError": true,
              "fullResponse": true,
              "responseFormat": "json"
            }
          }
        },
        "sendBody": true,
        "contentType": "binaryData",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "inputDataFieldName": "audio"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "997d9ca5-1e83-450e-9428-64ba759f4738",
      "name": "Fetch User Notes",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        5360,
        1376
      ],
      "parameters": {
        "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Fetch GHL Contacts').item.json.id }}/notes",
        "options": {},
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/json"
            },
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "nodeCredentialType": "highLevelOAuth2Api"
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "3d82d40c-c78d-4ada-8c28-75762a3957d2",
      "name": "Check Mobile Number",
      "type": "n8n-nodes-base.if",
      "position": [
        4240,
        1408
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f2a19712-eafc-4cf5-8ec5-2347fde30986",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.body.mobile_number }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "1a208f63-9be3-483b-8b1f-59eed4a3cb6a",
      "name": "Check Contact Existence",
      "type": "n8n-nodes-base.if",
      "position": [
        4688,
        1392
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "30bb8d1a-9af2-4356-b518-7c8a7f486976",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "f88ede6e-1d61-41af-8515-20d79a6e27ad",
      "name": "Extract Binary Data",
      "type": "n8n-nodes-base.code",
      "position": [
        4912,
        1376
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst webhookItem = $('When Webhook Received').first();\n\nif (!webhookItem || !webhookItem.binary) {\n  throw new Error(\"No binary file was found in the Webhook node.\");\n}\n\nconst binaryKey = Object.keys(webhookItem.binary)[0];\nconst binaryFile = webhookItem.binary[binaryKey];\n\nfor (const item of items) {\n  item.binary = {\n    audio: binaryFile\n  };\n}\n\nreturn items;"
      },
      "typeVersion": 2
    },
    {
      "id": "9ee1a4a5-f636-4d56-a08d-7dc30c8b51fe",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5968,
        1232
      ],
      "parameters": {
        "color": 7,
        "width": 768,
        "height": 304,
        "content": "## Log results and respond\n\nLogs the final execution details to Google Sheets and responds to the webhook."
      },
      "typeVersion": 1
    },
    {
      "id": "ea6dfda5-c3fd-4e8a-a380-1d421f380837",
      "name": "Append Logs to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        6320,
        1376
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{ $('Fetch GHL Contacts').item.json.contactName }}",
            "contactid": "={{ $('Fetch GHL Contacts').item.json.id }}",
            "previous notes": "={{    $('Fetch User Notes').item.json.notes     .filter(note => note.dateAdded >= $now.minus({ days: 30 }).toISO())     .map(note => `[${note.dateAdded.substring(0, 10)}] ${note.bodyText}`)     .join('\\n\\n')  }}",
            "transcript_execution_link": "=https://enter-your-n8n-instance-url-here/workflow/{{ $workflow.id }}/executions/{{ $execution.id }}",
            "Current_ai_generated_notes": "={{ $('Generate LLM Response').item.json.text }}"
          },
          "schema": [
            {
              "id": "contactid",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "contactid",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "transcript_execution_link",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "transcript_execution_link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "previous notes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "previous notes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Current_ai_generated_notes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Current_ai_generated_notes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "contactid"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1C-ibzrwXpbChQOd30u8yQ7Ukgq5nWcA30dH6eaIdi7k/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "807c840f-22ad-4f91-b455-02ea28a9440d",
      "name": "Create a Note about call summary",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        6048,
        1376
      ],
      "parameters": {
        "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Fetch GHL Contacts').item.json.id }}/notes",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "body",
              "value": "={{ $json.text }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2023-02-21"
            }
          ]
        },
        "nodeCredentialType": "highLevelOAuth2Api"
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    }
  ],
  "active": true,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "8787f99b-5922-4b66-b2fe-1fbcc109284b",
  "nodeGroups": [],
  "connections": {
    "Fetch User Notes": {
      "main": [
        [
          {
            "node": "Generate LLM Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generate LLM Response",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Fetch GHL Contacts": {
      "main": [
        [
          {
            "node": "Check Contact Existence",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Mobile Number": {
      "main": [
        [
          {
            "node": "Fetch GHL Contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Binary Data": {
      "main": [
        [
          {
            "node": "Transcribe Audio via Deepgram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append Logs to Sheets": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate LLM Response": {
      "main": [
        [
          {
            "node": "Create a Note about call summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Webhook Received": {
      "main": [
        [
          {
            "node": "Check Mobile Number",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Contact Existence": {
      "main": [
        [
          {
            "node": "Extract Binary Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transcribe Audio via Deepgram": {
      "main": [
        [
          {
            "node": "Fetch User Notes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create a Note about call summary": {
      "main": [
        [
          {
            "node": "Append Logs to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}