{
  "id": "mnHSrlxoHJPRTpH8",
  "name": "Sync and Enrich HubSpot Leads via AI and Lusha",
  "tags": [
    {
      "id": "PgQ4pUCc7A8lqI6y",
      "name": "Template",
      "createdAt": "2026-01-14T11:44:24.461Z",
      "updatedAt": "2026-01-14T11:44:24.461Z"
    }
  ],
  "nodes": [
    {
      "id": "b3f9cc95-e454-4cdd-9457-1a10d3125620",
      "name": "HubSpot: Update Company",
      "type": "n8n-nodes-base.hubspot",
      "position": [
        1088,
        -80
      ],
      "parameters": {
        "resource": "company",
        "companyId": "={{ $json.existing_company_id }}",
        "operation": "update",
        "updateFields": {
          "city": "={{ $json.updates_payload.city }}",
          "companyDomainName": "={{ $json.updates_payload.domain.match(/[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/)?.[0] || \"\" }}"
        },
        "authentication": "appToken"
      },
      "credentials": {
        "hubspotAppToken": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c749a19f-60b8-4153-bd1b-cad2ce0ffab3",
      "name": "HubSpot: Create Company",
      "type": "n8n-nodes-base.hubspot",
      "position": [
        1088,
        112
      ],
      "parameters": {
        "name": "={{ $json.updates_payload.company }}",
        "resource": "company",
        "authentication": "appToken",
        "additionalFields": {
          "city": "={{ $json.updates_payload.city }}",
          "description": "=Lead Source: {{ $json.updates_payload.source_type }}\nDate: {{ $now.toISO() }}\nOriginal Contact: {{ $json.updates_payload.email }}\nContact Person: {{ $json.updates_payload.first_name }} {{ $json.updates_payload.last_name }}",
          "lifecycleStatus": "lead",
          "companyDomainName": "={{ $json.updates_payload.domain.match(/[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/)?.[0] || \"\" }}"
        }
      },
      "credentials": {
        "hubspotAppToken": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "dae0749e-1756-4e2f-8dcb-4a619f031e3f",
      "name": "Switch Logic",
      "type": "n8n-nodes-base.switch",
      "position": [
        864,
        16
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "b02f35d6-f568-47ec-bd9d-c8e85bb05165",
                    "operator": {
                      "type": "number",
                      "operation": "gte"
                    },
                    "leftValue": "={{ $json.similarity_score }}",
                    "rightValue": 80
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "cda80c76-2929-47b2-8a30-ab36db0eadf3",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        -1248,
        16
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a91967fe-b6b0-4c8d-b7bf-c51948a466f3",
      "name": "Parse Telegram Message",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        -1072,
        16
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=Analyze this text and return ONLY a JSON object. Text: {{ $node[\"Telegram Trigger\"].json[\"message\"][\"text\"] }} Extract the 'company_domain' (the official corporate website, e.g., 'ibm.com' for IBM). If the domain is not explicitly mentioned, use your knowledge to provide the most likely corporate domain.\nThe 'note' field should contain ONLY the specific action item or additional context provided (e.g., 'call him'), excluding the names of people or companies already identified in other fields\n\nJSON Structure:\n{\n  \"company\": \"Company Name\",\n  \"company_domain\": \"Official domain (e.g. ibm.com)\",\n  \"first_name\": \"First Name\",\n  \"last_name\": \"Last Name\",\n  \"email\": \"Email Address\",\n  \"city\": \"City\",\n  \"note\": \"The note content\",\n  \"source_type\": \"Telegram Bot\"\n}"
            }
          ]
        },
        "jsonOutput": true
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "03865301-f09a-4206-96af-68032c0d7238",
      "name": "Get HubSpot data",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -400,
        144
      ],
      "parameters": {
        "url": "https://api.hubapi.com/crm/v3/objects/companies",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "limit",
              "value": "100"
            },
            {
              "name": "properties",
              "value": "name,city,domain"
            }
          ]
        },
        "nodeCredentialType": "hubspotAppToken"
      },
      "credentials": {
        "hubspotAppToken": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "668a8f24-e36f-44d8-b8fc-5ce561560430",
      "name": "New or Updated row",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "position": [
        -992,
        -256
      ],
      "parameters": {
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": ""
        }
      },
      "credentials": {
        "googleSheetsTriggerOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1,
      "waitBetweenTries": 2000
    },
    {
      "id": "03272bd1-5a3c-4ad7-8cd4-1e9287c49939",
      "name": "Create or update a contact",
      "type": "n8n-nodes-base.hubspot",
      "position": [
        2352,
        -32
      ],
      "parameters": {
        "email": "={{ $json.updates_payload.email }}",
        "options": {
          "resolveData": false
        },
        "authentication": "appToken",
        "additionalFields": {
          "lastName": "={{ $json.updates_payload.last_name }}",
          "firstName": "={{ $json.updates_payload.first_name }}",
          "associatedCompanyId": "={{ $json.id }}"
        }
      },
      "credentials": {
        "hubspotAppToken": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "notesInFlow": false,
      "retryOnFail": false,
      "typeVersion": 2.2,
      "alwaysOutputData": false
    },
    {
      "id": "bed43ccb-4020-484a-8fb9-29f2f09d12bb",
      "name": "Add a Note to Hubspot company",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3152,
        192
      ],
      "parameters": {
        "url": "https://api.hubapi.com/crm/v3/objects/notes",
        "body": "={\n  \"properties\": {\n    \"hs_note_body\": \"{{ $json.updates_payload.note }}\",\n    \"hs_timestamp\": \"{{ new Date().toISOString() }}\"\n  },\n  \"associations\": [\n    {\n      \"to\": {\n        \"id\": \"{{ $json.id }}\"\n      },\n      \"types\": [\n        {\n          \"associationCategory\": \"HUBSPOT_DEFINED\",\n          \"associationTypeId\": 190\n        }\n      ]\n    }\n  ]\n}",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "raw",
        "authentication": "genericCredentialType",
        "rawContentType": "application/json",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        },
        "hubspotAppToken": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "64d444d9-cc08-4693-b483-ed7b057bba5a",
      "name": "Identify Telegram triggered flow",
      "type": "n8n-nodes-base.filter",
      "position": [
        2912,
        -192
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8ad87c06-13d1-4bc3-ae6e-0dfd7a73a75b",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $node[\"Match Lead to Existing Company\"].json.updates_payload.is_live_trigger }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "be37f9e5-dc97-4c54-a543-2a5040fbe343",
      "name": "Update Telegram user",
      "type": "n8n-nodes-base.telegram",
      "position": [
        3152,
        -192
      ],
      "parameters": {
        "text": "=\u2705 Lead Processed Successfully!  \ud83c\udfe2 Company: {{ $node[\"Match Lead to Existing Company\"].json.updates_payload.company }} \ud83d\udc64 Contact: {{ $node[\"Match Lead to Existing Company\"].json.updates_payload.first_name }} {{ $node[\"Match Lead to Existing Company\"].json.updates_payload.last_name }} \ud83c\udfaf Action: {{ $node[\"Switch Logic\"].index === 0 ? 'Updated Existing Record' : 'Created New Record' }} \ud83d\udcdd Note Added: {{ $node[\"Match Lead to Existing Company\"].json.updates_payload.note }}",
        "chatId": "={{ $node[\"Match Lead to Existing Company\"].json.updates_payload.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "28235c93-0bed-45e2-bd55-5cae8e62b3f6",
      "name": "Identify updated row",
      "type": "n8n-nodes-base.filter",
      "position": [
        2912,
        16
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9eaa7a44-e124-4457-9f4e-d0e59414409e",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              },
              "leftValue": "={{ $node[\"Match Lead to Existing Company\"].json.updates_payload.is_live_trigger }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "67f093c8-a08d-4c3f-b797-a0afe6bf6a45",
      "name": "Acknowledge in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3152,
        16
      ],
      "parameters": {
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "809347f1-f6aa-44a9-b738-5d4cac4a7acb",
      "name": "Resolve Company ID",
      "type": "n8n-nodes-base.code",
      "position": [
        1616,
        160
      ],
      "parameters": {
        "jsCode": "// Resolve the final ID from current context or CRM nodes\nlet finalId = $json.id || $json.companyId;\nlet retryNeeded = false;\n\nif (!finalId) {\n  try {\n    const createNode = $('HubSpot: Create Company').item.json;\n    finalId = createNode.companyId || createNode.id;\n  } catch (e) {}\n}\n\nif (!finalId) {\n  try {\n    const updateNode = $('HubSpot: Update Company').item.json;\n    finalId = updateNode.companyId || updateNode.id;\n  } catch (e) {}\n}\n\nif (!finalId) retryNeeded = true;\n\nconst leadData = $('Match Lead to Existing Company').item.json.updates_payload;\nconst enrichedEmail = $json.updates_payload?.email;\n\nreturn {\n  id: finalId,\n  retry_needed: retryNeeded,\n  updates_payload: {\n    ...leadData,\n    email: enrichedEmail || leadData.email\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "febf99b1-ad06-4e34-a040-7f9183eec6c3",
      "name": "Retry ID resolution",
      "type": "n8n-nodes-base.wait",
      "position": [
        2000,
        160
      ],
      "parameters": {
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "b14903b4-c785-4fa8-ac7e-430f27c3d77d",
      "name": "Filter processed lines",
      "type": "n8n-nodes-base.filter",
      "position": [
        -768,
        -160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "73936385-e73b-4477-b964-96ba7670366a",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "280f3542-98f7-4924-9bd5-872cb13c75a8",
      "name": "Lusha Enrichment - email",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1536,
        -192
      ],
      "parameters": {
        "url": "https://api.lusha.com/v2/person",
        "options": {
          "response": {
            "response": {
              "neverError": true,
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "firstName",
              "value": "={{ $('Match Lead to Existing Company').item.json.updates_payload.first_name.trim() }}"
            },
            {
              "name": "lastName",
              "value": "={{ $('Match Lead to Existing Company').item.json.updates_payload.last_name.trim() }}"
            },
            {
              "name": "companyName",
              "value": "={{ $('Match Lead to Existing Company').item.json.updates_payload.company }}"
            },
            {
              "name": "companyDomain",
              "value": "={{ $('Match Lead to Existing Company').item.json.updates_payload.domain }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "55404dac-a87f-4f06-acd8-0352a7603413",
      "name": "Switch on email field",
      "type": "n8n-nodes-base.switch",
      "position": [
        1280,
        16
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "b4aec99d-82f8-4db2-9fe4-bcb03596dd1d",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ !$('Match Lead to Existing Company').item.json.updates_payload.email }}",
                    "rightValue": ""
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "5df0e6c1-3925-4179-9f85-78eb6867b790",
      "name": "Lusha Company Enrichment",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2176,
        -240
      ],
      "parameters": {
        "url": "https://api.lusha.com/v2/company",
        "options": {
          "response": {
            "response": {
              "neverError": true,
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "domain",
              "value": "={{ $('Match Lead to Existing Company').item.json.updates_payload.domain }}"
            },
            {
              "name": "company",
              "value": "={{ $('Match Lead to Existing Company').item.json.updates_payload.company }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "a49df86f-40c5-49a9-8dd5-42fd01530240",
      "name": "HubSpot: Update Enriched Company",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2688,
        -240
      ],
      "parameters": {
        "url": "=https://api.hubapi.com/crm/v3/objects/companies/{{ $json.hubspot_id }}",
        "method": "PATCH",
        "options": {},
        "jsonBody": "={\n  \"properties\": {{ JSON.stringify($json.delta_update) }}\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "f29ad8a0-f502-4a46-87a3-8c92715afe60",
      "name": "Domain Resolver",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "onError": "continueRegularOutput",
      "position": [
        -400,
        -224
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.0-flash",
          "cachedResultName": "models/gemini-2.0-flash"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=Task: Resolve the official corporate domain for '{{ $json.company }}'.\nRules:\n1. If a valid domain is present in 'Existing Domain' or can be extracted from 'Email', return that domain exactly.\n2. If missing, find the official corporate domain for the company name.\n3. Return ONLY the domain string (e.g., 'microsoft.com').\n4. Do not include 'https://' or 'www.'.\n5. If not found, return 'null'.\n6. Return ONLY the domain string. Do NOT use quotes or any formatting."
            }
          ]
        },
        "jsonOutput": true
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "ecd01c50-610e-4a1e-a918-924a087c2d58",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        304,
        -1264
      ],
      "parameters": {
        "color": 6,
        "width": 1344,
        "height": 544,
        "content": "# HubSpot Smart Lead Enrichment and Matching via Google Sheets, Telegram, Lusha, and Gemini AI\n\n## Core Architecture - Agnostic Data Structure\n### This architecure is designed to be data-source agnostic. Whether the lead comes from Telegram (AI-parsed) or Google Sheets, data is normalized into a standard 'updates_payload' object before hitting the logic engine. This allows for easy addition of new lead sources without changing the core code.\n\n## Template Setup Guide \n### The workflow automates lead intake from Telegram and Google Sheets, using Gemini AI for domain resolution and Lusha for data enrichment. It prevents CRM duplicates using a custom fuzzy matching engine.\n\n### Key Steps to Configure: \n1. **Credentials:** Connect your HubSpot (Private App), Lusha, Gemini, Google Sheets, and Telegram accounts. \n2. **Spreadsheet:** Set your Spreadsheet ID in the 'Trigger' and 'Acknowledge' nodes. \n3. **Matching Logic:** Adjust the similarity threshold (default 80) in the 'Switch Logic' node to fit your data quality needs. \n4. **Gemini Node:** Ensure 'Execute Once' is disabled for bulk processing support."
      },
      "typeVersion": 1
    },
    {
      "id": "d5f6dee6-9157-48a3-8d96-dcbe226b954d",
      "name": "Match Lead to Existing Company",
      "type": "n8n-nodes-base.code",
      "position": [
        640,
        16
      ],
      "parameters": {
        "jsCode": "/**\n * Secret Sauce: Fuzzy Match & Domain Resolution\n * English comments only per user preferences.\n */\n\nconst allData = $input.all();\n\n// 1. Separate HubSpot Reference Data from incoming leads\nconst hubspotCompanies = allData.filter(i => \n  i.json.hs_object_id || \n  i.json.properties?.hs_object_id || \n  i.json.is_reference_data\n);\n\nconst leads = allData.filter(i => \n  i.json.company && \n  !i.json.hs_object_id && \n  !i.json.properties?.hs_object_id\n);\n\nreturn leads.map(lead => {\n    let bestMatch = null;\n    let highestScore = 0;\n\n    // --- AGNOSTIC DOMAIN RESOLUTION (Plan B) ---\n    // Extract raw string from Gemini (handles Simplified Output or nested structure)\n    let rawGemini = lead.json.text || lead.json.content?.parts?.[0]?.text;\n    let cleanedGemini = null;\n\n    if (rawGemini) {\n        // English comment: Strictly remove brackets [], quotes \"\", newlines \\n and spaces\n        cleanedGemini = rawGemini.replace(/[\"'\\[\\]\\n\\r\\t]/g, \"\").trim().toLowerCase();\n        \n        // Ensure 'null' strings from AI are treated as actual nulls\n        if (cleanedGemini === \"null\" || cleanedGemini === \"\") {\n            cleanedGemini = null;\n        }\n    }\n\n    // Priority chain for Domain resolution\n    const leadDomain = (\n        cleanedGemini ||\n        lead.json.company_domain || \n        lead.json.email?.split('@')[1] || \n        lead.json.domain\n    )?.toLowerCase().trim();\n\n    const leadCompany = lead.json.company;\n\n    // --- MATCHING ENGINE ---\n    for (const hs of hubspotCompanies) {\n        let currentScore = 0;\n        const hsProps = hs.json.properties || {};\n        \n        // Extract HubSpot identifiers\n        const hsDomain = (hs.json.domain || hsProps.domain)?.toLowerCase().trim();\n        const hsName = (hsProps.name || hs.json.name || hs.json.company);\n\n        // A. Hard Match on Domain (Highest Confidence)\n        if (leadDomain && hsDomain && leadDomain === hsDomain) {\n            currentScore = 1.0;\n        } \n        // B. Fuzzy/Substring Match on Name\n        else if (leadCompany && hsName) {\n            const s1 = String(leadCompany).toLowerCase().trim();\n            const s2 = String(hsName).toLowerCase().trim();\n\n            if (s1 === s2) {\n                currentScore = 1.0;\n            } else if (s1.includes(s2) || s2.includes(s1)) {\n                currentScore = 0.95;\n            }\n        }\n\n        if (currentScore > highestScore) {\n            highestScore = currentScore;\n            bestMatch = hs;\n        }\n    }\n\n    // Return finalized agnostic object\n    return {\n        json: {\n            updates_payload: {\n                ...lead.json,\n                domain: leadDomain || null\n            },\n            similarity_score: Math.round(highestScore * 100),\n            existing_company_id: bestMatch ? (bestMatch.json.id || bestMatch.json.hs_object_id || bestMatch.json.properties?.hs_object_id) : null\n        }\n    };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "a73a4e63-36ec-4c20-b278-90145b7e08dc",
      "name": "Append Resolved Domain to Lead",
      "type": "n8n-nodes-base.merge",
      "position": [
        48,
        -112
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "59045d18-c3d5-4b71-9768-9e025abc1f58",
      "mode": "append",
      "name": "Combine Lead with CRM Reference Data",
      "type": "n8n-nodes-base.merge",
      "position": [
        384,
        16
      ],
      "parameters": {},
      "typeVersion": 3
    },
    {
      "id": "b0db6f88-bbc9-473a-88cd-ba005f7af711",
      "name": "Split HubSpot Search Results",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        -176,
        144
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "results"
      },
      "typeVersion": 1
    },
    {
      "id": "6c118aab-9f82-4575-a9e3-a8068a4fc35a",
      "name": "Mark as HubSpot Reference Data",
      "type": "n8n-nodes-base.code",
      "position": [
        48,
        144
      ],
      "parameters": {
        "jsCode": "// Mark all incoming items as reference data\nreturn items.map(item => {\n  item.json.is_reference_data = true;\n  return item;\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "d3c7dccd-1f22-477c-b330-59ea626ce024",
      "name": "Format Telegram Lead Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -768,
        16
      ],
      "parameters": {
        "jsCode": "// 1. Extract the raw text string from the Gemini output structure\nconst rawText = items[0].json.content.parts[0].text;\n\n// 2. Clean up Markdown formatting if present\nconst cleanJson = rawText.replace(/```json|```/g, '').trim();\n\n// 3. Parse the string into a valid JSON object\ntry {\n  const parsedData = JSON.parse(cleanJson);\n  parsedData.is_live_trigger = true;\n  parsedData.chat_id = $node[\"Telegram Trigger\"].json[\"message\"][\"chat\"][\"id\"];\n  \n  return [\n    {\n      json: parsedData\n    }\n  ];\n} catch (error) {\n  throw new Error(\"Failed to parse JSON: \" + error.message);\n}"
      },
      "typeVersion": 2
    },
    {
      "id": "f49edeef-6865-4dfc-abf5-02a696c64ace",
      "name": "Map Contact Enrichment Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1744,
        -192
      ],
      "parameters": {
        "jsCode": "const sourceData = $('Match Lead to Existing Company').item.json;\nconst item = JSON.parse(JSON.stringify(sourceData));\nconst lushaResponse = $input.first().json;\nconst lushaEmail = lushaResponse.contact?.data?.emailAddresses?.[0]?.email;\nif (lushaEmail) {\n  item.updates_payload.email = lushaEmail;\n}\nreturn { json: item };"
      },
      "typeVersion": 2
    },
    {
      "id": "9bd9f4dc-a08e-40ff-a221-061b2e0b4582",
      "name": "Prepare Firmographic Updates",
      "type": "n8n-nodes-base.code",
      "position": [
        2352,
        -240
      ],
      "parameters": {
        "jsCode": "const resolveNode = $('Resolve Company ID').item.json;\nconst hubspotProps = resolveNode.properties || {};\nconst companyId = resolveNode.id;\nconst sourceData = $('Match Lead to Existing Company').item.json;\nconst item = JSON.parse(JSON.stringify(sourceData));\nconst lushaData = $input.first().json.data;\nlet delta = {};\nfunction addIfChanged(hsKey, newValue) {\n  const currentVal = hubspotProps[hsKey]?.value || \"\";\n  if (newValue && newValue.toString() !== currentVal.toString()) {\n    delta[hsKey] = newValue;\n  }\n}\nif (lushaData) {\n  addIfChanged('description', lushaData.description);\n  addIfChanged('annualrevenue', lushaData.revenueRange ? lushaData.revenueRange[1] : null);\n  addIfChanged('founded_year', lushaData.founded);\n  addIfChanged('website', lushaData.website);\n}\nitem.hubspot_id = companyId;\nitem.delta_update = delta;\nitem.has_changes = Object.keys(delta).length > 0;\nreturn { json: item };"
      },
      "typeVersion": 2
    },
    {
      "id": "21809c08-2b0a-4efc-b715-b18545319b83",
      "name": "Validate Company ID Status",
      "type": "n8n-nodes-base.switch",
      "position": [
        1984,
        -48
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "527b4ca9-1bee-4d7f-adf2-0808ee110a69",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.retry_needed }}",
                    "rightValue": false
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "d87039fd-c6c2-470b-a815-910326e633a6",
      "name": "Check for Existing Contact Email",
      "type": "n8n-nodes-base.switch",
      "position": [
        2176,
        112
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Has email",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "5152f80c-ed95-49a8-9376-3b7b955dd996",
                    "operator": {
                      "type": "string",
                      "operation": "notEmpty",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.updates_payload.email }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "77482f41-01e3-4aa1-b660-e34e3cc5ae3f",
      "name": "Filter Leads with Data Changes",
      "type": "n8n-nodes-base.filter",
      "position": [
        2512,
        -240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "11c5baeb-f422-4a05-a233-b9005ebb7daf",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.has_changes }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "ad741b53-69bb-46ea-818b-93d08c11762f",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1312,
        -544
      ],
      "parameters": {
        "color": 6,
        "width": 704,
        "height": 912,
        "content": "## 1. Data Intake & Parsing \n\n###  These nodes capture new leads from Google Sheets (polling) or Telegram (webhooks). \n### Gemini AI parses unstructured messages into a standard JSON payload, ensuring data consistency regardless of the source."
      },
      "typeVersion": 1
    },
    {
      "id": "847000e9-4adb-4675-850a-f06f87f0355e",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        -544
      ],
      "parameters": {
        "color": 6,
        "width": 656,
        "height": 912,
        "content": "## 2. Contextual Lookup \n\n### Uses Gemini AI to resolve missing corporate domains and fetches existing company data from HubSpot. \n\n### This preparation is key for accurate matching and prevents CRM fragmentation."
      },
      "typeVersion": 1
    },
    {
      "id": "31f1f6fd-6666-4001-8ada-d9729e4d8a87",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -544
      ],
      "parameters": {
        "color": 6,
        "width": 464,
        "height": 912,
        "content": "## 3. The Matching Engine \n\n### Custom JS logic performs fuzzy matching against HubSpot data. \n### It calculates a similarity score to determine if a lead belongs to an existing record, optimizing enrichment credit usage, and prevents HubSpot record duplication."
      },
      "typeVersion": 1
    },
    {
      "id": "373662ca-70b1-4cba-be0d-cfe4f1bae360",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        848,
        -544
      ],
      "parameters": {
        "color": 6,
        "width": 560,
        "height": 912,
        "content": "## 4. CRM Routing & Core Writes \n\n### This stage directs the lead based on its score: high scores trigger the HubSpot: Update Company node to refresh existing records, while low scores route to HubSpot: Create Company to generate a new entity with proper source metadata."
      },
      "typeVersion": 1
    },
    {
      "id": "55380460-9aba-44e8-a389-76f941d18bae",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        -544
      ],
      "parameters": {
        "color": 6,
        "width": 1360,
        "height": 912,
        "content": "## 5. Contact & Firmographic Enrichment \n\n### This stage uses Lusha API to find missing emails and firmographic data (revenue, year founded). \n### It automatically updates the HubSpot company and associate/creates the contact person, ensuring your CRM has 360-degree data coverage."
      },
      "typeVersion": 1
    },
    {
      "id": "50c9961d-374b-4723-a623-30cff6a54806",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2880,
        -544
      ],
      "parameters": {
        "color": 6,
        "width": 448,
        "height": 912,
        "content": "## 6. Feedback Loop \n\n### This final stage of the workflow closes the execution by \n### - Logging the interaction as a HubSpot Note\n### - Updating the original Google Sheet status to 'Processed'\n### - Notify the Telegram user with a formatted success summary."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": "K3aG2vzbrcrUC2J1",
    "timeSavedMode": "fixed",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "06347870-74b5-4960-85bf-aef45289b690",
  "connections": {
    "Switch Logic": {
      "main": [
        [
          {
            "node": "HubSpot: Update Company",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "HubSpot: Create Company",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Domain Resolver": {
      "main": [
        [
          {
            "node": "Append Resolved Domain to Lead",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Get HubSpot data": {
      "main": [
        [
          {
            "node": "Split HubSpot Search Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Parse Telegram Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New or Updated row": {
      "main": [
        [
          {
            "node": "Filter processed lines",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Resolve Company ID": {
      "main": [
        [
          {
            "node": "Validate Company ID Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retry ID resolution": {
      "main": [
        [
          {
            "node": "Resolve Company ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Identify updated row": {
      "main": [
        [
          {
            "node": "Acknowledge in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch on email field": {
      "main": [
        [
          {
            "node": "Lusha Enrichment - email",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Resolve Company ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter processed lines": {
      "main": [
        [
          {
            "node": "Get HubSpot data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Domain Resolver",
            "type": "main",
            "index": 0
          },
          {
            "node": "Append Resolved Domain to Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Telegram Message": {
      "main": [
        [
          {
            "node": "Format Telegram Lead Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HubSpot: Create Company": {
      "main": [
        [
          {
            "node": "Switch on email field",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HubSpot: Update Company": {
      "main": [
        [
          {
            "node": "Switch on email field",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lusha Company Enrichment": {
      "main": [
        [
          {
            "node": "Prepare Firmographic Updates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lusha Enrichment - email": {
      "main": [
        [
          {
            "node": "Map Contact Enrichment Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Telegram Lead Data": {
      "main": [
        [
          {
            "node": "Get HubSpot data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Combine Lead with CRM Reference Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create or update a contact": {
      "main": [
        [
          {
            "node": "Identify Telegram triggered flow",
            "type": "main",
            "index": 0
          },
          {
            "node": "Identify updated row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Company ID Status": {
      "main": [
        [
          {
            "node": "Retry ID resolution",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Add a Note to Hubspot company",
            "type": "main",
            "index": 0
          },
          {
            "node": "Check for Existing Contact Email",
            "type": "main",
            "index": 0
          },
          {
            "node": "Lusha Company Enrichment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map Contact Enrichment Data": {
      "main": [
        [
          {
            "node": "Resolve Company ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Firmographic Updates": {
      "main": [
        [
          {
            "node": "Filter Leads with Data Changes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split HubSpot Search Results": {
      "main": [
        [
          {
            "node": "Mark as HubSpot Reference Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append Resolved Domain to Lead": {
      "main": [
        [
          {
            "node": "Combine Lead with CRM Reference Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Leads with Data Changes": {
      "main": [
        [
          {
            "node": "HubSpot: Update Enriched Company",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark as HubSpot Reference Data": {
      "main": [
        [
          {
            "node": "Combine Lead with CRM Reference Data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Match Lead to Existing Company": {
      "main": [
        [
          {
            "node": "Switch Logic",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for Existing Contact Email": {
      "main": [
        [
          {
            "node": "Create or update a contact",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Identify Telegram triggered flow",
            "type": "main",
            "index": 0
          },
          {
            "node": "Identify updated row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Identify Telegram triggered flow": {
      "main": [
        [
          {
            "node": "Update Telegram user",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Lead with CRM Reference Data": {
      "main": [
        [
          {
            "node": "Match Lead to Existing Company",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}