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": "CallFlow \u2014 ElevenLabs Post-Call WhatsApp",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "elevenlabs-postcall",
"responseMode": "responseNode",
"options": {}
},
"id": "a1b2c3d4-0001-0001-0001-000000000001",
"name": "ElevenLabs Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
300
]
},
{
"parameters": {
"jsCode": "// ElevenLabs post-call webhook payload\nconst body = $input.first().json.body || $input.first().json;\n\n// Temel alanlar\nconst conversationId = body.conversation_id || '';\nconst agentId = body.agent_id || '';\nconst callDuration = body.call_duration_secs || 0;\nconst transcript = body.transcript || [];\nconst callSuccess = body.call_successful || false;\n\n// Telefon numaras\u0131\nconst metadata = body.metadata || {};\nconst clientData = body.conversation_initiation_client_data || {};\nconst rawPhone = metadata.phone_number\n || clientData.to_number\n || body.to_number\n || '';\nconst whatsappNumber = rawPhone.replace(/\\D/g, '');\n\n// Data collection\nconst dc = body.data_collection_results || {};\nconst customerName = dc.customer_name?.value || '';\nconst appointmentDate = dc.appointment_date?.value || '';\nconst appointmentTime = dc.appointment_time?.value || '';\nconst rawAddr = dc.appointment_address?.value || '';\nlet appointmentLat = dc.appointment_lat?.value ? parseFloat(dc.appointment_lat.value) : null;\nlet appointmentLng = dc.appointment_lng?.value ? parseFloat(dc.appointment_lng.value) : null;\n\n// \u2500\u2500 Adres koordinat m\u0131? \u00d6rn: \"39.994784, 32.768634\" \u2500\u2500\n// ElevenLabs bazen adres alan\u0131na koordinat yaz\u0131yor.\nconst COORD_RE = /^\\s*(-?\\d{1,3}\\.\\d+)\\s*,\\s*(-?\\d{1,3}\\.\\d+)\\s*$/;\nconst coordMatch = rawAddr.match(COORD_RE);\nlet appointmentAddr = rawAddr;\n\nif (coordMatch) {\n // Koordinatlar\u0131 parse et, adres metnini bo\u015falt\n appointmentLat = parseFloat(coordMatch[1]);\n appointmentLng = parseFloat(coordMatch[2]);\n appointmentAddr = ''; // harita mesaj\u0131yla g\u00f6nderilecek\n}\n\n// S\u00fcre format\u0131\nconst mins = Math.floor(callDuration / 60);\nconst secs = callDuration % 60;\nconst durationText = mins > 0 ? `${mins} dk ${secs} sn` : `${secs} sn`;\n\nreturn [{\n json: {\n conversationId,\n agentId,\n callDuration,\n durationText,\n callSuccess,\n whatsappNumber,\n customerName,\n appointmentDate,\n appointmentTime,\n appointmentAddr,\n appointmentLat,\n appointmentLng,\n hasAppointment: !!(appointmentDate || appointmentTime || appointmentLat),\n hasLocation: !!(appointmentLat && appointmentLng)\n }\n}];"
},
"id": "a1b2c3d4-0002-0002-0002-000000000002",
"name": "Veriyi \u0130\u015fle",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
480,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "cond-phone",
"leftValue": "={{ $json.whatsappNumber }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "notEmpty"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "a1b2c3d4-0003-0003-0003-000000000003",
"name": "Telefon var m\u0131?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
720,
300
]
},
{
"parameters": {
"method": "GET",
"url": "=https://supabase.lueratech.com/rest/v1/whatsapp_templates?is_active=eq.true&order=created_at.desc&limit=1",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "<redacted-credential>"
},
{
"name": "Authorization",
"value": "<redacted-credential>"
}
]
},
"options": {}
},
"id": "a1b2c3d4-0009-0009-0009-000000000009",
"name": "Supabase: Aktif \u015eablonu Al",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
960,
160
]
},
{
"parameters": {
"jsCode": "// Supabase'den gelen aktif \u015fablon\nconst templates = $input.first().json;\nconst callData = $('Veriyi \u0130\u015fle').first().json;\n\n// \u2500\u2500\u2500 Fallback: Supabase'de aktif \u015fablon yoksa bunu kullan \u2500\u2500\u2500\nconst FALLBACK = [\n '\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501',\n '\ud83e\udd16 *LUERA CallFlow*',\n '\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501',\n '',\n 'Merhaba *{{isim}}!* \ud83d\udc4b',\n '',\n 'AI asistan\u0131m\u0131zla g\u00f6r\u00fc\u015fmeniz ba\u015far\u0131yla tamamland\u0131. \u2705',\n '\u23f1 G\u00f6r\u00fc\u015fme s\u00fcresi: _{{sure}}_',\n '{{randevu_bolumu}}',\n '',\n 'Herhangi bir sorunuz i\u00e7in bizi aramaktan \u00e7ekinmeyin. \ud83d\ude0a',\n '',\n '_Te\u015fekk\u00fcrler, g\u00f6r\u00fc\u015fmek \u00fczere!_ \ud83d\ude4f',\n '*LUERA Ekibi*'\n].join('\\n');\n\n// \u015eablon i\u00e7eri\u011fini belirle (Supabase'den \"message\" veya \"content\" alan\u0131)\nlet templateContent = '';\nif (Array.isArray(templates) && templates.length > 0) {\n const tpl = templates[0];\n templateContent = tpl.message || tpl.content || '';\n}\nif (!templateContent.trim()) {\n templateContent = FALLBACK;\n}\n\n// Randevu b\u00f6l\u00fcm\u00fc \u2014 sadece veri varsa g\u00f6ster\nlet randevuBolumu = '';\nif (callData.appointmentDate || callData.appointmentTime || callData.hasLocation) {\n randevuBolumu = '\\n\ud83d\udcc5 *Randevu Bilgileriniz*\\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500';\n if (callData.appointmentDate) randevuBolumu += `\\n\ud83d\udcc6 Tarih: *${callData.appointmentDate}*`;\n if (callData.appointmentTime) randevuBolumu += `\\n\ud83d\udd50 Saat: *${callData.appointmentTime}*`;\n if (callData.appointmentAddr) {\n randevuBolumu += `\\n\ud83d\udccd Adres: ${callData.appointmentAddr}`;\n } else if (callData.hasLocation) {\n randevuBolumu += `\\n\ud83d\udccd _Konum a\u015fa\u011f\u0131da harita olarak payla\u015f\u0131ld\u0131_ \ud83d\udc47`;\n }\n}\n\n// M\u00fc\u015fteri ad\u0131 \u2014 bo\u015fsa nazik fallback\nconst isim = (callData.customerName || '').trim() || 'De\u011ferli M\u00fc\u015fterimiz';\n\n// De\u011fi\u015fken yerine koy (her iki adres format\u0131n\u0131 da destekle)\nconst messageText = templateContent\n .replace(/\\{\\{isim\\}\\}/gi, isim)\n .replace(/\\{\\{sure\\}\\}/gi, callData.durationText || '')\n .replace(/\\{\\{randevu_tarihi\\}\\}/gi, callData.appointmentDate || '')\n .replace(/\\{\\{randevu_saati\\}\\}/gi, callData.appointmentTime || '')\n .replace(/\\{\\{randevu_adresi\\}\\}/gi, callData.appointmentAddr || '')\n .replace(/\\{\\{adres\\}\\}/gi, callData.appointmentAddr || '')\n .replace(/\\{\\{randevu_bolumu\\}\\}/gi, randevuBolumu)\n .replace(/\\{\\{konusma_id\\}\\}/gi, callData.conversationId || '');\n\nreturn [{\n json: {\n ...callData,\n messageText\n }\n}];"
},
"id": "a1b2c3d4-0010-0010-0010-000000000010",
"name": "\u015eablonu \u0130\u015fle",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1200,
160
]
},
{
"parameters": {
"method": "POST",
"url": "=https://evoapi.lueratech.com/message/sendText/wms",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "yaCLHuAqSTS4CwUadOBhD23SYca2ZhF1"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"number\": \"{{ $json.whatsappNumber }}\",\n \"text\": {{ JSON.stringify($json.messageText) }}\n}",
"options": {}
},
"id": "a1b2c3d4-0004-0004-0004-000000000004",
"name": "WhatsApp Mesaj G\u00f6nder",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1440,
160
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "cond-loc",
"leftValue": "={{ $('\u015eablonu \u0130\u015fle').first().json.hasLocation }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equal"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "a1b2c3d4-0006-0006-0006-000000000006",
"name": "Konum var m\u0131?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
960,
380
]
},
{
"parameters": {
"method": "POST",
"url": "=https://evoapi.lueratech.com/message/sendLocation/wms",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "yaCLHuAqSTS4CwUadOBhD23SYca2ZhF1"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"number\": \"{{ $('\u015eablonu \u0130\u015fle').first().json.whatsappNumber }}\",\n \"name\": \"Randevu Konumu\",\n \"address\": \"{{ $('\u015eablonu \u0130\u015fle').first().json.appointmentAddr || 'Randevu Adresi' }}\",\n \"latitude\": {{ $('\u015eablonu \u0130\u015fle').first().json.appointmentLat }},\n \"longitude\": {{ $('\u015eablonu \u0130\u015fle').first().json.appointmentLng }}\n}",
"options": {}
},
"id": "a1b2c3d4-0005-0005-0005-000000000005",
"name": "Konum G\u00f6nder",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1200,
380
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={ \"status\": \"ok\", \"conversation_id\": \"{{ $('Veriyi \u0130\u015fle').first().json.conversationId }}\" }",
"options": {}
},
"id": "a1b2c3d4-0007-0007-0007-000000000007",
"name": "Webhook Yan\u0131tla",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1680,
270
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "{ \"status\": \"skipped\", \"reason\": \"no phone number\" }",
"options": {}
},
"id": "a1b2c3d4-0008-0008-0008-000000000008",
"name": "Telefon Yok \u2014 Atla",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
960,
520
]
},
{
"parameters": {
"method": "POST",
"url": "=https://supabase.lueratech.com/rest/v1/appointments",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "<redacted-credential>"
},
{
"name": "Authorization",
"value": "<redacted-credential>"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Prefer",
"value": "resolution=merge-duplicates"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"conversation_id\": {{ JSON.stringify($('Veriyi \u0130\u015fle').first().json.conversationId) }},\n \"customer_name\": {{ JSON.stringify($('Veriyi \u0130\u015fle').first().json.customerName || null) }},\n \"customer_phone\": {{ JSON.stringify($('Veriyi \u0130\u015fle').first().json.whatsappNumber || null) }},\n \"appointment_date\": {{ JSON.stringify($('Veriyi \u0130\u015fle').first().json.appointmentDate || null) }},\n \"appointment_time\": {{ JSON.stringify($('Veriyi \u0130\u015fle').first().json.appointmentTime || null) }},\n \"appointment_address\": {{ JSON.stringify($('Veriyi \u0130\u015fle').first().json.appointmentAddr || null) }},\n \"latitude\": {{ $('Veriyi \u0130\u015fle').first().json.appointmentLat || 'null' }},\n \"longitude\": {{ $('Veriyi \u0130\u015fle').first().json.appointmentLng || 'null' }},\n \"call_duration_secs\": {{ $('Veriyi \u0130\u015fle').first().json.callDuration || 0 }},\n \"agent_id\": {{ JSON.stringify($('Veriyi \u0130\u015fle').first().json.agentId || null) }},\n \"status\": \"confirmed\"\n}",
"options": {}
},
"id": "a1b2c3d4-0011-0011-0011-000000000011",
"name": "Supabase: Randevu Kaydet",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1680,
420
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "cond-appt",
"leftValue": "={{ $('Veriyi \u0130\u015fle').first().json.hasAppointment }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equal"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "a1b2c3d4-0012-0012-0012-000000000012",
"name": "Randevu var m\u0131?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1440,
380
]
}
],
"connections": {
"ElevenLabs Webhook": {
"main": [
[
{
"node": "Veriyi \u0130\u015fle",
"type": "main",
"index": 0
}
]
]
},
"Veriyi \u0130\u015fle": {
"main": [
[
{
"node": "Telefon var m\u0131?",
"type": "main",
"index": 0
}
]
]
},
"Telefon var m\u0131?": {
"main": [
[
{
"node": "Supabase: Aktif \u015eablonu Al",
"type": "main",
"index": 0
},
{
"node": "Konum var m\u0131?",
"type": "main",
"index": 0
}
],
[
{
"node": "Telefon Yok \u2014 Atla",
"type": "main",
"index": 0
}
]
]
},
"Supabase: Aktif \u015eablonu Al": {
"main": [
[
{
"node": "\u015eablonu \u0130\u015fle",
"type": "main",
"index": 0
}
]
]
},
"\u015eablonu \u0130\u015fle": {
"main": [
[
{
"node": "WhatsApp Mesaj G\u00f6nder",
"type": "main",
"index": 0
}
]
]
},
"WhatsApp Mesaj G\u00f6nder": {
"main": [
[
{
"node": "Webhook Yan\u0131tla",
"type": "main",
"index": 0
},
{
"node": "Randevu var m\u0131?",
"type": "main",
"index": 0
}
]
]
},
"Randevu var m\u0131?": {
"main": [
[
{
"node": "Supabase: Randevu Kaydet",
"type": "main",
"index": 0
}
],
[]
]
},
"Konum var m\u0131?": {
"main": [
[
{
"node": "Konum G\u00f6nder",
"type": "main",
"index": 0
}
],
[]
]
},
"Konum G\u00f6nder": {
"main": [
[
{
"node": "Webhook Yan\u0131tla",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [
"callflow",
"whatsapp",
"elevenlabs"
]
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
CallFlow — ElevenLabs Post-Call WhatsApp. Uses httpRequest. Webhook trigger; 12 nodes.
Source: https://github.com/furkanulgr/callflow/blob/7e933ad19094442d592de059f7e34e66344427da/n8n-callflow-workflow.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.
HR teams, IT Operations, and System Administrators managing employee onboarding at scale. It’s perfect if you use Odoo 18 to trigger account requests and need Redmine + GitLab accounts created instant
This workflow is a complete, production-ready solution for recovering abandoned carts in Shopify stores using a multi-channel, multi-touch approach. It automates personalized follow-ups via Email, SMS
qualiopi. Uses airtable, telegram, emailSend, httpRequest. Webhook trigger; 51 nodes.
This workflow automates end-to-end research analysis by coordinating multiple AI models—including NVIDIA NIM (Llama), OpenAI GPT-4, and Claude to analyze uploaded documents, extract insights, and gene
PsyCardv2. Uses executeCommand, telegram, readBinaryFile, googleDrive. Webhook trigger; 41 nodes.