This workflow corresponds to n8n.io template #16192 — we link there as the canonical source.
This workflow follows the Airtable → HTTP Request 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": "e7oovuRIhpM5oh7u",
"name": "AI Voice Outreach System with Bolna, Groq & Airtable",
"tags": [],
"nodes": [
{
"id": "54c806cb-b4af-4593-8100-25c3910a9906",
"name": "Airtable \u2014 Get Contacts",
"type": "n8n-nodes-base.airtable",
"notes": "Picks up: (1) fresh records where Call Status is empty, AND (2) records marked No Answer - 1 that were last called 3+ days ago. Skips records with no phone number.",
"position": [
-1472,
624
],
"parameters": {
"base": {
"__rl": true,
"mode": "id",
"value": "YOUR_AIRTABLE_BASE_ID"
},
"table": {
"__rl": true,
"mode": "name",
"value": "Contacts"
},
"options": {},
"operation": "search"
},
"typeVersion": 2
},
{
"id": "e646a3e7-38d3-43ae-9fa9-b5da17bb321e",
"name": "Loop Over Contacts",
"type": "n8n-nodes-base.splitInBatches",
"notes": "Processes one college at a time. Output [0] = current item. Output [1] = done signal (not connected \u2014 workflow ends cleanly when all records are processed).",
"position": [
-1264,
624
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "c75e6a52-585c-4f57-8b3e-470a65aeb2fd",
"name": "Bolna.ai \u2014 Place Call",
"type": "n8n-nodes-base.httpRequest",
"notes": "Places outbound call via Bolna.ai to the coordinator's phone. PHONE FORMAT: Airtable must store numbers in international format e.g. +919876543210. Bolna returns a call_id used in the next step. Agent ID is already set.",
"position": [
-800,
624
],
"parameters": {
"url": "https://api.bolna.dev/call",
"method": "POST",
"options": {},
"jsonBody": "={\n\"agent_id\": \"YOUR_BOLNA_AGENT_ID\",\n\"recipient_phone_number\": \"{{ $json['Coordinator Phone'] }}\",\n \"user_data\": {\n \"name\": \"{{ $json['Coordinator Name'] }}\",\n \"college\": \"{{ $json['College Name'] }}\"\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.2
},
{
"id": "0e513954-0097-4e66-810f-ba53e52a4265",
"name": "Bolna \u2014 Get Call Status",
"type": "n8n-nodes-base.httpRequest",
"notes": "Fetches full call data from Bolna. Key fields used downstream: conversation_duration (to detect pickup) and transcript (for Claude analysis). IF THIS FAILS: Bolna might return 'id' instead of 'call_id' in the POST response \u2014 open this node and change call_id to id in the URL.",
"position": [
-400,
624
],
"parameters": {
"url": "=https://api.bolna.dev/agent/YOUR_BOLNA_AGENT_ID/execution/{{ $('Bolna.ai \u2014 Place Call').item.json.execution_id }}",
"options": {},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.2
},
{
"id": "73dcc71e-c023-4157-a4d9-0fb720a3c98d",
"name": "IF \u2014 Did They Pick Up?",
"type": "n8n-nodes-base.if",
"notes": "TRUE [0] = conversation_duration > 0 meaning someone spoke. FALSE [1] = null or 0 duration meaning no answer or busy. Number() safely converts null to 0.",
"position": [
-192,
624
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-picked-up",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ !!$json.transcript }}",
"rightValue": {}
}
]
}
},
"typeVersion": 2
},
{
"id": "f91d4c44-c90e-4eb3-9d9f-93f4f820c77d",
"name": "IF \u2014 Interested?",
"type": "n8n-nodes-base.if",
"notes": "TRUE [0] = Claude said YES (coordinator is interested). FALSE [1] = Claude said NO. caseSensitive is false so YES / yes / Yes all match.",
"position": [
256,
384
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-interested",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.choices[0].message.content }}",
"rightValue": "Interested"
}
]
}
},
"typeVersion": 2
},
{
"id": "5ca58a54-770e-426a-803a-894aa9e746f0",
"name": "Brevo \u2014 Opportunity Email",
"type": "n8n-nodes-base.httpRequest",
"notes": "ACTION REQUIRED: Replace PASTE_YOUR_BREVO_API_KEY_HERE with your actual Brevo API key. Find it at: Brevo dashboard \u2192 Settings \u2192 SMTP and API \u2192 API Keys. It starts with xkeysib-",
"position": [
480,
224
],
"parameters": {
"url": "https://api.brevo.com/v3/smtp/email",
"method": "POST",
"options": {},
"jsonBody": "={\n \"sender\": {\n \"name\": \"Your Company Name\",\n \"email\": \"your-email@example.com\"\n},\n \"to\": [\n {\n \"email\": \"{{ $('Loop Over Contacts').item.json['Coordinator Email'] }}\",\n \"name\": \"{{ $('Loop Over Contacts').item.json['Coordinator Name'] }}\"\n }\n],\n \"subject\": \"Thank You for Connecting \u2014 Placement Partnership Opportunity\",\n \"htmlContent\": \"<p>Hi {{ $('Loop Over Contacts').item.json['Coordinator Name'] }},</p><p>It was a pleasure speaking with you today.</p><p>We are a placement platform connecting candidates with verified job opportunities across multiple industries.</p><p>Our platform is designed for entry-level and skilled hiring, making it relevant for technical institutes and training centres.</p><p>We work with reputed organizations across manufacturing, automotive, electrical, operations, and technical sectors, with <strong>thousands of active openings</strong>.</p><p>Benefits for students:<br>\u2022 Free registration and job applications<br>\u2022 Direct interview opportunities from employers<br>\u2022 Regular alerts for new opportunities</p><p><strong>Website:</strong> <a href='https://your-platform-link.com'>https://your-platform-link.com</a></p><p>We would be happy to support your students with placement opportunities.</p><p>Looking forward to your collaboration.</p><p>Thank you<br>Your Name \u2014 Business Development<br>Your Company</p>\"\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "api-key",
"value": "YOUR_BREVO_API_KEY"
},
{
"name": "content-type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "11bbea61-0461-4962-9053-569332569545",
"name": "Brevo \u2014 Reassurance Email",
"type": "n8n-nodes-base.httpRequest",
"notes": "ACTION REQUIRED: Replace PASTE_YOUR_BREVO_API_KEY_HERE with your actual Brevo API key (same key as the Opportunity Email node).",
"position": [
480,
544
],
"parameters": {
"url": "https://api.brevo.com/v3/smtp/email",
"method": "POST",
"options": {},
"jsonBody": "={\n \"sender\": {\n \"name\": \"Your Company Name\",\n \"email\": \"your-email@example.com\"\n },\n \"to\": [\n {\n \"email\": \"{{ $('Loop Over Contacts').item.json['Coordinator Email'] }}\",\n \"name\": \"{{ $('Loop Over Contacts').item.json['Coordinator Name'] }}\"\n }\n],\n \"subject\": \"Thank You for Your Time\",\n \"htmlContent\": \"<p>Hi {{ $('Loop Over Contacts').item.json['Coordinator Name'] }},</p><p>Thank you for taking the time to speak with us today.</p><p>We understand there may not be an immediate requirement at your end. However, we would be happy to stay connected for any future placement support needs.</p><p>Our platform currently hosts <strong>thousands of job opportunities</strong> across various sectors including manufacturing, automotive, electrical, and operations.</p><p>For your reference:<br><a href='https://your-platform-link.com'>https://your-platform-link.com</a></p><p>We would be glad to collaborate whenever suitable in the future.</p><p>Thank you<br>Your Name \u2014 Business Development<br>Your Company</p>\"\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "api-key",
"value": "YOUR_BREVO_API_KEY"
},
{
"name": "content-type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "08fb9ade-ceb6-4f15-bbc3-f81f04574669",
"name": "IF \u2014 2nd Attempt?",
"type": "n8n-nodes-base.if",
"notes": "Checks the original Airtable record's Call Status. TRUE [0] = Call Status was 'No Answer - 1' meaning this is the SECOND failed attempt \u2192 Dead Contact. FALSE [1] = Call Status was empty, this is the FIRST failed attempt \u2192 send email, mark No Answer - 1, retry in 3 days.",
"position": [
32,
912
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-second-attempt",
"operator": {
"type": "number",
"operation": "gte"
},
"leftValue": "={{ Number($('Airtable \u2014 Get Contacts').item.json['Call Attempts'] ?? 0) }}",
"rightValue": 1
}
]
}
},
"typeVersion": 2
},
{
"id": "371f20fa-980c-42cc-a775-f9798ae20b4e",
"name": "Brevo \u2014 No Answer Email",
"type": "n8n-nodes-base.httpRequest",
"notes": "Sent after FIRST failed attempt. Informs the coordinator we tried calling and will try again in a few days. ACTION REQUIRED: Replace PASTE_YOUR_BREVO_API_KEY_HERE.",
"position": [
304,
1040
],
"parameters": {
"url": "https://api.brevo.com/v3/smtp/email",
"method": "POST",
"options": {},
"jsonBody": "={\n \"sender\": {\n \"name\": \"Your Company Name\",\n \"email\": \"your-email@example.com\"\n },\n \"to\": [\n {\n \"email\": \"{{ $('Loop Over Contacts').item.json['Coordinator Email'] }}\",\n \"name\": \"{{ $('Loop Over Contacts').item.json['Coordinator Name'] }}\"\n }\n],\n \"subject\": \"Follow-up \u2014 Placement Partnership Opportunity\",\n \"htmlContent\": \"<p>Hi {{ $('Loop Over Contacts').item.json['Coordinator Name'] }},</p><p>We tried reaching out to you today regarding our placement platform that supports technical institutes and training centres with verified job opportunities.</p><p>Our platform works with organizations across manufacturing, automotive, electrical, operations, and technical sectors, with <strong>thousands of active openings</strong> available for students.</p><p>The platform is completely free for students, including:<br>\u2022 Registration<br>\u2022 Job applications<br>\u2022 Interview opportunities through direct employer connect</p><p>You may explore the platform here:<br><a href='https://your-platform-link.com'>https://your-platform-link.com</a></p><p>We would be happy to connect with your institution and support your students with placement opportunities.</p><p>Looking forward to connecting with you soon.</p><p>Thank you<br>Your Name \u2014 Business Development<br>Your Company</p>\"\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "api-key",
"value": "YOUR_BREVO_API_KEY"
},
{
"name": "content-type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "032cb38a-1b77-4a5c-b33e-1193d35246a5",
"name": "Airtable update \u2014No answer",
"type": "n8n-nodes-base.httpRequest",
"position": [
560,
1040
],
"parameters": {
"url": "=https://api.airtable.com/v0/YOUR_AIRTABLE_BASE_ID/YOUR_TABLE_NAME/{{ $('Loop Over Contacts').item.json.id }}",
"method": "PATCH",
"options": {},
"jsonBody": "={\n \"fields\": {\n \"Call Attempts\": {{ ($json['Call Attempts'] || 0) + 1 }},\n \"Call Status\": \"No Answer\",\n \"Last Called\": \"{{ $now.toUTC().toISO().split('T')[0] }}\"\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.4
},
{
"id": "75200e99-8d47-4952-9d96-83b2b4692a06",
"name": "Airtable update \u2014 Interested",
"type": "n8n-nodes-base.httpRequest",
"position": [
912,
224
],
"parameters": {
"url": "=https://api.airtable.com/v0/YOUR_AIRTABLE_BASE_ID/YOUR_TABLE_NAME/{{ $('Airtable \u2014 Get Contacts').item.json.id }}",
"method": "PATCH",
"options": {},
"jsonBody": "={\n \"fields\": {\n \"Call Status\": \"Interested\",\n \"Last Called\": \"{{ $now.toISODate() }}\",\n \"Call Attempts\": {{ Number($('Airtable \u2014 Get Contacts').item.json['Call Attempts'] ?? 0) + 1 }}\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.4
},
{
"id": "70a3f5cf-6280-42af-a2f8-dfe277fd186e",
"name": "Airtable update - Not Interested",
"type": "n8n-nodes-base.httpRequest",
"position": [
688,
544
],
"parameters": {
"url": "=https://api.airtable.com/v0/YOUR_AIRTABLE_BASE_ID/YOUR_TABLE_NAME/{{ $('Airtable \u2014 Get Contacts').item.json.id }}",
"method": "PATCH",
"options": {},
"jsonBody": "={\n \"fields\": {\n \"Call Status\": \"Not Interested\",\n \"Call Attempts\": {{ ($('Airtable \u2014 Get Contacts').item.json['Call Attempts'] || 0) + 1 }},\n\"Last Called\": \"{{ $now.toUTC().toISO().split('T')[0] }}\"\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.4
},
{
"id": "9c405b67-7263-4817-905f-0b26534e195c",
"name": "Airtable update - Dead Contact",
"type": "n8n-nodes-base.httpRequest",
"position": [
576,
800
],
"parameters": {
"url": "=https://api.airtable.com/v0/YOUR_AIRTABLE_BASE_ID/YOUR_TABLE_NAME/{{ $('Airtable \u2014 Get Contacts').item.json.id }}",
"method": "PATCH",
"options": {},
"jsonBody": "={\n \"fields\": {\n \"Call Status\": \"Dead Contact\",\n \"Last Called\": \"{{ $now.toISODate() }}\",\n \"Call Attempts\": {{ Number($('Airtable \u2014 Get Contacts').item.json['Call Attempts'] ?? 0) + 1 }}\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.4
},
{
"id": "53e292da-aa39-4b6b-9a14-eb44af8f11cd",
"name": "Schedule \u2014 Daily 11AM IST",
"type": "n8n-nodes-base.scheduleTrigger",
"notes": "Runs every day at 9:00 AM IST (3:30 AM UTC). To test manually, use the Execute Workflow button instead.",
"position": [
-1680,
624
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 30 5 * * *"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "203d53a6-2f7f-46cd-81e0-a891c0975c2e",
"name": "Skip if Called Recently",
"type": "n8n-nodes-base.if",
"position": [
-1024,
624
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "abb660e6-aa1a-4dbf-8a30-0f4fdff6062a",
"operator": {
"type": "number",
"operation": "lt"
},
"leftValue": "={{ $json['Last Called'] ? $now.diff(DateTime.fromISO($json['Last Called']), 'days').days : 999 }}",
"rightValue": 1
},
{
"id": "19775958-1ab5-44f7-a7f7-db76bee7e693",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json['Call Status'] ?? '' }}",
"rightValue": "Interested "
},
{
"id": "4a831d44-7540-4b03-8a7e-59cdcd0e746b",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json['Call Status'] ?? '' }}",
"rightValue": "Not Interested"
},
{
"id": "c4773a33-3e9a-448d-954b-fa5b84211605",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json['Call Status'] ?? '' }}",
"rightValue": "Dead Contact"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "d6074b7d-13ca-4acf-bd3c-237316a9033e",
"name": "Brevo \u2014 Dead Contact Email",
"type": "n8n-nodes-base.httpRequest",
"position": [
336,
800
],
"parameters": {
"url": "https://api.brevo.com/v3/smtp/email",
"method": "POST",
"options": {},
"jsonBody": "={\n \"sender\": {\n \"name\": \"Your Company Name\",\n \"email\": \"your-email@example.com\"\n },\n \"to\": [\n {\n \"email\": \"{{ $('Loop Over Contacts').item.json['Coordinator Email'] }}\",\n \"name\": \"{{ $('Loop Over Contacts').item.json['Coordinator Name'] }}\"\n }\n],\n \"subject\": \"Introduction \u2014 Placement Support for Your Students\",\n \"htmlContent\": \"<p>Hi {{ $('Loop Over Contacts').item.json['Coordinator Name'] }},</p><p>We have attempted to connect with you regarding our placement support platform for technical institutes and entry-level candidates.</p><p>As we could not connect over call, we wanted to briefly share our details over email for your reference.</p><p>We are a pan-India job platform working with reputed employers across manufacturing, automotive, electrical, operations, and technical sectors. The platform currently hosts <strong>thousands of active job openings</strong> and is completely free for students to use.</p><p>Students can:<br>\u2022 Register directly on the platform<br>\u2022 Apply for jobs free of cost<br>\u2022 Receive interview opportunities from employers<br>\u2022 Get regular job alerts</p><p><strong>Platform Link:</strong> <a href='https://your-platform-link.com'>https://your-platform-link.com</a></p><p>If your institution would like to explore placement support in the future, we would be happy to connect at a convenient time.</p><p>Thank you<br>Your Name \u2014 Business Development<br>Your Company</p>\"\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"headerParameters": {
"parameters": [
{
"name": "api-key",
"value": "YOUR_BREVO_API_KEY"
},
{
"name": "content-type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.4
},
{
"id": "c6a42653-53f4-4e2e-9560-6ab649f7798b",
"name": "Groq \u2014 Analyze Transcript",
"type": "n8n-nodes-base.httpRequest",
"notes": "Uses Claude Haiku to read the Hindi/Hinglish/English transcript and return YES or NO. max_tokens is 10 because we only need one word back \u2014 keeps cost minimal (~$0.0001 per call analysis).",
"position": [
32,
384
],
"parameters": {
"url": "https://api.groq.com/openai/v1/chat/completions",
"method": "POST",
"options": {},
"jsonBody": "={\n \"model\": \"llama-3.3-70b-versatile\",\n \"max_tokens\": 1024,\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": {{ JSON.stringify(\"Analyze this call transcript and classify the outcome.\\n\\nTranscript:\\n\" + $json.transcript + \"\\n\\nRespond with ONLY one word:\\n- Interested (coordinator showed interest)\\n- NotInterested (coordinator declined)\\n- NoAnswer (call not picked up or unclear)\") }}\n }\n ]\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_GROQ_API_KEY"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "a249f92c-9884-4042-a34f-3d8b68e583cb",
"name": "Whatsapp msg from Twilio",
"type": "n8n-nodes-base.httpRequest",
"position": [
704,
224
],
"parameters": {
"url": "https://api.twilio.com/2010-04-01/Accounts/YOUR_TWILIO_ACCOUNT_SID/Messages.json",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "form-urlencoded",
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "From",
"value": "whatsapp:+YOUR_TWILIO_NUMBER"
},
{
"name": "To",
"value": "whatsapp:+91XXXXXXXXXX"
},
{
"name": "Body",
"value": "=Hi {{ $('Loop Over Contacts').item.json['Coordinator Name'] }},\\nWe are reaching out from our placement platform.\\n\\nYour students can register for free and access thousands of verified job opportunities across multiple industries.\\n\\nPlease share this registration link with your students:\\nhttps://your-platform-link.com\\n\\nFor any queries, feel free to reply to this message."
}
]
},
"genericAuthType": "httpBasicAuth"
},
"typeVersion": 4.4
},
{
"id": "133ebcab-1be1-4b66-8ee7-6428dcad5402",
"name": "Wait \u2014 180sec",
"type": "n8n-nodes-base.wait",
"notes": "Waits 5 minutes for the call to complete before fetching the result. Adjust if your calls are consistently shorter or longer. Most calls in call history were 2-4 minutes.",
"position": [
-592,
624
],
"parameters": {
"amount": 180
},
"typeVersion": 1.1
},
{
"id": "30e7cffd-6e06-4530-bc4b-1b5f2456d650",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2400,
256
],
"parameters": {
"color": 3,
"width": 624,
"height": 704,
"content": "## AI Voice Outreach System - Automated Calling with Bolna, Brevo, Groq & Airtable\n\n**Who is this for:**\nSales teams, BDE executives, recruiters, and outreach managers who need to call a large number of contacts daily and automatically follow up based on the call outcome (in short this workflow helps you to decreases manual calling ,which will save you time).\n\n**What it does:**\n- Runs daily on a schedule and pulls contacts from Airtable\n- Skips contacts that were already called recently or marked as final status\n- Places an AI voice call using Bolna.ai( We can use Vapi.ai as per need) to each contact\n- Waits for the call to finish, then checks if the person picked up\n- If picked up - Groq reads the call transcript and classifies it\n- Based on the result (Interested / Not Interested / No Answer / Dead Contact), sends the right follow-up email via Brevo and updates Airtable status accordingly\n- If interested: also sends a WhatsApp message via Twilio\n- Also supports 2nd-attempt retry logic for no-answer contacts\n\n**Setup needed:**\n1. Airtable account with a Contacts table (fields: Name, Phone, Email, Call Status, Call Attempts, Last Called)\n2. Bolna.ai account with a configured voice agent\n3. Groq API key (free at console.groq.com)\n4. Brevo API key (free at brevo.com)\n5. Twilio account with WhatsApp sandbox or approved number( of your own)\n6. Set your own time zone in the Schedule trigger node\n\nBuilt and tested by Utkarsh Kapoor"
},
"typeVersion": 1
},
{
"id": "7639fe87-0937-4eed-ab7b-c81779364de1",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1728,
256
],
"parameters": {
"color": 4,
"width": 832,
"height": 688,
"content": "## Scheduling & Data Fetch\n\n- Runs daily at a set time (according to you). \n\n- Pulls all contacts from Airtable, loops through them one by one, and skips anyone who was already called today or has a final status (Interested, Not Interested, Dead Contact)."
},
"typeVersion": 1
},
{
"id": "27cb2bb5-7f3a-4c42-9176-d21f4dd49370",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-848,
256
],
"parameters": {
"color": 6,
"width": 800,
"height": 688,
"content": "## AI Voice Calling\n\n- Places an outbound call via Bolna.ai using a pre-configured voice agent.\n\n- Waits 3 minutes for the call to complete, then fetches the call status and transcript. \n\n- And checks if the person actually picked up based on whether a transcript exists."
},
"typeVersion": 1
},
{
"id": "3c0f48ab-faaf-4795-8ad7-18440d9abfec",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"color": 2,
"width": 1104,
"height": 1280,
"content": "## AI Analysis & Follow-up Actions\nGroq AI reads the call transcript and classifies the outcome as Interested or Not Interested. Based on the results :\n- Interested : Sends opportunity email + WhatsApp message + updates Airtable\n- Not Interested : Sends reassurance email + updates Airtable\n- No Answer (1st attempt) : Sends follow-up email + marks for retry in 3 days\n- No Answer (2nd attempt) : Marks as Dead Contact + sends final email"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "0ead57a1-5b95-4e35-b682-422819477069",
"connections": {
"Wait \u2014 180sec": {
"main": [
[
{
"node": "Bolna \u2014 Get Call Status",
"type": "main",
"index": 0
}
]
]
},
"IF \u2014 Interested?": {
"main": [
[
{
"node": "Brevo \u2014 Opportunity Email",
"type": "main",
"index": 0
}
],
[
{
"node": "Brevo \u2014 Reassurance Email",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Contacts": {
"main": [
[],
[
{
"node": "Skip if Called Recently",
"type": "main",
"index": 0
}
]
]
},
"IF \u2014 2nd Attempt?": {
"main": [
[
{
"node": "Brevo \u2014 Dead Contact Email",
"type": "main",
"index": 0
}
],
[
{
"node": "Brevo \u2014 No Answer Email",
"type": "main",
"index": 0
}
]
]
},
"Bolna.ai \u2014 Place Call": {
"main": [
[
{
"node": "Wait \u2014 180sec",
"type": "main",
"index": 0
}
]
]
},
"Skip if Called Recently": {
"main": [
[],
[
{
"node": "Bolna.ai \u2014 Place Call",
"type": "main",
"index": 0
}
]
]
},
"IF \u2014 Did They Pick Up?": {
"main": [
[
{
"node": "Groq \u2014 Analyze Transcript",
"type": "main",
"index": 0
}
],
[
{
"node": "IF \u2014 2nd Attempt?",
"type": "main",
"index": 0
}
]
]
},
"Whatsapp msg from Twilio": {
"main": [
[
{
"node": "Airtable update \u2014 Interested",
"type": "main",
"index": 0
}
]
]
},
"Airtable \u2014 Get Contacts": {
"main": [
[
{
"node": "Loop Over Contacts",
"type": "main",
"index": 0
}
]
]
},
"Bolna \u2014 Get Call Status": {
"main": [
[
{
"node": "IF \u2014 Did They Pick Up?",
"type": "main",
"index": 0
}
]
]
},
"Brevo \u2014 No Answer Email": {
"main": [
[
{
"node": "Airtable update \u2014No answer",
"type": "main",
"index": 0
}
]
]
},
"Brevo \u2014 Opportunity Email": {
"main": [
[
{
"node": "Whatsapp msg from Twilio",
"type": "main",
"index": 0
}
]
]
},
"Brevo \u2014 Reassurance Email": {
"main": [
[
{
"node": "Airtable update - Not Interested",
"type": "main",
"index": 0
}
]
]
},
"Groq \u2014 Analyze Transcript": {
"main": [
[
{
"node": "IF \u2014 Interested?",
"type": "main",
"index": 0
}
]
]
},
"Schedule \u2014 Daily 11AM IST": {
"main": [
[
{
"node": "Airtable \u2014 Get Contacts",
"type": "main",
"index": 0
}
]
]
},
"Brevo \u2014 Dead Contact Email": {
"main": [
[
{
"node": "Airtable update - Dead Contact",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow runs daily to pull contacts from Airtable, place outbound AI voice calls via Bolna.ai, analyze call transcripts with Groq, then send follow-up emails through Brevo and (for interested contacts) a WhatsApp message via Twilio, while updating call status and attempts…
Source: https://n8n.io/workflows/16192/ — 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.
Prospection Sénégal - Email + WhatsApp/jour. Uses httpRequest, gmail, googleSheets. Scheduled trigger; 20 nodes.
This workflow is built for agencies, freelancers, and local service businesses who want to automate prospecting. If you sell services to local businesses -- web design, SEO, bookkeeping, HVAC -- this
Lumen - Outreach Audit & Send. Uses httpRequest, microsoftOutlook, telegram. Webhook trigger; 26 nodes.
This workflow is a powerful, two-phase system designed to automate the entire passive candidate sourcing and engagement cycle.
Every weekday morning, the workflow reads your prospect list from Google Sheets and cross-checks it against a send log — anyone already emailed is automatically skipped Each new contact is assigned on