This workflow follows the Agent → Error Trigger 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 →
{
"name": "Lead Pipeline v3.0",
"nodes": [
{
"parameters": {
"content": "# Predictive Send Timing",
"height": 572,
"width": 412,
"color": 7
},
"id": "533db844-9e45-4d83-9714-37c850848e08",
"name": "\ud83d\udd2e Predictive Timing",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1024,
2528
]
},
{
"parameters": {
"content": "# Multichannel Outreach\n",
"height": 572,
"width": 1176,
"color": 5
},
"id": "e5c4a258-ca67-46aa-a7f5-f81f58017429",
"name": "\ud83d\udcf1 Multichannel Outreach",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-608,
2528
]
},
{
"parameters": {
"content": "# CRM Update & Activity Log\n",
"height": 572,
"width": 788,
"color": 4
},
"id": "afa76773-2de6-45e3-bae6-3c9bd8047416",
"name": "\ud83d\udcbe CRM & Logging",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
576,
2528
]
},
{
"parameters": {
"content": "## Lead Scraper & Discovery",
"height": 650,
"width": 2384,
"color": 2
},
"id": "c2b44136-ac11-49a2-8369-5daa1a7cfb7c",
"name": "\ud83d\udd77\ufe0f Lead Scraper",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1024,
992
]
},
{
"parameters": {
"content": "# Lead Intake",
"height": 316,
"width": 1108,
"color": 4
},
"id": "b579efa0-e51b-4908-8e2a-26325a6d202c",
"name": "\ud83d\udce5 Lead Intake",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1024,
1648
]
},
{
"parameters": {
"content": "# Enrichment Waterfall",
"height": 316,
"width": 1272,
"color": 6
},
"id": "37eb36c6-55fb-44c9-8de6-606b62ef3490",
"name": "\ud83d\udd0d Enrichment Waterfall",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
96,
1648
]
},
{
"parameters": {
"content": "# AI Agent ",
"height": 544,
"width": 800,
"color": 7
},
"id": "1f6c64b7-c2a0-43c0-b323-dbff92cc2cc5",
"name": "\ud83e\udde0 AI Agent \u2014 Lead Intelligence",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1024,
1968
]
},
{
"parameters": {
"httpMethod": "POST",
"path": "lead-pipeline-v3",
"responseMode": "responseNode",
"options": {}
},
"id": "76d187a2-9fae-4700-a4af-293d15c1042c",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-960,
1760
]
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 6 * * 1-5"
}
]
}
},
"id": "3959bdd0-a44a-4f93-b577-5f63b6ed94a9",
"name": "Scrape Scheduler",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
-928,
1216
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "cc7b9bd2-a647-4911-a6dd-27eae49f94c2",
"name": "config.apifyToken",
"value": "={{$env.APIFY_TOKEN}}",
"type": "string"
},
{
"id": "b87f6580-da17-4845-baf2-faa55fe03eb9",
"name": "config.targetMarket",
"value": "property managers",
"type": "string"
},
{
"id": "730922bf-3f32-426c-9a08-106aae22b3f0",
"name": "config.locations",
"value": "Austin TX, Denver CO, Nashville TN, Phoenix AZ",
"type": "string"
},
{
"id": "cc252d59-2810-41d8-8494-3b86976ca059",
"name": "config.maxLeads",
"value": "50",
"type": "number"
},
{
"id": "bbf20992-caaf-4e42-9be7-efeec467e013",
"name": "config.dryRun",
"value": "false",
"type": "boolean"
}
]
},
"options": {}
},
"id": "f173dd97-8260-4919-9151-d3bef05117f0",
"name": "Config",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-704,
1216
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.apify.com/v2/acts/compass~crawler-google-places/runs?token={{$json.config.apifyToken}}",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "searchStringsArray",
"value": "=[\"property management companies in {{ $json.config.locations }}\"]"
},
{
"name": "maxCrawledPlacesPerSearch",
"value": "={{ $json.config.maxLeads }}"
}
]
},
"options": {
"timeout": 120000
}
},
"id": "014c8ba0-16da-4fb2-86b5-72d02a30f98f",
"name": "Scrape Google Maps",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-448,
1216
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.apify.com/v2/acts/yin~yelp-scraper/runs?token={{$json.config.apifyToken}}",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "searchTerms",
"value": "=[\"property management\"]"
},
{
"name": "locations",
"value": "=[\"Austin, TX\", \"Denver, CO\"]"
}
]
},
"options": {
"timeout": 120000
}
},
"id": "ee93dbc2-153c-4bad-875b-a577b5b84f99",
"name": "Scrape Yelp Directory",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-448,
1040
]
},
{
"parameters": {
"amount": 60
},
"id": "51295385-743c-4fcb-8e88-fe03dd356b8e",
"name": "Wait for Scrapes",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
-208,
1216
]
},
{
"parameters": {
"url": "=https://api.apify.com/v2/acts/compass~crawler-google-places/runs/last/dataset/items?token={{ $('Config').item.json.config.apifyToken }}",
"options": {}
},
"id": "307d6d91-630f-44cf-a75a-445d408d50a7",
"name": "Fetch Google Maps Results",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
80,
1216
]
},
{
"parameters": {
"url": "=https://api.apify.com/v2/acts/yin~yelp-scraper/runs/last/dataset/items?token={{ $('Config').item.json.config.apifyToken }}",
"options": {}
},
"id": "40b9123a-218d-4eee-b2e4-b653d5cebeeb",
"name": "Fetch Yelp Results",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
80,
1056
]
},
{
"parameters": {},
"id": "84a515eb-7c8e-4017-83d1-404e3313efbe",
"name": "Merge Scraped Leads",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
336,
1232
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nreturn items.map(item => {\n const d = item.json;\n return { json: {\n name: d.title || d.name || d.hostName || d.businessName || '',\n company: d.title || d.businessName || d.name || '',\n email: d.email || d.contactEmail || '',\n phone: d.phone || d.contactPhone || d.phoneNumber || '',\n website: d.website || d.url || d.websiteUrl || '',\n address: d.address || d.fullAddress || d.location || '',\n source: d.searchPageUrl ? 'google_maps' : d.hostName ? 'airbnb' : 'yelp',\n rating: d.totalScore || d.rating || d.stars || null,\n reviewCount: d.reviewsCount || d.numberOfReviews || 0,\n category: d.categoryName || d.category || 'property management',\n scrapedAt: new Date().toISOString()\n }};\n});"
},
"id": "2817241e-580c-47df-890a-7276bdd4a89c",
"name": "Normalize Scraped Data",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
560,
1232
]
},
{
"parameters": {
"promptType": "define",
"text": "=Validate this scraped lead:\n{{ JSON.stringify($json) }}",
"options": {
"systemMessage": "You are a lead validation agent. For each scraped business, determine if it's a valid property management or STR host prospect. Check: 1) Is this actually a property management company or STR host? 2) Is it likely a decision-maker or just a listing? 3) Are there any red flags (competitor, too large, government entity)? Return JSON: {valid: boolean, confidence: 0-1, reason: string, estimatedSize: string}",
"maxIterations": 5,
"returnIntermediateSteps": false
}
},
"id": "583a72d6-7a5f-4b3a-9305-2ecb7f91040f",
"name": "AI Scrape Validator",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.7,
"position": [
800,
1232
]
},
{
"parameters": {
"model": "claude-sonnet-4-20250514",
"options": {
"maxTokensToSample": 1024,
"temperature": 0.1
}
},
"id": "b9560a4b-3d74-4761-a2b0-505ad67cfe66",
"name": "Scrape Validator Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"typeVersion": 1.2,
"position": [
800,
1408
],
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {},
"id": "a2fdd003-48cb-4a47-b515-3e607eaf167b",
"name": "Scrape Validator Think",
"type": "@n8n/n8n-nodes-langchain.toolThink",
"typeVersion": 1,
"position": [
992,
1408
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nreturn items.filter(item => {\n try {\n const text = item.json.output || item.json.text || JSON.stringify(item.json);\n const match = text.match(/\\{[\\s\\S]*\\}/);\n if (!match) return true;\n const result = JSON.parse(match[0]);\n return result.valid !== false && (result.confidence || 0.5) >= 0.5;\n } catch(e) { return true; }\n});"
},
"id": "f310a1e0-7d1b-4782-9694-6f440549df93",
"name": "Filter Valid Leads",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1184,
1392
]
},
{
"parameters": {},
"id": "cc663ba7-4c23-4a12-83c7-805c4bc1c47d",
"name": "Merge All Sources",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
-704,
1776
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nconst seen = new Set();\nconst unique = [];\nfor (const item of items) {\n const key = (item.json.email || item.json.phone || item.json.company || JSON.stringify(item.json)).toLowerCase().trim();\n if (!seen.has(key)) { seen.add(key); unique.push(item); }\n}\nreturn unique;"
},
"id": "4bcfa6b7-b87c-43aa-9ac5-defdd7ca73a2",
"name": "Deduplicate Leads",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-432,
1776
]
},
{
"parameters": {
"batchSize": 10,
"options": {}
},
"id": "becf4fb2-9382-4a69-a653-023a4f5f7080",
"name": "Process in Batches",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
-176,
1776
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.apollo.io/v1/people/match",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "email",
"value": "={{ $json.email }}"
},
{
"name": "first_name",
"value": "={{ ($json.name || '').split(' ')[0] }}"
},
{
"name": "organization_name",
"value": "={{ $json.company }}"
}
]
},
"options": {
"timeout": 15000
}
},
"id": "d8d3d7d2-b767-4de1-9276-304cb2a29079",
"name": "Enrich: Apollo",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
160,
1760
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "4d06937b-c50b-45ab-9891-337671f30858",
"leftValue": "={{ $json.person?.email || $json.email }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "notEmpty"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "29008362-f461-43f9-8e7e-3fe10700e4fd",
"name": "Has Email?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
320,
1760
]
},
{
"parameters": {
"url": "https://api.peopledatalabs.com/v5/person/enrich",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "name",
"value": "={{ $json.name || ($json.person?.first_name + ' ' + $json.person?.last_name) }}"
},
{
"name": "company",
"value": "={{ $json.company || $json.person?.organization?.name }}"
},
{
"name": "api_key",
"value": "={{$env.PDL_API_KEY}}"
}
]
},
"options": {
"timeout": 15000
}
},
"id": "82c830f3-1d72-481d-87fa-73f7e16e3200",
"name": "Fallback: PDL",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
544,
1776
]
},
{
"parameters": {},
"id": "ddf0ef8c-f66a-46c5-8038-a098ec3d27e5",
"name": "Merge Email Results",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
688,
1664
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "4afb99bf-d5ea-422f-b0fa-21d99920a963",
"name": "lead.name",
"value": "={{ $json.person?.name || $json.name || '' }}",
"type": "string"
},
{
"id": "019a7678-00e0-4cb7-88b9-39fbff6c852a",
"name": "lead.email",
"value": "={{ $json.person?.email || $json.email || '' }}",
"type": "string"
},
{
"id": "428ec163-76d5-4084-970e-2f18e831bc21",
"name": "lead.phone",
"value": "={{ $json.phone || $json.person?.phone_numbers?.[0] || '' }}",
"type": "string"
},
{
"id": "c3c8f02e-74f6-42de-9644-921ce11de931",
"name": "lead.company",
"value": "={{ $json.person?.organization?.name || $json.company || '' }}",
"type": "string"
},
{
"id": "51f8bd26-c08f-48fa-a613-818788e982ca",
"name": "lead.title",
"value": "={{ $json.person?.title || '' }}",
"type": "string"
},
{
"id": "86aef112-1098-48c4-a77c-1cae0552860e",
"name": "lead.linkedin",
"value": "={{ $json.person?.linkedin_url || '' }}",
"type": "string"
},
{
"id": "150780cf-dfc0-4aa3-9972-b64c4c9a38d8",
"name": "lead.website",
"value": "={{ $json.website || $json.person?.organization?.website_url || '' }}",
"type": "string"
},
{
"id": "285bbf51-215c-447c-914a-c228850808e7",
"name": "lead.siteContent",
"value": "={{ ($json.data?.markdown || '').substring(0, 3000) }}",
"type": "string"
},
{
"id": "9a473f62-2387-434d-a627-038c9faa7f66",
"name": "lead.address",
"value": "={{ $json.address || '' }}",
"type": "string"
},
{
"id": "d3522ff1-1ea3-4865-b49f-a6d9b5cac8f1",
"name": "lead.source",
"value": "={{ $json.source || 'webhook' }}",
"type": "string"
},
{
"id": "2668fd20-0735-4507-a28e-d3218a09ebf6",
"name": "lead.raw",
"value": "={{ JSON.stringify($json).substring(0, 5000) }}",
"type": "string"
}
]
},
"options": {}
},
"id": "2139a2ca-82dd-4c07-96a4-5584c466623d",
"name": "Combine Enriched Data",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1200,
1760
]
},
{
"parameters": {
"promptType": "define",
"text": "=Analyze this enriched lead and provide your intelligence report:\n\n{{ JSON.stringify($json) }}",
"options": {
"systemMessage": "You are the AI brain of Otter Labs' lead pipeline. You are an expert at analyzing enriched lead data and making intelligent GTM decisions.\n\nFor each lead, analyze ALL available data and output a JSON object with these keys:\n\n1. **score** (number 1-10): Composite lead quality score based on:\n - Fit: Does their business match property management / STR hosting?\n - Size: Revenue signals, review count, listing count, employee count\n - Pain: Manual processes, outdated tools, scaling challenges visible on their site\n - Timing: Recent growth, hiring, complaints, tool changes\n - Budget: Revenue indicators, property portfolio size\n - Access: Can we reach a decision-maker?\n\n2. **tier** (string): \"A\" (score 7+), \"B\" (score 5-6.9), \"C\" (below 5)\n\n3. **painPoints** (array of 3 strings): Top 3 pain points inferred from their data\n\n4. **personalizationHook** (string): One specific, unique detail about their business to reference in outreach \u2014 NOT generic\n\n5. **recommendedChannel** (string): \"email\", \"sms\", \"linkedin\", or \"multi-channel\" with reasoning\n\n6. **emailColdOpen** (string): A compelling 1-line email opener personalized to THIS lead\n\n7. **smsColdOpen** (string): A casual, human 1-line SMS opener\n\n8. **urgency** (string): \"hot\" (today), \"warm\" (this week), \"cold\" (nurture)\n\n9. **objectionPrediction** (string): Most likely objection this lead will raise\n\n10. **competitorLikely** (string): What tool/service they're probably using now\n\nOutput ONLY valid JSON. No markdown, no explanation.",
"maxIterations": 10,
"returnIntermediateSteps": false
}
},
"id": "4550c42e-9adf-4ff1-914d-b870b9c80087",
"name": "AI Agent \u2014 Lead Brain",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.7,
"position": [
-752,
2128
]
},
{
"parameters": {
"model": "claude-sonnet-4-20250514",
"options": {
"maxTokensToSample": 4096,
"temperature": 0.3
}
},
"id": "15c10cea-0334-431c-9503-7bd82f26eb9d",
"name": "Claude Sonnet",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"typeVersion": 1.2,
"position": [
-912,
2336
],
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {},
"id": "38c30a72-4ea1-4c1c-b9a8-8c1f1d2709f7",
"name": "Think Tool",
"type": "@n8n/n8n-nodes-langchain.toolThink",
"typeVersion": 1,
"position": [
-576,
2336
]
},
{
"parameters": {
"name": "weighted_lead_scorer",
"description": "Calculate weighted composite lead score. Input: JSON with keys fit, size, pain, timing, budget, access (each 1-10). Returns weighted score and tier.",
"jsCode": "const data = JSON.parse(query);\nconst weights = {fit:0.25, size:0.15, pain:0.20, timing:0.15, budget:0.10, access:0.15};\nlet score = 0;\nfor (const [k,w] of Object.entries(weights)) { score += (data[k]||5) * w; }\nscore = Math.round(score * 10) / 10;\nreturn JSON.stringify({score, tier: score>=7?'A':score>=5?'B':'C', weights, breakdown: data});"
},
"id": "5839a90f-0dce-435c-8d7d-9c35d3aa0dc7",
"name": "Scoring Calculator",
"type": "@n8n/n8n-nodes-langchain.toolCode",
"typeVersion": 1,
"position": [
-416,
2336
]
},
{
"parameters": {
"sessionIdType": "customKey",
"sessionKey": "pipeline-v3-session"
},
"id": "81ebaf65-4f21-437c-9889-cf72a5dcb141",
"name": "Buffer Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"typeVersion": 1.3,
"position": [
-736,
2336
]
},
{
"parameters": {
"content": "# Nurture Track\n",
"height": 204,
"width": 776
},
"id": "74ad0def-b8a1-43e6-8300-8259ca34ba74",
"name": "\ud83d\udd04 Nurture Track",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
352,
2304
],
"disabled": true
},
{
"parameters": {
"content": "# Error Handling\n",
"height": 344,
"width": 900
},
"id": "4522fef1-8039-4a02-9af2-fdd22be9891a",
"name": "\u26a0\ufe0f Error Handling",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1024,
3104
]
},
{
"parameters": {
"amount": 3,
"unit": "days"
},
"id": "83502991-4904-47dd-b83b-83bb14c2ccd7",
"name": "Wait 3 Days (Tier B)",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
416,
2368
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nreturn items.map(item => {\n const s = item.json.score || 5;\n const boost = item.json.replied ? 3 : item.json.opened ? 1.5 : 0;\n const newScore = Math.min(10, s + boost);\n return { json: { ...item.json, score: newScore, tier: newScore>=7?'A':newScore>=5?'B':'C', rescored: true } };\n});"
},
"id": "91d31bcc-45ab-45d5-8bfd-1f5a35ee1495",
"name": "Re-Score Lead",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
592,
2368
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "c3072886-e5f7-4bb0-87a3-d7b003b6bb24",
"leftValue": "={{ $json.tier }}",
"rightValue": "A",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "c88c36b0-6c2b-4117-978b-e983f2600820",
"name": "Upgraded to A?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
752,
2368
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.instantly.ai/api/v1/campaign/add-leads",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "campaign_id",
"value": "={{$env.INSTANTLY_DRIP_CAMPAIGN_ID}}"
},
{
"name": "leads",
"value": "={{ JSON.stringify([{email: $json.lead?.email || $json.email}]) }}"
}
]
},
"options": {}
},
"id": "843ad2b6-0817-4828-9ca4-fc78e178c701",
"name": "Add to Drip",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
944,
2352
]
},
{
"parameters": {},
"id": "11905575-8117-4eb1-8bd6-761c79579615",
"name": "Error Trigger",
"type": "n8n-nodes-base.errorTrigger",
"typeVersion": 1,
"position": [
-928,
3200
]
},
{
"parameters": {
"jsCode": "const err = $input.first().json;\nreturn [{ json: {\n workflow: err.workflow?.name || 'Pipeline v3.0',\n node: err.execution?.error?.node?.name || 'Unknown',\n message: err.execution?.error?.message || 'No message',\n severity: (err.execution?.error?.message||'').match(/timeout|ECONNRESET|429|503/) ? 'warning' : 'critical',\n retryable: ['ECONNRESET','ETIMEDOUT','429','503'].some(e => (err.execution?.error?.message||'').includes(e)),\n ts: new Date().toISOString()\n}}];"
},
"id": "d06e99ce-3c6a-4962-8b8c-c63d6d981226",
"name": "Format Error",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-624,
3200
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.telegram.org/bot{{$env.TELEGRAM_BOT_TOKEN}}/sendMessage",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "chat_id",
"value": "={{$env.TELEGRAM_CHAT_ID}}"
},
{
"name": "text",
"value": "\ud83d\udea8 *Pipeline Error*\n\n\ud83d\udd34 {{ $json.severity }}\n\ud83d\udccb Node: {{ $json.node }}\n\ud83d\udcac {{ $json.message }}\n\ud83d\udd04 Retryable: {{ $json.retryable }}\n\u23f0 {{ $json.ts }}"
},
{
"name": "parse_mode",
"value": "Markdown"
}
]
},
"options": {}
},
"id": "8807b1fd-1a81-44e9-a449-9e45b8e90cb4",
"name": "Error \u2192 Telegram",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-320,
3152
]
},
{
"parameters": {
"method": "POST",
"url": "https://sheets.googleapis.com/v4/spreadsheets/{{$env.PIPELINE_SHEET_ID}}/values/Errors!A:Z:append?valueInputOption=USER_ENTERED",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "values",
"value": "={{ JSON.stringify([[new Date().toISOString(), $json.severity, $json.node, $json.message, String($json.retryable)]]) }}"
}
]
},
"options": {}
},
"id": "cdcd880a-296b-425c-b24e-24ca0f50d771",
"name": "Error \u2192 Sheets",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-320,
3296
]
},
{
"parameters": {
"content": "# Smart Scoring & Routing",
"height": 540,
"width": 572,
"color": 3
},
"id": "334c8b5b-ec27-4de1-b7bf-37b1a933bd51",
"name": "\ud83d\udcca Smart Scoring & Routing",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-224,
1968
]
},
{
"parameters": {
"content": "# Competitive Intel\n\n",
"height": 328,
"width": 780,
"color": 6
},
"id": "579098e5-9d46-4221-af47-779350ab134c",
"name": "\ud83c\udfaf Competitive Intelligence",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
352,
1968
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nreturn items.map(item => {\n let ai;\n try {\n const text = item.json.output || item.json.text || JSON.stringify(item.json);\n const match = text.match(/\\{[\\s\\S]*\\}/);\n ai = match ? JSON.parse(match[0]) : {score:5, tier:'B', urgency:'warm'};\n } catch(e) { ai = {score:5, tier:'B', urgency:'warm', parseError: e.message}; }\n return { json: { ...item.json, ai, tier: ai.tier||'B', score: ai.score||5 } };\n});"
},
"id": "d7d6fb8b-490b-48b2-b642-82bb5d25dc90",
"name": "Parse AI Output",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-176,
2144
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.firecrawl.dev/v1/scrape",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "url",
"value": "={{ $json.ai?.competitorLikely ? 'https://www.' + $json.ai.competitorLikely.toLowerCase().replace(/[^a-z0-9]/g,'') + '.com' : '' }}"
}
]
},
"options": {
"timeout": 30000
}
},
"id": "7ecdc153-24f0-48b3-9f34-0c657219cb17",
"name": "Scrape Competitor Site",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
416,
2112
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nreturn items.map(item => {\n const content = (item.json.data?.markdown || '').substring(0, 2000);\n const pricing = content.match(/\\$\\d+[\\d,]*/g) || [];\n const features = ['automation','integration','API','dashboard','reporting','analytics','scheduling']\n .filter(f => content.toLowerCase().includes(f));\n return { json: { ...item.json, competitorAnalysis: {\n competitor: item.json.ai?.competitorLikely || 'unknown',\n pricingMentions: pricing.slice(0,5),\n featuresFound: features,\n weaknesses: features.length < 3 ? 'Limited feature set \u2014 room for displacement' : 'Feature-rich \u2014 focus on service/price differentiation'\n }}};\n});"
},
"id": "78b459d2-e0da-4425-8de2-9815c43a229b",
"name": "Analyze Competitor",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
592,
2112
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nreturn items.map(item => {\n const ai = item.json.ai || {};\n const comp = item.json.competitorAnalysis || {};\n const hook = ai.personalizationHook || 'your property management business';\n const pain = (ai.painPoints || ['automation'])[0];\n const objection = ai.objectionPrediction || '';\n\n return { json: { ...item.json,\n messages: {\n emailSubject: 'Quick question about ' + hook.substring(0, 60),\n emailBody: (ai.emailColdOpen || 'Hi,') + '\\n\\n' +\n 'I noticed ' + hook + ' and thought Otter Labs could help with ' + pain + '.\\n\\n' +\n (comp.weaknesses ? 'I know tools like ' + (comp.competitor||'your current setup') + ' can be limiting \u2014 ' : '') +\n 'we\\'ve been helping similar property managers save 15+ hours/week on operations.\\n\\n' +\n 'Would you be open to a quick 15-min chat?\\n\\n' +\n 'Book here: https://cal.com/YOUR_USERNAME/demo\\n\\nBest,\\nJordan @ Otter Labs',\n smsMessage: (ai.smsColdOpen || 'Hey!') + ' ' +\n 'Quick Q about ' + (item.json.lead?.company || 'your business') + ' \u2014 ' +\n 'we help PMs automate ops & save 15+ hrs/week. Worth a 15min chat? ' +\n 'cal.com/YOUR_USERNAME/demo',\n channel: ai.recommendedChannel || 'multi-channel'\n }\n }};\n});"
},
"id": "587bede6-a857-4549-95d4-5051c195dc1c",
"name": "Generate Messages",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
752,
2112
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "bcffd565-7185-49a2-972c-5849c39cb54d",
"name": "outreach.email.to",
"value": "={{ $json.lead?.email || $json.email }}",
"type": "string"
},
{
"id": "fe2680f2-4603-4260-8070-19c0e531f61c",
"name": "outreach.email.subject",
"value": "={{ $json.messages.emailSubject }}",
"type": "string"
},
{
"id": "e6e27c1a-157f-40c5-97eb-cdc6be0edd21",
"name": "outreach.email.body",
"value": "={{ $json.messages.emailBody }}",
"type": "string"
}
]
},
"options": {}
},
"id": "8ac831da-e946-4b67-ae01-d7b2d709d501",
"name": "Format Email Payload",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
928,
2000
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "64715a1e-0920-49ec-85d7-a2223caf8d85",
"name": "outreach.sms.to",
"value": "={{ $json.lead?.phone || $json.phone }}",
"type": "string"
},
{
"id": "a7de3c78-f73d-4cf3-961c-e89da31abde9",
"name": "outreach.sms.message",
"value": "={{ $json.messages.smsMessage }}",
"type": "string"
}
]
},
"options": {}
},
"id": "c8bdfe59-8785-4459-9e1e-3d3ae4c21b26",
"name": "Format SMS Payload",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
928,
2144
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": ""
},
"combinator": "and",
"conditions": [
{
"id": "1",
"leftValue": "={{ $json.tier }}",
"rightValue": "A",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"options": {}
},
"id": "ec156eb1-1ba2-455b-b4e5-b484cb8f6864",
"name": "Tier A?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
-16,
2144
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": ""
},
"combinator": "and",
"conditions": [
{
"id": "1",
"leftValue": "={{ $json.tier }}",
"rightValue": "B",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"options": {}
},
"id": "c0535294-6aa7-4c6f-91c6-311656bc3604",
"name": "Tier B?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
144,
2256
]
},
{
"parameters": {
"url": "=https://api.apify.com/v2/acts/tri_angle~airbnb-scraper/runs/last/dataset/items?token={{ $('Config').item.json.config.apifyToken }}",
"options": {}
},
"id": "8dfb6548-85f8-4e91-b58c-d11e22aa270c",
"name": "Fetch Results",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
80,
1392
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.apify.com/v2/acts/tri_angle~airbnb-scraper/runs?token={{$json.config.apifyToken}}",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "locationQueries",
"value": "=[\"Austin, TX\", \"Denver, CO\", \"Nashville, TN\"]"
},
{
"name": "maxListings",
"value": "={{ $json.config.maxLeads }}"
}
]
},
"options": {
"timeout": 120000
}
},
"id": "668cd161-74a1-456d-acd5-65e8a073d739",
"name": "Scrape Custom Endpoint",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-448,
1392
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.batchdata.com/api/v1/phone/skip-trace",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "requests",
"value": "=[{\"name\": \"{{ $json.name || $json.person?.name }}\", \"address\": \"{{ $json.address || \"\" }}\"}]"
}
]
},
"options": {
"timeout": 20000
}
},
"id": "c554f6cf-c386-446b-bcbf-684a7843335a",
"name": "Phone enrich and validate",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
848,
1728
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.firecrawl.dev/v1/scrape",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "httpHeaderAuth",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "url",
"value": "={{ $json.website || $json.person?.organization?.website_url || '' }}"
}
]
},
"options": {
"timeout": 30000
}
},
"id": "a9bf3bda-8545-4613-9488-5af0d1d80eb5",
"name": "Firecrawl",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1008,
1728
],
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const items = $input.all();\nreturn items.map(item => {\n const addr = (item.json.lead?.address || item.json.address || '').toLowerCase();\n let tz = 'America/New_York';\n if (addr.match(/\\b(ca|wa|or|nv|az)\\b|los angeles|san francisco|seattle|phoenix|denver/)) tz = 'America/Los_Angeles';\n else if (addr.match(/\\b(tx|il|mn|wi|mo|co)\\b|chicago|dallas|austin|denver|nashville/)) tz = 'America/Chicago';\n else if (addr.match(/\\b(co|mt|ut|nm)\\b/)) tz = 'America/Denver';\n \n const offsets = {'America/New_York':-5,'America/Chicago':-6,'America/Denver':-7,'America/Los_Angeles':-8};\n const offset = offsets[tz] || -5;\n const optimalHourUTC = 10 - offset; // 10am local\n const now = new Date();\n let waitHrs = optimalHourUTC - now.getUTCHours();\n if (waitHrs <= 0) waitHrs += 24;\n const sendDate = new Date(now.getTime() + waitHrs * 3600000);\n const day = sendDate.getUTCDay();\n if (day === 0) waitHrs += 24;\n if (day === 6) waitHrs += 48;\n \n return { json: { ...item.json, timing: { tz, optimalHourUTC, waitHours: Math.max(0.5, waitHrs), sendAt: new Date(now.getTime() + waitHrs*3600000).toISOString() } } };\n});"
},
"id": "99f90682-c301-46cb-a38a-3304f6145231",
"name": "Calculate Optimal Send Time",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-960,
2784
]
},
{
"parameters": {
"amount": "={{ $json.timing?.waitHours || 1 }}",
"unit": "hours"
},
"id": "465bdade-ab87-4d95-a43c-575fe756a3ee",
"name": "Smart Wait",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
-784,
2784
]
},
{
"parameters": {
"amount": 3
},
"id": "4dabd751-97a7-42b1-ae5b-d864a734163f",
"name": "SMS Rate Limit",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
-288,
2624
]
},
{
"parameters": {
"amount": 30
},
"id": "a662a96a-9839-45cb-839c-feae0082aaff",
"name": "LinkedIn Rate Limit",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
-288,
2944
]
},
{
"parameters": {},
"id": "84bfde37-26bc-4128-bc79-a7ce5f517444",
"name": "Merge Outreach Results",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
656,
2800
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.twenty.com/graphql",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "query",
"value": "mutation CreateLead($input: PersonCreateInput!) { createPerson(data: $input) { id } }"
},
{
"name": "variables",
"value": "={{ JSON.stringify({input: {name: {firstName: ($json.lead?.name||'').split(' ')[0], lastName: ($json.lead?.name||'').split(' ').slice(1).join(' ')}, emails: {primaryEmail: $json.lead?.email||''}, phones: {primaryPhone: $json.lead?.phone||''}}}) }}"
}
]
},
"options": {
"timeout": 10000
}
},
"id": "3cc65564-d6ec-4111-ba68-4f9a1bc6c4be",
"name": "Update Twenty CRM",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
848,
2800
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nconst m = {\n total: items.length,\n enrichRate: Math.round(items.filter(i => i.json.lead?.email).length / Math.max(items.length,1) * 100),\n tiers: {A:0, B:0, C:0},\n avgScore: 0,\n channels: {},\n ts: new Date().toISOString()\n};\nlet sum = 0;\nitems.forEach(i => {\n m.tiers[i.json.tier||'C']++;\n sum += i.json.score||0;\n const ch = i.json.ai?.recommendedChannel||'unknown';\n m.channels[ch] = (m.channels[ch]||0)+1;\n});\nm.avgScore = Math.round(sum/Math.max(items.length,1)*10)/10;\nreturn [{json: m}];"
},
"id": "f5d39e59-cf8c-4980-9e98-289959a01db8",
"name": "Calculate Metrics",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1008,
2800
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.telegram.org/bot{{$env.TELEGRAM_BOT_TOKEN}}/sendMessage",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "chat_id",
"value": "={{$env.TELEGRAM_CHAT_ID}}"
},
{
"name": "text",
"value": "\ud83d\udcc8 *Pipeline v3.0 Report*\n\n\ud83d\udcca Processed: {{ $json.total }}\n\u2705 Enrichment: {{ $json.enrichRate }}%\n\ud83d\udccb Avg Score: {{ $json.avgScore }}\n\n\ud83c\udfc6 Tier A: {{ $json.tiers.A }}\n\ud83d\udce7 Tier B: {{ $json.tiers.B }}\n\ud83d\udce6 Tier C: {{ $json.tiers.C }}\n\n\u23f0 {{ $json.ts }}"
},
{
"name": "parse_mode",
"value": "Markdown"
}
]
},
"options": {}
},
"id": "d3a7bde0-74c3-4e55-b6b1-b99e1584ecd4",
"name": "Telegram Report",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1184,
2800
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nreturn items.map(item => {\n const lead = item.json.lead || item.json;\n const timing = item.json.timing || {};\n const ai = item.json.ai || {};\n \n // Determine industry/vertical\n const company = (lead.company || '').toLowerCase();\n const category = (lead.category || '').toLowerCase();\n const siteContent = (lead.siteContent || '').toLowerCase();\n \n let industry = 'general';\n if (category.includes('property') || company.includes('property') || siteContent.includes('property management')) {\n industry = 'property-management';\n } else if (category.includes('vacation') || siteContent.includes('short-term') || siteContent.includes('airbnb') || siteContent.includes('str')) {\n industry = 'str-hosting';\n } else if (category.includes('laundro') || company.includes('laundro') || siteContent.includes('laundromat')) {\n industry = 'laundromat';\n } else if (category.includes('clean') || siteContent.includes('cleaning service')) {\n industry = 'cleaning';\n }\n \n // Determine send window based on timezone\n const tz = timing.tz || 'America/New_York';\n let sendWindow = 'morning'; // default 9-11am\n const hour = timing.optimalHourUTC || 15;\n if (hour >= 12 && hour < 17) sendWindow = 'afternoon';\n if (hour >= 17) sendWindow = 'evening';\n \n // Build campaign name: {industry}_{sendWindow}_{date}\n const today = new Date();\n const weekNum = Math.ceil((today.getDate()) / 7);\n const monthNames = ['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'];\n const campaignName = `${industry}_${sendWindow}_${monthNames[today.getMonth()]}${today.getFullYear()}_w${weekNum}`;\n \n // Map to Instantly campaign config\n const campaignConfigs = {\n 'property-management': {\n subject_lines: [\n 'Quick question about {{first_name}}\\'s property ops',\n '{{company_name}} \u2014 saving 15+ hrs/week on management',\n 'Automating the busywork at {{company_name}}'\n ],\n from_name: 'Jordan @ Otter Labs',\n daily_limit: 30,\n wait_days_between: 3\n },\n 'str-hosting': {\n subject_lines: [\n 'Your STR listings \u2014 quick thought',\n '{{first_name}}, automating guest comms at scale',\n 'Saw {{company_name}} on Airbnb \u2014 quick question'\n ],\n from_name: 'Jordan @ Otter Labs',\n daily_limit: 25,\n wait_days_between: 4\n },\n 'laundromat': {\n subject_lines: [\n 'Quick question about {{company_name}}',\n '{{first_name}} \u2014 modernizing laundromat ops',\n 'Saw {{company_name}} \u2014 thought of something'\n ],\n from_name: 'Jordan @ Otter Labs',\n daily_limit: 20,\n wait_days_between: 5\n },\n 'general': {\n subject_lines: [\n 'Quick question for {{first_name}}',\n '{{company_name}} \u2014 thought you\\'d want to see this',\n 'Saving time at {{company_name}}'\n ],\n from_name: 'Jordan @ Otter Labs',\n daily_limit: 25,\n wait_days_between: 3\n }\n };\n \n const config = campaignConfigs[industry] || campaignConfigs['general'];\n \n // Pick send time schedule based on window\n const schedules = {\n 'morning': { start_hour: '09:00', end_hour: '11:00' },\n 'afternoon': { start_hour: '13:00', end_hour: '15:00' },\n 'evening': { start_hour: '16:00', end_hour: '18:00' }\n };\n \n return { json: {\n ...item.json,\n campaign: {\n name: campaignName,\n industry: industry,\n sendWindow: sendWindow,\n timezone: tz,\n schedule: schedules[sendWindow] || schedules['morning'],\n config: config,\n // Custom variables for this lead\n customVars: {\n first_name: (lead.name || '').split(' ')[0] || '',\n last_name: (lead.name || '').split(' ').slice(1).join(' ') || '',\n company_name: lead.company || '',\n email: lead.email || '',\n personalization_hook: ai.personalizationHook || '',\n pain_point: (ai.painPoints || ['automation'])[0] || '',\n cold_open: ai.emailColdOpen || '',\n email_subject: item.json.outreach?.email?.subject || item.json.messages?.emailSubject || config.subject_lines[0],\n email_body: item.json.outreach?.email?.body || item.json.messages?.emailBody || '',\n booking_link: 'https://cal.com/YOUR_USERNAME/demo',\n tier: item.json.tier || 'A',\n score: String(item.json.score || 0)\n }\n }\n }};\n});"
},
"id": "b0f58ba8-4869-4f30-8e38-79663f86c56e",
"name": "Determine Campaign",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-512,
2784
]
},
{
"parameters": {
"url": "=https://api.instantly.ai/api/v2/campaigns?api_key={{$env.INSTANTLY_API_KEY}}&search={{ encodeURIComponent($json.campaign.name) }}&limit=1",
"options": {
"timeout": 10000
}
},
"id": "8be657a2-54d6-40d4-8500-d5f1d73055e3",
"name": "Check Campaign Exists",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-320,
2784
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": ""
},
"combinator": "and",
"conditions": [
{
"id": "1",
"leftValue": "={{ $json.data?.length > 0 || $json.campaigns?.length > 0 || $json.length > 0 }}",
"rightValue": "true",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
},
"options": {}
},
"id": "7ece9592-efdc-4093-a3fe-14ea363e6e2d",
"name": "Campaign Exists?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
-144,
2784
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.instantly.ai/api/v1/campaign/add",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "api_key",
"value": "={{$env.INSTANTLY_API_KEY}}"
},
{
"name": "name",
"value": "={{ $json.campaign.name }}"
}
]
},
"options": {
"timeout": 15000
}
},
"id": "0a588abe-5a6f-4c50-905d-59c54d2762f1",
"name": "Create Campaign",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
32,
2864
]
},
{
"parameters": {
"jsCode": "const items = $input.all();\nreturn items.map(item => {\n // Try to get campaign ID from various response formats\n const d = item.json;\n let campaignId = d.id || d.campaign_id || \n (d.data && d.data[0]?.id) || \n (d.campaigns && d.campaigns[0]?.id) ||\n (Array.isArray(d) && d[0]?.id) || '';\n \n return { json: { ...item.json, campaignId } };\n});"
},
"id": "4ed02832-c841-4614-b3a9-9a4233a13ccd",
"name": "Extract Campaign ID",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
32,
2688
]
},
{
"parameters": {},
"id": "a3261510-18bd-4706-9f4c-12eb31db1a7d",
"name": "Merge Campaign Path",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
208,
2784
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.instantly.ai/api/v1/lead/add",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "api_key",
"value": "={{$env.INSTANTLY_API_KEY}}"
},
{
"name": "campaign_id",
"value": "={{ $json.campaignId }}"
},
{
"name": "email",
"value": "={{ $json.campaign.customVars.email }}"
},
{
"name": "first_name",
"value": "={{ $json.campaign.customVars.first_name }}"
},
{
"name": "last_name",
"value": "={{ $json.campaign.customVars.last_name }}"
},
{
"name": "company_name",
"value": "={{ $json.campaign.customVars.company_name }}"
},
{
"name": "custom_variables",
"value": "={{ JSON.stringify({personalization_hook: $json.campaign.customVars.personalization_hook, pain_point: $json.campaign.customVars.pain_point, cold_open: $json.campaign.customVars.cold_open, email_subject: $json.campaign.customVars.email_subject, email_body: $json.campaign.customVars.email_body, booking_link: $json.campaign.customVars.booking_link, tier: $json.campaign.customVars.tier, score: $json.campaign.customVars.score}) }}"
}
]
},
"options": {
"timeout": 10000
}
},
"id": "92889070-8f78-47f5-b57f-030ed4c1d441",
"name": "Add Lead to Campaign",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
400,
2784
]
},
{
"parameters": {
"method": "POST",
"url": "ottersend",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "id",
"value": "={{$env.PHANTOMBUSTER_AGENT_ID}}"
},
{
"name": "argument",
"value": "={{ JSON.stringify({profileUrl: $json.lead?.linkedin || ''}) }}"
}
]
},
"options": {}
},
"id": "29d4b9a4-eb0d-49f9-a682-4be581bb6983",
"name": "LinkedIn",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-480,
2944
]
},
{
"parameters": {
"method": "POST",
"url": "ottersend",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "to",
"value": "={{ $json.outreach?.sms?.to || $json.lead?.phone }}"
},
{
"name": "content",
"value": "={{ $json.outreach?.sms?.message || $json.messages?.smsMessage }}"
},
{
"name": "from",
"value": "={{$env.OPENPHONE_NUMBER}}"
}
]
},
"options": {
"timeout": 10000
}
},
"id": "2cf2bf6e-995e-4d36-9d17-a664f5f30c5a",
"name": "Send SMS",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-464,
2624
]
},
{
"parameters": {
"fieldsToAggregate": {
"fieldToAggregate": [
{}
]
},
"options": {}
},
"type": "n8n-nodes-base.aggregate",
"typeVersion": 1,
"position": [
1168,
2176
],
"id": "90ad6375-97f0-4928-905e-469f4f2277f6",
"name": "Aggregate"
},
{
"parameters": {
"content": "# Prep data\n",
"height": 540,
"width": 236,
"color": 3
},
"id": "dcc97702-24f2-44cd-9d7d-01d70f36a1af",
"name": "\ud83d\udcca Smart Scoring & Routing1",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
1136,
1968
]
}
],
"connections": {
"Scrape Scheduler": {
"main": [
[
{
"node": "Config",
"type": "main",
"index": 0
}
]
]
},
"Config": {
"main": [
[
{
"node": "Scrape Google Maps",
"type": "main",
"index": 0
},
{
"node": "Scrape Custom Endpoint",
"type": "main",
"index": 0
},
{
"node": "Scrape Yelp Directory",
"type": "main",
"index": 0
}
]
]
},
"Scrape Google Maps": {
"main": [
[
{
"node": "Wait for Scrapes",
"type": "main",
"index": 0
}
]
]
},
"Scrape Yelp Directory": {
"main": [
[
{
"node": "Wait for Scrapes",
"type": "main",
"index": 0
}
]
]
},
"Wait for Scrapes": {
"main": [
[
{
"node": "Fetch Google Maps Results",
"type": "main",
"index": 0
},
{
"node": "Fetch Results",
"type": "main",
"index": 0
},
{
"node": "Fetch Yelp Results",
"type": "main",
"index": 0
}
]
]
},
"Fetch Google Maps Results": {
"main": [
[
{
"node": "Merge Scraped Leads",
"type": "main",
"index": 0
}
]
]
},
"Fetch Yelp Results": {
"main": [
[
{
"node": "Merge Scraped Leads",
"type": "main",
"index": 0
}
]
]
},
"Merge Scraped Leads": {
"main": [
[
{
"node": "Normalize Scraped Data",
"type": "main",
"index": 0
}
]
]
},
"Normalize Scraped Data": {
"main": [
[
{
"node": "AI Scrape Validator",
"type": "main",
"index": 0
}
]
]
},
"Scrape Validator Model": {
"ai_languageModel": [
[
{
"node": "AI Scrape Validator",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Scrape Validator Think": {
"ai_tool": [
[
{
"node": "AI Scrape Validator",
"type": "ai_tool",
"index": 0
}
]
]
},
"AI Scrape Validator": {
"main": [
[
{
"node": "Filter Valid Leads",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger": {
"main": [
[
{
"node": "Merge All Sources",
"type": "main",
"index": 0
}
]
]
},
"Filter Valid Leads": {
"main": [
[
{
"node": "Merge All Sources",
"type": "main",
"index": 1
}
]
]
},
"Merge All Sources": {
"main": [
[
{
"node": "Deduplicate Leads",
"type": "main",
"index": 0
}
]
]
},
"Deduplicate Leads": {
"main": [
[
{
"node": "Process in Batches",
"type": "main",
"index": 0
}
]
]
},
"Process in Batches": {
"main": [
[
{
"node": "Enrich: Apollo",
"type": "main",
"index": 0
}
]
]
},
"Enrich: Apollo": {
"main": [
[
{
"node": "Has Email?",
"type": "main",
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.
anthropicApihttpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
This workflow streamlines lead generation and nurturing by automating the intake of new leads via webhook, enriching them with detailed intelligence using an AI agent powered by Anthropic's Claude model, and initiating personalised multichannel outreach to boost conversion rates. It's designed for sales and marketing teams handling high volumes of prospects, saving hours of manual research and follow-up. The key step involves the AI agent analysing enriched data to predict optimal engagement timing and craft tailored messages, integrating seamlessly with your CRM for logging interactions.
Use this when scaling lead pipelines for B2B sales where data enrichment and AI-driven personalisation can significantly improve response rates, such as in tech or consulting firms. Avoid it for low-volume or highly regulated industries needing strict compliance checks, as the automation assumes standard data handling. Common variations include swapping the Anthropic integration for OpenAI or adding Slack notifications for real-time alerts on high-potential leads.
About this workflow
Lead Pipeline v3.0. Uses httpRequest, agent, lmChatAnthropic, toolThink. Webhook trigger; 77 nodes.
Source: https://github.com/jslizar/builder-lab/blob/dac901bc94368095e42e48185c9bb3f1c5c8e529/automations/n8n-workflows/lead-pipeline-v3.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.
🧠 Gwen – The AI Voice Marketing Agent Gwen is your intelligent voice-powered marketing assistant built in n8n. She combines the power of OpenAI, ElevenLabs, and automation workflows to handle content
Tired of grinding out YouTube content? This n8n workflow turns AI into your personal video factory—creating engaging, faceless shorts on autopilot. Perfect for creators, marketers, or side-hustlers lo
Faceless YouTube Generator. Uses httpRequest, limit, googleDrive, googleSheets. Webhook trigger; 49 nodes.
This workflow turns your WhatsApp Business number into a 24/7 AI-powered customer assistant — without any third-party chatbot platform. It receives incoming WhatsApp messages via Evolution API, unders
This workflow automates end-to-end marketing campaign management for digital marketing teams and agencies executing multi-channel strategies. It solves the complex challenge of coordinating personaliz