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.
PostStack: Leady z DM → Google Sheets. Uses httpRequest, googleSheets. Webhook trigger; 18 nodes.
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.