This workflow corresponds to n8n.io template #15418 — we link there as the canonical source.
This workflow follows the Airtable → OpenAI 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 →
{
"id": "09jHGcO9nLmJc5IC",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "LeadFlow AI Qualification & Routing System",
"tags": [],
"nodes": [
{
"id": "70e562cb-be5d-44cf-927c-8da181943225",
"name": "Lead Intake Endpoint",
"type": "n8n-nodes-base.webhook",
"position": [
-416,
-304
],
"parameters": {
"path": "lead-capture",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "fb07ff4e-bd19-4557-a1b6-531e99415417",
"name": "Normalize Lead Data",
"type": "n8n-nodes-base.set",
"position": [
-208,
-304
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "20e7ddeb-7c25-4932-9c70-e3ee80d213f4",
"name": "Name",
"type": "string",
"value": "={{ $json.body.name }}"
},
{
"id": "b58d28e8-b0dd-4065-833e-eed3505dade1",
"name": "Email",
"type": "string",
"value": "={{ $json.body.email }}"
},
{
"id": "3e2c2a35-0f7d-403c-a0a5-62e1d06f3133",
"name": "Company",
"type": "string",
"value": "={{ $json.body.company }}"
},
{
"id": "e77e1d83-a373-484d-a58c-42356e25c112",
"name": "Message",
"type": "string",
"value": "={{ $json.body.message }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "e66fa1de-a345-46ef-8ed9-1bf2174b50f2",
"name": "Basic Lead Validation (Email + Message Check)",
"type": "n8n-nodes-base.if",
"position": [
-16,
-304
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "83547104-a8ff-4852-8e8c-a2052453e422",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.Email }}",
"rightValue": ""
},
{
"id": "e07d50eb-46d4-4751-a621-3d31c9ca3d31",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $json.Message.length }}",
"rightValue": 10
}
]
}
},
"typeVersion": 2.3
},
{
"id": "33a81f9c-cd31-4d23-b4eb-78cfc46c990d",
"name": "Check Existing Lead in Airtable",
"type": "n8n-nodes-base.airtable",
"position": [
304,
-320
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "appNQHdM1ceSscFxw",
"cachedResultUrl": "https://airtable.com/appNQHdM1ceSscFxw",
"cachedResultName": "Leads Database"
},
"table": {
"__rl": true,
"mode": "list",
"value": "tbl5uho2uJkXxBGTO",
"cachedResultUrl": "https://airtable.com/appNQHdM1ceSscFxw/tbl5uho2uJkXxBGTO",
"cachedResultName": "Leads"
},
"options": {},
"operation": "search",
"filterByFormula": "=LOWER({Email}) = LOWER(\"{{$json.Email}}\")"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.2,
"alwaysOutputData": true
},
{
"id": "a49c8666-aebb-435b-86f5-68037c77a59a",
"name": "New Lead Decision Gate",
"type": "n8n-nodes-base.if",
"position": [
528,
-320
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4b9984dd-f589-4123-9db3-f7772ff38a5d",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{$json.isEmpty()}}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "d4d1181b-2ac8-42db-bc1a-31c02c339e21",
"name": "AI Lead Scoring Engine",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
864,
-336
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {},
"responses": {
"values": [
{
"role": "system",
"content": "You are a lead qualification assistant."
},
{
"content": "=You are NOT a chatbot.\n\nYou are a strict data extraction engine inside an automation system.\n\nYou must NEVER:\n- ask questions\n- respond conversationally\n- give explanations\n\nYou MUST always output ONLY valid JSON.\n\nIf data is missing, still return JSON with default values.\n\n---\n\nINPUT:\nName: {{ $('Normalize Lead Data').item.json.Name }}\nMessage: {{ $('Normalize Lead Data').item.json.Message }}\n\n---\n\nOUTPUT FORMAT (STRICT):\n{\n \"score\": number (0-100),\n \"category\": \"Hot\" | \"Warm\" | \"Cold\",\n \"summary\": \"1 line only\"\n}\n\n---\n\nSCORING RULES:\n- Hot = clear intent to buy / hire / need service\n- Warm = interest but no urgency\n- Cold = no intent or unclear message\n\n---\n\nIMPORTANT:\nReturn ONLY JSON. No text. No markdown. No questions."
}
]
},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "60633b58-e2fa-4267-be3b-f2cbb92ca721",
"name": "AI Output Parser & Safety Handler",
"type": "n8n-nodes-base.code",
"position": [
1168,
-336
],
"parameters": {
"jsCode": "const raw = $input.first().json.output[0].content[0].text;\n\n// \ud83e\uddf9 Step 1: Clean markdown formatting (```json ... ```)\nlet cleaned = raw\n .replace(/```json/g, '')\n .replace(/```/g, '')\n .trim();\n\n// \ud83d\udee0 Step 2: Try parsing safely\nlet parsed;\ntry {\n parsed = JSON.parse(cleaned);\n} catch (e) {\n parsed = {\n score: 50,\n category: \"Warm\",\n summary: cleaned\n };\n}\n\n// \ud83e\uddea Step 3: Extra safety (edge cases)\nconst score = typeof parsed.score === \"number\" ? parsed.score : 50;\nconst category = [\"Hot\", \"Warm\", \"Cold\"].includes(parsed.category)\n ? parsed.category\n : \"Warm\";\nconst summary = parsed.summary || \"No summary available\";\n\n// \ud83d\ude80 Final output\nreturn [{\n json: {\n ...$json,\n leadScore: score,\n category: category,\n summary: summary\n }\n}];"
},
"typeVersion": 2
},
{
"id": "7ca0f5f3-d3de-48b0-95ff-c370ab9b6759",
"name": "High-Intent Lead Filter (Score > 70)",
"type": "n8n-nodes-base.if",
"position": [
1504,
-336
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "46aa4219-f569-4554-846b-1a874a8f849c",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $json.leadScore }}",
"rightValue": 70
}
]
}
},
"typeVersion": 2.3
},
{
"id": "20fdf696-606d-4109-a8e0-1e3686202c92",
"name": "Slack Hot Lead Notification",
"type": "n8n-nodes-base.slack",
"position": [
2048,
-352
],
"parameters": {
"text": "=New Hot Lead! \n\nName: {{ $json.fields.Name }}\nCompany: {{$json.fields.Company}} \nScore: {{$json.fields['Lead Score']}} \nSummary: {{$json.fields['AI Summary']}}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C0ALTQD6L0H",
"cachedResultName": "feature-addition"
},
"otherOptions": {
"includeLinkToWorkflow": false
}
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.4
},
{
"id": "32ee0031-6d95-4871-b748-d335ac38b907",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-496,
-528
],
"parameters": {
"color": 7,
"width": 704,
"height": 400,
"content": "## Lead Intake & Validation Layer\nThis section receives incoming leads from external forms or APIs. It extracts required fields like name, email, company and message, then validates them to ensure only meaningful and complete leads proceed further into the system."
},
"typeVersion": 1
},
{
"id": "40162517-cec1-4a98-83bf-4f54793098c4",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
240,
-528
],
"parameters": {
"color": 7,
"width": 528,
"height": 400,
"content": "## Lead Deduplication Layer\nThis section checks whether the lead already exists in Airtable using email matching. It prevents duplicate processing and ensures only new leads are passed forward for AI scoring and qualification."
},
"typeVersion": 1
},
{
"id": "cbf6c8c5-f005-4739-a389-09eef0dc0c5d",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
800,
-528
],
"parameters": {
"color": 7,
"width": 560,
"height": 400,
"content": "## AI Lead Intelligence Layer\nThis section uses AI to analyze the lead message and generate a score, category and summary. A safety parser ensures the AI output is always valid JSON and handles any unexpected response errors."
},
"typeVersion": 1
},
{
"id": "65a834ca-9342-4eb3-9c88-4d43779a419c",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1392,
-528
],
"parameters": {
"color": 7,
"width": 368,
"height": 400,
"content": "## Lead Qualification & Routing Layer\nThis section filters leads based on AI score. Only high-intent leads with score greater than 70 are considered qualified and sent forward for storage and sales notification."
},
"typeVersion": 1
},
{
"id": "c83115bb-9c5d-447b-9f6f-f5b851d8de1b",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1792,
-528
],
"parameters": {
"color": 7,
"width": 464,
"height": 400,
"content": "## CRM Storage & Sales Notification Layer\nThis section stores qualified leads in Airtable CRM for tracking and sends real-time Slack notifications to the sales team. It ensures instant visibility of hot leads for quick follow-up."
},
"typeVersion": 1
},
{
"id": "79328609-6ae3-41c5-8d26-421a563109d3",
"name": "Store Lead in Airtable CRM",
"type": "n8n-nodes-base.airtable",
"position": [
1872,
-352
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "appNQHdM1ceSscFxw",
"cachedResultUrl": "https://airtable.com/appNQHdM1ceSscFxw",
"cachedResultName": "Leads Database"
},
"table": {
"__rl": true,
"mode": "list",
"value": "tbl5uho2uJkXxBGTO",
"cachedResultUrl": "https://airtable.com/appNQHdM1ceSscFxw/tbl5uho2uJkXxBGTO",
"cachedResultName": "Leads"
},
"columns": {
"value": {
"Name": "={{ $('Normalize Lead Data').item.json.Name }}",
"Email": "={{ $('Normalize Lead Data').item.json.Email }}",
"Company": "={{ $('Normalize Lead Data').item.json.Company }}",
"Message": "={{ $('Normalize Lead Data').item.json.Message }}",
"AI Summary": "={{ $('AI Output Parser & Safety Handler').item.json.summary }}",
"Lead Score": "={{ $('AI Output Parser & Safety Handler').item.json.leadScore }}",
"Lead Category": "={{ $('AI Output Parser & Safety Handler').item.json.category }}"
},
"schema": [
{
"id": "Name",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Company",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Company",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Message",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Message",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Lead Score",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Lead Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Lead Category",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Lead Category",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "AI Summary",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "AI Summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Created At",
"type": "dateTime",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Created At",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "create"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "845c0de4-bb49-4c7b-8217-f65db0d63a66",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-496,
-960
],
"parameters": {
"width": 704,
"height": 400,
"content": "## Workflow Overview & Setup Guide\n\n\nThis workflow automatically captures, analyzes and routes leads using AI. It starts when a lead is submitted through a webhook. The system extracts and standardizes the lead data, then validates it to ensure required fields like email and message are present.\n\nNext, it checks Airtable to avoid duplicate leads. If the lead is new, it is sent to an AI model which evaluates the message and generates a lead score, category and summary. A safety layer ensures the AI output is always clean and usable.\n\nAfter scoring, the workflow filters only high-intent leads (score above 70). These qualified leads are stored in Airtable CRM for record-keeping. At the same time, a Slack notification is sent to the sales team so they can respond immediately.\n\n**Setup Steps:**\n**1.** Connect webhook endpoint to your form or API source.\n**2.** Configure Airtable base and table for lead storage.\n**3.** Add OpenAI credentials in n8n.\n**4.** Set Slack channel for notifications.\n**5.** Activate workflow and test with sample leads."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "1b162b56-c9c8-4a3f-8323-968227c06970",
"connections": {
"Normalize Lead Data": {
"main": [
[
{
"node": "Basic Lead Validation (Email + Message Check)",
"type": "main",
"index": 0
}
]
]
},
"Lead Intake Endpoint": {
"main": [
[
{
"node": "Normalize Lead Data",
"type": "main",
"index": 0
}
]
]
},
"AI Lead Scoring Engine": {
"main": [
[
{
"node": "AI Output Parser & Safety Handler",
"type": "main",
"index": 0
}
]
]
},
"New Lead Decision Gate": {
"main": [
[
{
"node": "AI Lead Scoring Engine",
"type": "main",
"index": 0
}
]
]
},
"Store Lead in Airtable CRM": {
"main": [
[
{
"node": "Slack Hot Lead Notification",
"type": "main",
"index": 0
}
]
]
},
"Check Existing Lead in Airtable": {
"main": [
[
{
"node": "New Lead Decision Gate",
"type": "main",
"index": 0
}
]
]
},
"AI Output Parser & Safety Handler": {
"main": [
[
{
"node": "High-Intent Lead Filter (Score > 70)",
"type": "main",
"index": 0
}
]
]
},
"High-Intent Lead Filter (Score > 70)": {
"main": [
[
{
"node": "Store Lead in Airtable CRM",
"type": "main",
"index": 0
}
]
]
},
"Basic Lead Validation (Email + Message Check)": {
"main": [
[
{
"node": "Check Existing Lead in Airtable",
"type": "main",
"index": 0
}
]
]
}
}
}
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.
airtableTokenApiopenAiApislackApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow captures leads via webhook, validates and deduplicates them, uses OpenAI to score and summarize intent and sends high-quality leads (score > 70) to Airtable and Slack for immediate sales action. Login to your n8n account and import this workflow Connect your…
Source: https://n8n.io/workflows/15418/ — 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.
AI-Powered Fake Review Detection Workflow Using n8n & Airtable. Uses httpRequest, airtable, openAi, slack. Webhook trigger; 27 nodes.
This workflow automatically monitors Facebook Group posts, analyzes them using AI, detects policy violations, logs incidents, notifies moderators and automatically hides high-severity posts to keep th
Recruitment Pipeline Automation. Uses airtable, openAi, emailSend, googleCalendar. Webhook trigger; 7 nodes.
This powerful n8n automation workflow is designed to execute advanced B2B lead enrichment and hyper-personalization for cold email outreach. By orchestrating a complex chain of data scraping, AI analy
This template is perfect for e-commerce entrepreneurs, marketers, agencies, and creative teams who want to turn simple product photos and short descriptions into professional flyers or product videos—