AutomationFlowsMarketing & Ads › Automate Contact Enrichment with Surfe, Google Sheets & Hubspot

Automate Contact Enrichment with Surfe, Google Sheets & Hubspot

Bygo-surfe @go-surfe on n8n.io

This template enables fully automated lead enrichment using Surfe’s bulk API. Simply drop a Google Spreadsheet into your Google Drive, and n8n will handle everything — from reading the leads, enriching them in batches, filtering valid data, and pushing results to HubSpot.

Event trigger★★★★☆ complexity12 nodesGoogle SheetsGoogle Drive TriggerHTTP RequestGmailHubSpot
Marketing & Ads Trigger: Event Nodes: 12 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #5776 — we link there as the canonical source.

This workflow follows the Gmail → Google Sheets recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "GepE6tB2olhDRCxP",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Enrich Marketing Leads From A Google Sheet",
  "tags": [],
  "nodes": [
    {
      "id": "0796ab84-bf14-4f51-906e-db01486b2c76",
      "name": "Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -460,
        580
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1-4gGB9cugFdrutFYdlaPwMT737ODxPnizWqLODoDfmo/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "0cf2212f-e1f3-4616-ad6b-6c8c00bfe237",
      "name": "Google Drive Trigger",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "position": [
        -760,
        580
      ],
      "parameters": {
        "event": "fileCreated",
        "options": {
          "fileType": "application/vnd.google-apps.spreadsheet"
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "mode": "list",
          "value": "1C4ccbMW84VWzgGMsNTVEUUm3i_MH3Rlm",
          "cachedResultUrl": "https://drive.google.com/YOUR_AWS_SECRET_KEY_HERE_MH3Rlm",
          "cachedResultName": "folder-n8n-listener"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c3e28407-7bb4-4d2a-8009-0621f236efa3",
      "name": "Filter: phone AND email",
      "type": "n8n-nodes-base.filter",
      "position": [
        1240,
        440
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4f8f9bec-6eee-4e62-8d5f-e8f5b85620d6",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.phone }}",
              "rightValue": ""
            },
            {
              "id": "007f5a66-4e2a-42bc-bbed-0fb2b2f39ae7",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.email }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "23fdf067-cd74-4b04-96df-9241a86570cf",
      "name": "Extract list of peoples from Surfe API response",
      "type": "n8n-nodes-base.code",
      "position": [
        1020,
        440
      ],
      "parameters": {
        "jsCode": "const people = $json.people || [];\n\nreturn people.map(person => {\n  return {\n    json: {\n      id: person.id || '',\n      firstName: person.firstName || '',\n      lastName: person.lastName || '',\n      email: person.emails?.[0]?.email || '',\n      phone: person.mobilePhones?.[0]?.mobilePhone || '',\n      jobTitle: person.jobTitle || '',\n      companyName: person.companyName || '',\n      companyWebsite: person.companyWebsite || '',\n      linkedinUrl: person.linkedinUrl || '',\n      country: person.country || '',\n      status: person.status || ''\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "1b84d64f-85ea-4914-96e2-3321c3ed389d",
      "name": "Is enrichment complete ?",
      "type": "n8n-nodes-base.if",
      "position": [
        800,
        480
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "65a670df-84e8-4c87-956c-96758b8d8d26",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "COMPLETED"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "735abd1e-66df-4e0c-92e4-803c08edd307",
      "name": "Surfe Bulk Enrichments API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        340,
        580
      ],
      "parameters": {
        "url": "https://api.surfe.com/v2/people/enrich",
        "method": "POST",
        "options": {
          "redirect": {
            "redirect": {}
          }
        },
        "jsonBody": "={{ $json }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "976ebf8c-8838-41c1-bb8f-f817a9b60ae9",
      "name": "Surfe check enrichement status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        560,
        580
      ],
      "parameters": {
        "url": "=https://api.surfe.com/v2/people/enrich/{{ $json.enrichmentID }}",
        "options": {
          "redirect": {
            "redirect": {}
          }
        },
        "jsonBody": "{\n  \"enrichmentType\": \"emailAndMobile\",\n  \"listName\": \"listName\",\n  \"people\": [\n    {\n      \"firstName\": \"\",\n      \"lastName\": \"\",\n      \"companyName\": \"\",\n      \"companyWebsite\": \"\",\n      \"externalID\": \"\",\n      \"linkedinUrl\": \"[YOUR LINKEDIN URL]/\"\n    }\n  ]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "94417a70-a873-491e-88e6-262dcadde94f",
      "name": "Gmail",
      "type": "n8n-nodes-base.gmail",
      "notes": "Notify end of all batches",
      "position": [
        120,
        340
      ],
      "parameters": {
        "sendTo": "{YOUR EMAIL ADDRESS}",
        "message": "Your batch csv enrichment is done.",
        "options": {},
        "subject": "Your batch csv enrichment is done."
      },
      "executeOnce": true,
      "notesInFlow": true,
      "typeVersion": 2.1
    },
    {
      "id": "ad49f2c1-a9a0-49fa-8853-aef4dc63a453",
      "name": "Split Batch - 500",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -160,
        580
      ],
      "parameters": {
        "options": {},
        "batchSize": 500
      },
      "notesInFlow": false,
      "typeVersion": 3,
      "alwaysOutputData": false
    },
    {
      "id": "b1c2c48c-5ba6-4a42-ab17-bf69400aa0ac",
      "name": "HubSpot: Create or Update",
      "type": "n8n-nodes-base.hubspot",
      "position": [
        1380,
        1100
      ],
      "parameters": {
        "email": "={{ $json.email }}",
        "options": {
          "resolveData": false
        },
        "authentication": "appToken",
        "additionalFields": {
          "country": "={{ $json.country }}",
          "jobTitle": "={{ $json.jobTitle }}",
          "lastName": "={{ $json.lastName }}",
          "firstName": "={{ $json.firstName }}",
          "websiteUrl": "={{ $json.linkedinUrl }}",
          "companyName": "={{ $json.companyName }}",
          "phoneNumber": "={{ $json.phone }}",
          "mobilePhoneNumber": "={{ $json.phone }}"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "5e689b8d-5539-4593-9e18-903b172f4c73",
      "name": "Wait 30 secondes",
      "type": "n8n-nodes-base.wait",
      "position": [
        780,
        940
      ],
      "parameters": {
        "amount": 30
      },
      "typeVersion": 1.1
    },
    {
      "id": "b6b81b03-77b5-4868-91f6-12d4d9c248d9",
      "name": "Prepare JSON Payload Enrichment Request",
      "type": "n8n-nodes-base.code",
      "position": [
        120,
        580
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nreturn [\n  {\n    json: {\n    \"include\": {\n      \"email\": true,\n      \"linkedInUrl\": false,\n      \"mobile\": true\n    },\n    \"notificationOptions\": {\n      \"webhookUrl\": \"\"\n    },\n      people: items.map((item) => ({\n        firstName: \"\",\n        lastName: \"\",\n        companyName: \"\",\n        companyWebsite: \"\",\n        externalID: \"\",\n        linkedinUrl: item.json.linkedin_url,\n      })),\n    },\n  },\n];\n"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "eb0be05b-a13d-453a-ae04-6800bce9699a",
  "connections": {
    "Google Sheets": {
      "main": [
        [
          {
            "node": "Split Batch - 500",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 30 secondes": {
      "main": [
        [
          {
            "node": "Surfe check enrichement status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Batch - 500": {
      "main": [
        [
          {
            "node": "Gmail",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare JSON Payload Enrichment Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Drive Trigger": {
      "main": [
        [
          {
            "node": "Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter: phone AND email": {
      "main": [
        [
          {
            "node": "HubSpot: Create or Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is enrichment complete ?": {
      "main": [
        [
          {
            "node": "Extract list of peoples from Surfe API response",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait 30 secondes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HubSpot: Create or Update": {
      "main": [
        [
          {
            "node": "Split Batch - 500",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Surfe Bulk Enrichments API": {
      "main": [
        [
          {
            "node": "Surfe check enrichement status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Surfe check enrichement status": {
      "main": [
        [
          {
            "node": "Is enrichment complete ?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare JSON Payload Enrichment Request": {
      "main": [
        [
          {
            "node": "Surfe Bulk Enrichments API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract list of peoples from Surfe API response": {
      "main": [
        [
          {
            "node": "Filter: phone AND email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This template enables fully automated lead enrichment using Surfe’s bulk API. Simply drop a Google Spreadsheet into your Google Drive, and n8n will handle everything — from reading the leads, enriching them in batches, filtering valid data, and pushing results to HubSpot.

Source: https://n8n.io/workflows/5776/ — original creator credit. Request a take-down →

More Marketing & Ads workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Marketing & Ads

This workflow runs on scheduled weekly and monthly triggers to generate unified marketing performance reports. It processes multiple websites by collecting analytics data, paid ads performance, and CR

Gmail, Google Sheets, Google Analytics +3
Marketing & Ads

My workflow 11. Uses manualTrigger, splitOut, httpRequest, splitInBatches. Event-driven trigger; 14 nodes.

HTTP Request, OpenAI, Google Sheets +2
Marketing & Ads

Run professional email campaigns with A/B testing, Google Sheets tracking, and Slack analytics. FEATURES:

Google Sheets, Slack, Gmail +1
Marketing & Ads

This workflow allows you to send multi-step email campaigns using n8n, Gmail and Google Sheets.

Google Sheets, Gmail, Execute Workflow Trigger
Marketing & Ads

This workflow acts as an instant SDR that replies to new inbound leads across multiple channels in real time. It first captures and normalizes all incoming lead data into a unified structure. The work

Google Sheets, HTTP Request, Gmail +1