This workflow corresponds to n8n.io template #10061 — we link there as the canonical source.
This workflow follows the Gmail → 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": "nppmYxp46CaRqogp",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Candidate Nurturing Automation & Multi-Channel Follow-Up Flow",
"tags": [
{
"id": "iOQBFJ1QN7ogrHfc",
"name": "Old Template",
"createdAt": "2025-11-03T13:48:41.053Z",
"updatedAt": "2025-11-03T13:48:41.053Z"
},
{
"id": "crTs3uLd5lOJp7ZC",
"name": "Candidate Nurturing Automation & Multi-Channel Follow-Up Flow",
"createdAt": "2025-11-03T13:50:30.978Z",
"updatedAt": "2025-11-03T13:50:30.978Z"
}
],
"nodes": [
{
"id": "f43837bf-0e61-4130-96ba-b51eda44b7e8",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-688,
32
],
"parameters": {
"path": "receving-new-candidate",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "1877b58c-9f73-46b8-90d7-604fdce2eb6a",
"name": "Extract age",
"type": "n8n-nodes-base.dateTime",
"position": [
-272,
32
],
"parameters": {
"units": [
"year"
],
"endDate": "={{ $now }}",
"options": {},
"operation": "getTimeBetweenDates",
"startDate": "={{ $json.birthday }}",
"outputFieldName": "yearsOld"
},
"typeVersion": 2
},
{
"id": "690a5dba-a7ea-4967-b52e-8efecbfc3535",
"name": "Getting the AI content",
"type": "n8n-nodes-base.set",
"position": [
352,
32
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "24cb25da-c26e-4fbd-9729-17f64f6fdbdf",
"name": "content",
"type": "string",
"value": "={{ $json.message.content }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "bef64d83-4074-4ebe-82a1-4511aa1de6f8",
"name": "Separating information",
"type": "n8n-nodes-base.code",
"position": [
-480,
32
],
"parameters": {
"jsCode": "// Gets the body of the first item\nconst body = $input.item.json.body || {};\n\n// Function to keep only numbers (removes spaces, parentheses, dashes etc.)\nconst onlyNumbers = (value) => {\n if (!value) return \"\";\n return String(value).replace(/\\D+/g, \"\");\n};\n\nreturn [\n {\n json: {\n vacancy_id: body.vacancy_id || \"\",\n name: body.name || \"\",\n email: body.email || \"\",\n vacancy: body.vacancy || \"\",\n phone: onlyNumbers(body.phone), // formatted phone\n birthday: body.birthday || \"\",\n location: body.location || \"\"\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "cc3d9f50-9dac-43e4-8dec-a87c02c5ade8",
"name": "Separating messages per days",
"type": "n8n-nodes-base.code",
"position": [
608,
32
],
"parameters": {
"jsCode": "// Gets the content of the first item\nconst content = $input.item.json.content || \"\";\n\n// Splits into parts by the \"|\" character and trims spaces\nlet parts = content.split('|').map(p => (p || \"\").trim());\n\n// Ensures there are exactly 3 parts (no undefined)\nwhile (parts.length < 3) {\n parts.push(\"\");\n}\n\n// Safely extracts the parts\nconst [day1, day3, day7] = parts.slice(0, 3);\n\n// Returns exactly in the requested format\nreturn [\n {\n json: {\n day1,\n day3,\n day7\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "212f1062-ca17-4e25-a835-2fa99c30b04b",
"name": "Wait for more 4 days",
"type": "n8n-nodes-base.wait",
"position": [
816,
1072
],
"parameters": {
"amount": 4
},
"typeVersion": 1.1
},
{
"id": "28ada4b6-be55-485f-a0f7-c276c70d0f73",
"name": "Wait for more 2 days",
"type": "n8n-nodes-base.wait",
"position": [
816,
640
],
"parameters": {
"amount": 2
},
"typeVersion": 1.1
},
{
"id": "f173591e-d525-48bb-a4c2-a6ee750bc5f6",
"name": "No Operation, do nothing",
"type": "n8n-nodes-base.noOp",
"notes": "Your workflow has reach the end, you can costumize however you want",
"position": [
1552,
1072
],
"parameters": {},
"typeVersion": 1
},
{
"id": "be95e50d-5ff0-45c6-bef4-50bce1fc2a5b",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-848,
-544
],
"parameters": {
"width": 1056,
"height": 432,
"content": "## How it works\n\nThis workflow receives candidate data through a Recrutei Webhook, cleans the information, extracts the candidate\u2019s age when available, and sends these details to an AI model to generate three nurturing messages (Day 1, Day 3, Day 7).\nThe resulting text is split into separate messages, and each one is scheduled for delivery using timed waits. After each wait period, the workflow sends the appropriate message through WhatsApp and Gmail.\nEverything runs automatically once the webhook receives the initial payload.\n\n## Setup steps\n\nConfigure the Webhook node and test it once to initialize data.\n- In Separating information, confirm the field mappings match your incoming payload.\n- In Extract age, ensure the birthday format matches your source system.\n- In Message Model, add your API credentials and connect to the MCP tool.\n- In Getting the AI content, set the model, prompt, and input variables.\n- For WhatsApp and Gmail nodes, authenticate both accounts and fill in sender details.\n- Adjust wait durations if your nurturing schedule changes.\n- Run a full test with a dummy candidate to confirm message flow and timing."
},
"typeVersion": 1
},
{
"id": "593883e8-f36c-4a41-affb-1758594808ce",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-736,
-80
],
"parameters": {
"color": 6,
"width": 624,
"height": 336,
"content": "## Input & Data Preparation\nThis section receives the webhook payload, extracts the relevant candidate fields, cleans the data, and calculates age when available.\n"
},
"typeVersion": 1
},
{
"id": "58e6a956-6754-4e16-b9a0-1c6187d9f4e4",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-112,
-80
],
"parameters": {
"color": 7,
"width": 880,
"height": 336,
"content": "## AI Generation & Message Split\nHere the workflow sends candidate + job data to the AI model and receives the 3 nurturing messages in a single string."
},
"typeVersion": 1
},
{
"id": "6104d0c7-6d4f-4a13-a228-ec8b850553df",
"name": "MCP Recrutei",
"type": "@n8n/n8n-nodes-langchain.mcpClientTool",
"position": [
64,
144
],
"parameters": {
"options": {},
"endpointUrl": "your_recrutei_mcp_url"
},
"typeVersion": 1.2
},
{
"id": "99497950-08cd-4787-b0c6-ed49bb591fd9",
"name": "AI Recruitment Assistant",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
0,
32
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "GPT-4.1-MINI"
},
"options": {},
"messages": {
"values": [
{
"content": "=ID Vacancy: {{ $('Separating information').item.json.vacancy_id }}\n\nCandidate name: {{ $('Separating information').item.json.name }}\n\nCandidate age (years): {{ $('Extract age').item.json.yearsOld.years }}\n\nJob title: {{ $('Separating information').item.json.vacancy }}\n\nCompany name (signature):\n\nAcknowledge that the candidate applied for the position.\n\nAdapt the tone based on the age (if available):\n\n<25 years \u2192 focus on learning and opportunities.\n\n25\u201340 years \u2192 focus on career growth and challenges.\n\n40+ years \u2192 focus on experience and contribution.\n\nIf age is not available \u2192 use a neutral and inclusive message."
},
{
"role": "system",
"content": "You are an AI assistant specialized in recruitment communication.\nYour objective is to create exactly three nurturing messages, in plain text, for candidates who applied to a job opening.\n\nThe messages must follow this schedule:\n\nDay 1: thank-you and reinforcement of the company\u2019s interest.\n\nDay 3: friendly reminder reinforcing that the process is still active and highlighting one benefit of the role.\n\nDay 7: final reinforcement, inviting the candidate to stay attentive and showing that the company values their application.\n\nMANDATORY RULES\n\nUse ONLY the candidate data provided by the user.\n\nNever query MCP for candidates.\n\nThe candidate always exists.\n\nPersonal data comes only from the user prompt.\n\nYou may query MCP ONLY for vacancy/job information.\n\nMANDATORY AND INFLEXIBLE FORMAT\n\nThe response may contain line breaks, but must follow exactly this format:\n\n[day 1 message] |\n[day 3 message] |\n[day 7 message]\n\nThat is:\n\nEach message may have multiple paragraphs or line breaks.\n\nThe character | must be at the end of message 1 and at the end of message 2.\n\nMessage 3 MUST NOT end with |.\n\nNothing before and nothing after the three messages.\n\nLength\n\nTotal between 150 and 200 words.\n\nEach message must have 50 to 70 words.\n\n\nProfessional, empathetic and natural tone\n\nPersonalize candidate name, age (if available) and job title\n\nNo HTML\n\nNo emojis\n\nNo sensitive data\n\nNo guarantees of approval\n\nSign only if the company name is provided\n\nMandatory self-validation\n\nBefore sending, verify internally:\n\nThe response contains exactly two pipes, each one at the end of message 1 and 2.\n\nThe language needs to be (EN-US)\n\nEach message has real content.\n\nThere is no text after the third message.\n\nTotal of 150 to 200 words per message.\n\nMake the format of thhe message well written for e-mails\n\nThere is nothing besides the three messages.\n\nIf any rule fails, rewrite internally until you are 100% correct."
}
]
}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.8
},
{
"id": "7c932b66-090c-41e7-9dc8-235766561c03",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
768,
-80
],
"parameters": {
"color": 6,
"width": 944,
"height": 432,
"content": "## Day 1 Sending \nThis group sends the Day 1 nurturing message immediately through WhatsApp (**Evolution API**) and Gmail.\nThe merge node ensures both channels process the correct next message."
},
"typeVersion": 1
},
{
"id": "19ce6d6f-b851-4744-9a11-d416a66e9598",
"name": "Message WhatsApp day1",
"type": "n8n-nodes-base.httpRequest",
"notes": "Refer to EvolutionAPI docs: https://doc.evolution-api.com/v1/api-reference/message-controller/send-text",
"onError": "continueRegularOutput",
"position": [
1152,
32
],
"parameters": {
"url": "=https://{server-url}/message/sendText/{instance}",
"method": "POST",
"options": {},
"jsonBody": "={\n \"number\": {{ JSON.stringify($('Separating information').item.json.phone) }},\n \"text\": {{ JSON.stringify($json.day1) }},\n \"delay\": 1200,\n \"quoted\": {\n \"key\": {\n \"id\": \"MESSAGE_ID\"\n },\n \"message\": {\n \"conversation\": \"CONTENT_MESSAGE\"\n }\n },\n \"linkPreview\": false,\n \"mentionsEveryOne\": false,\n \"mentioned\": [\n {{ JSON.stringify($('Separating information').item.json.phone) }}\n ]\n} ",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "=your_api_key"
}
]
}
},
"executeOnce": true,
"retryOnFail": true,
"typeVersion": 4.2,
"alwaysOutputData": true
},
{
"id": "b68ae456-fe0e-4c24-9fea-1526b93aa820",
"name": "Message Gmail day1",
"type": "n8n-nodes-base.gmail",
"position": [
1152,
192
],
"parameters": {
"sendTo": "={{ $('Separating information').item.json.email }}",
"message": "={{ $json.day1 }}",
"options": {
"senderName": "your_company",
"appendAttribution": false
},
"subject": "=Applying for the vacancy {{ $('Separating information').item.json.vacancy }}",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"executeOnce": true,
"typeVersion": 2.1
},
{
"id": "496347a3-2e5b-4bd1-8533-982364516857",
"name": "Message WhatsApp day3",
"type": "n8n-nodes-base.httpRequest",
"notes": "Refer to EvolutionAPI docs: https://doc.evolution-api.com/v1/api-reference/message-controller/send-text",
"onError": "continueRegularOutput",
"position": [
1152,
464
],
"parameters": {
"url": "=https://{server-url}/message/sendText/{instance}",
"method": "POST",
"options": {},
"jsonBody": "={\n \"number\": {{ JSON.stringify($('Separating information').item.json.phone) }},\n \"text\": {{ JSON.stringify($('Separating messages per days').item.json.day3) }},\n \"delay\": 1200,\n \"quoted\": {\n \"key\": {\n \"id\": \"MESSAGE_ID\"\n },\n \"message\": {\n \"conversation\": \"CONTENT_MESSAGE\"\n }\n },\n \"linkPreview\": false,\n \"mentionsEveryOne\": false,\n \"mentioned\": [\n {{ JSON.stringify($('Separating information').item.json.phone) }}\n ]\n} ",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "=your_api_key"
}
]
}
},
"executeOnce": true,
"retryOnFail": true,
"typeVersion": 4.2,
"alwaysOutputData": true
},
{
"id": "13adaf0b-dd45-4357-ad0a-562ca6875bfd",
"name": "Message Gmail day3",
"type": "n8n-nodes-base.gmail",
"position": [
1152,
640
],
"parameters": {
"sendTo": "={{ $('Separating information').item.json.email }}",
"message": "={{ $('Separating messages per days').item.json.day3 }}",
"options": {
"senderName": "your_company",
"appendAttribution": false
},
"subject": "=Applying for the vacancy {{ $('Separating information').item.json.vacancy }}",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"executeOnce": true,
"typeVersion": 2.1
},
{
"id": "de468f87-39f0-4896-bb59-e3fe5626047a",
"name": "Message WhatsApp day7",
"type": "n8n-nodes-base.httpRequest",
"notes": "Refer to EvolutionAPI docs: https://doc.evolution-api.com/v1/api-reference/message-controller/send-text",
"onError": "continueRegularOutput",
"position": [
1152,
896
],
"parameters": {
"url": "=https://{server-url}/message/sendText/{instance}",
"method": "POST",
"options": {},
"jsonBody": "={\n \"number\": {{ JSON.stringify($('Separating information').item.json.phone) }},\n \"text\": {{ JSON.stringify($('Separating messages per days').item.json.day7) }},\n \"delay\": 1200,\n \"quoted\": {\n \"key\": {\n \"id\": \"MESSAGE_ID\"\n },\n \"message\": {\n \"conversation\": \"CONTENT_MESSAGE\"\n }\n },\n \"linkPreview\": false,\n \"mentionsEveryOne\": false,\n \"mentioned\": [\n {{ JSON.stringify($('Separating information').item.json.phone) }}\n ]\n} ",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "=your_api_key"
}
]
}
},
"executeOnce": true,
"retryOnFail": true,
"typeVersion": 4.2,
"alwaysOutputData": true
},
{
"id": "d57e0e8c-705b-4360-b947-68a9c9055708",
"name": "Message Gmail day7",
"type": "n8n-nodes-base.gmail",
"position": [
1152,
1072
],
"parameters": {
"sendTo": "={{ $('Separating information').item.json.email }}",
"message": "={{ $('Separating messages per days').item.json.day7 }}",
"options": {
"senderName": "your_company",
"appendAttribution": false
},
"subject": "=Applying for the vacancy {{ $('Separating information').item.json.vacancy }}",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"executeOnce": true,
"typeVersion": 2.1
},
{
"id": "7985cdf6-8e7d-419b-ab6a-f890055d0691",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
768,
352
],
"parameters": {
"color": 7,
"width": 944,
"height": 464,
"content": "## Day 3 Sending\nAfter a 2-day wait, the workflow delivers the Day 3 message via WhatsApp and Gmail and merges outputs for consistency."
},
"typeVersion": 1
},
{
"id": "0a58e888-7f08-4287-bd27-7dc02f0e4b8a",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
768,
800
],
"parameters": {
"color": 6,
"width": 944,
"height": 432,
"content": "## Day 7 Sending\nAfter a 4-day delay, the workflow sends the final nurturing message.\nThe last node simply ends the execution without additional actions."
},
"typeVersion": 1
},
{
"id": "663fc2ff-4f47-4c19-a808-71e32d2e4869",
"name": "Merge correct next node",
"type": "n8n-nodes-base.merge",
"position": [
1552,
176
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "e35e8d14-cd3e-4abc-b8a6-957adc60c8a4",
"name": "Merge correct next node1",
"type": "n8n-nodes-base.merge",
"position": [
1552,
624
],
"parameters": {},
"typeVersion": 3.2
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "a5048791-eb35-4d5b-ac69-bf47e0e631ba",
"connections": {
"Webhook": {
"main": [
[
{
"node": "Separating information",
"type": "main",
"index": 0
}
]
]
},
"Extract age": {
"main": [
[
{
"node": "AI Recruitment Assistant",
"type": "main",
"index": 0
}
]
]
},
"MCP Recrutei": {
"ai_tool": [
[
{
"node": "AI Recruitment Assistant",
"type": "ai_tool",
"index": 0
}
]
]
},
"Message Gmail day1": {
"main": [
[
{
"node": "Merge correct next node",
"type": "main",
"index": 1
}
]
]
},
"Message Gmail day3": {
"main": [
[
{
"node": "Merge correct next node1",
"type": "main",
"index": 1
}
]
]
},
"Message Gmail day7": {
"main": [
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
]
]
},
"Wait for more 2 days": {
"main": [
[
{
"node": "Message WhatsApp day3",
"type": "main",
"index": 0
},
{
"node": "Message Gmail day3",
"type": "main",
"index": 0
}
]
]
},
"Wait for more 4 days": {
"main": [
[
{
"node": "Message WhatsApp day7",
"type": "main",
"index": 0
},
{
"node": "Message Gmail day7",
"type": "main",
"index": 0
}
]
]
},
"Message WhatsApp day1": {
"main": [
[
{
"node": "Merge correct next node",
"type": "main",
"index": 0
}
]
]
},
"Message WhatsApp day3": {
"main": [
[
{
"node": "Merge correct next node1",
"type": "main",
"index": 0
}
]
]
},
"Message WhatsApp day7": {
"main": [
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
]
]
},
"Getting the AI content": {
"main": [
[
{
"node": "Separating messages per days",
"type": "main",
"index": 0
}
]
]
},
"Separating information": {
"main": [
[
{
"node": "Extract age",
"type": "main",
"index": 0
}
]
]
},
"Merge correct next node": {
"main": [
[
{
"node": "Wait for more 2 days",
"type": "main",
"index": 0
}
]
]
},
"AI Recruitment Assistant": {
"main": [
[
{
"node": "Getting the AI content",
"type": "main",
"index": 0
}
]
]
},
"Merge correct next node1": {
"main": [
[
{
"node": "Wait for more 4 days",
"type": "main",
"index": 0
}
]
]
},
"Separating messages per days": {
"main": [
[
{
"node": "Message WhatsApp day1",
"type": "main",
"index": 0
},
{
"node": "Message Gmail day1",
"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.
gmailOAuth2openAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automates the candidate nurturing process, solving the common problem of candidates losing interest or "ghosting" after an application. It keeps them engaged and informed by sending a personalized, multi-channel (WhatsApp & Gmail) sequence of follow-up messages…
Source: https://n8n.io/workflows/10061/ — 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.
Eu Clara – Funil Kiwify Completo. Uses postgres, openAi, httpRequest, gmail. Webhook trigger; 70 nodes.
User Signup & Verification: The workflow starts when a user signs up. It generates a verification code and sends it via SMS using Twilio. Code Validation: The user replies with the code. The workflow
Instantly map all internal URLs, perform AI-powered (ChatGPT) analysis, and deliver results in HTML via webhook, Google Sheets, or email. All from your own n8n instance!
Watch on Youtube▶️
Listens for completed Fireflies transcripts, qualifies whether a proposal is needed using OpenAI, drafts structured proposal content, populates a Google Doc template, converts to PDF, and sends it to