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 →
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567804",
"name": "HotBot \u2014 04 Leads Pipeline",
"nodes": [
{
"id": "node-webhook-leads",
"name": "Webhook \u2014 Leads CRUD",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
300
],
"parameters": {
"httpMethod": "POST",
"path": "hotbotstudios-leads",
"responseMode": "responseNode",
"options": {
"allowedOrigins": "*"
}
}
},
{
"id": "node-validate-leads",
"name": "Validate & Extract Action",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
480,
300
],
"parameters": {
"jsCode": "const body = $input.first().json.body || $input.first().json;\nconst method = $input.first().json.method || 'POST';\n\n// Support both POST body action and HTTP method mapping\nconst actionMap = { GET: 'list', POST: 'create', PATCH: 'update', DELETE: 'delete' };\nconst action = body.action || actionMap[method] || 'list';\n\nconst validActions = ['list', 'create', 'update', 'delete'];\nif (!validActions.includes(action)) throw new Error(`Invalid action: ${action}`);\n\nreturn [{\n json: {\n action,\n leadId: body.leadId || null,\n status: body.status || null,\n filters: body.filters || {},\n data: body.data || body,\n timestamp: new Date().toISOString()\n }\n}];"
}
},
{
"id": "node-switch-action",
"name": "Switch \u2014 Action Router",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
720,
300
],
"parameters": {
"mode": "expression",
"output": "={{ $json.action }}",
"rules": {
"rules": [
{
"outputKey": "list",
"value": "list"
},
{
"outputKey": "create",
"value": "create"
},
{
"outputKey": "update",
"value": "update"
},
{
"outputKey": "delete",
"value": "delete"
}
]
},
"fallbackOutput": "none"
}
},
{
"id": "node-sheets-list",
"name": "Google Sheets \u2014 List Leads",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [
960,
100
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"parameters": {
"operation": "read",
"documentId": {
"__rl": true,
"value": "YOUR_GOOGLE_SHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Leads",
"mode": "name"
},
"options": {
"returnAllMatches": true
}
}
},
{
"id": "node-sheets-create",
"name": "Google Sheets \u2014 Create Lead",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [
960,
220
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"parameters": {
"operation": "appendOrUpdate",
"documentId": {
"__rl": true,
"value": "YOUR_GOOGLE_SHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Leads",
"mode": "name"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Lead ID": "={{ $json.data.leadId || 'LEAD-' + Date.now() }}",
"Timestamp": "={{ $json.timestamp }}",
"Name": "={{ $json.data.name }}",
"Email": "={{ $json.data.email }}",
"Phone": "={{ $json.data.phone }}",
"Company": "={{ $json.data.company }}",
"Services": "={{ Array.isArray($json.data.services) ? $json.data.services.join(', ') : $json.data.services }}",
"Budget": "={{ $json.data.budget }}",
"Message": "={{ $json.data.message }}",
"Status": "new"
}
},
"options": {}
}
},
{
"id": "node-sheets-update",
"name": "Google Sheets \u2014 Update Lead",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [
960,
380
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"parameters": {
"operation": "update",
"documentId": {
"__rl": true,
"value": "YOUR_GOOGLE_SHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Leads",
"mode": "name"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Lead ID": "={{ $json.leadId }}",
"Status": "={{ $json.status }}"
}
},
"options": {
"cellFormat": "USER_ENTERED"
}
}
},
{
"id": "node-sheets-delete",
"name": "Google Sheets \u2014 Mark Deleted",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [
960,
500
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"parameters": {
"operation": "update",
"documentId": {
"__rl": true,
"value": "YOUR_GOOGLE_SHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Leads",
"mode": "name"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Lead ID": "={{ $json.leadId }}",
"Status": "deleted"
}
},
"options": {}
}
},
{
"id": "node-merge-results",
"name": "Merge Results",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
1200,
300
],
"parameters": {
"mode": "combine",
"combinationMode": "multiplex",
"options": {}
}
},
{
"id": "node-format-response",
"name": "Format Response",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1440,
300
],
"parameters": {
"jsCode": "const items = $input.all();\nconst action = $('Validate & Extract Action').first().json.action;\n\nif (action === 'list') {\n const leads = items.map(item => item.json).filter(r => r['Lead ID'] && r['Status'] !== 'deleted');\n return [{ json: { success: true, action, leads, count: leads.length } }];\n}\n\nif (action === 'create') {\n return [{ json: { success: true, action, message: 'Lead created', leadId: items[0]?.json['Lead ID'] || 'unknown' } }];\n}\n\nif (action === 'update') {\n return [{ json: { success: true, action, message: 'Lead updated', leadId: $('Validate & Extract Action').first().json.leadId } }];\n}\n\nif (action === 'delete') {\n return [{ json: { success: true, action, message: 'Lead removed', leadId: $('Validate & Extract Action').first().json.leadId } }];\n}\n\nreturn [{ json: { success: false, message: 'Unknown action' } }];"
}
},
{
"id": "node-respond-leads",
"name": "Respond to Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
1680,
300
],
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {
"responseCode": 200
}
}
}
],
"connections": {
"Webhook \u2014 Leads CRUD": {
"main": [
[
{
"node": "Validate & Extract Action",
"type": "main",
"index": 0
}
]
]
},
"Validate & Extract Action": {
"main": [
[
{
"node": "Switch \u2014 Action Router",
"type": "main",
"index": 0
}
]
]
},
"Switch \u2014 Action Router": {
"main": [
[
{
"node": "Google Sheets \u2014 List Leads",
"type": "main",
"index": 0
}
],
[
{
"node": "Google Sheets \u2014 Create Lead",
"type": "main",
"index": 0
}
],
[
{
"node": "Google Sheets \u2014 Update Lead",
"type": "main",
"index": 0
}
],
[
{
"node": "Google Sheets \u2014 Mark Deleted",
"type": "main",
"index": 0
}
]
]
},
"Google Sheets \u2014 List Leads": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 0
}
]
]
},
"Google Sheets \u2014 Create Lead": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 1
}
]
]
},
"Google Sheets \u2014 Update Lead": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 2
}
]
]
},
"Google Sheets \u2014 Mark Deleted": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 3
}
]
]
},
"Merge Results": {
"main": [
[
{
"node": "Format Response",
"type": "main",
"index": 0
}
]
]
},
"Format Response": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true,
"callerPolicy": "workflowsFromSameOwner"
},
"tags": [
{
"id": "tag-hotbot",
"name": "hotbot-studios"
},
{
"id": "tag-leads",
"name": "leads-pipeline"
}
]
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
HotBot — 04 Leads Pipeline. Uses googleSheets. Webhook trigger; 10 nodes.
Source: https://github.com/harshpreet20/hotbot26/blob/337e1599ac488651f97c911ee272fd705de8e90c/n8n-workflows/04-leads-pipeline.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Automatically qualify, score, and route inbound B2B leads using GPT-4o-mini — no manual review needed.
This workflow receives website lead submissions via webhook, normalizes the payload, validates contact details, scores intent to assign an SLA bucket, logs each lead to Google Sheets, and routes hot a
An intelligent automation workflow that monitors thought leader activity via social listening, tracks high-value prospects who engage with industry content, and systematically builds a qualified lead
This workflow uses KlickTipp community nodes, available for self-hosted n8n instances only.
This workflow automatically captures leads submitted through an Instagram Form and saves the data directly to a Google Sheet. It ensures that every new lead is instantly logged, creating a centralized