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": "Vitalis - Respuestas WhatsApp Inbound",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "twilio-inbound",
"responseMode": "responseNode",
"options": {}
},
"id": "node-wh-inbound",
"name": "Webhook Twilio",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
300
]
},
{
"parameters": {
"jsCode": "const body = $input.first().json.body ?? $input.first().json;\nconst fromRaw = body.From ?? body.from ?? '';\nconst msgBody = (body.Body ?? body.body ?? '').trim();\nconst buttonPayload = (body.ButtonPayload ?? body.buttonPayload ?? '').trim();\nconst respuesta = (buttonPayload || msgBody).toLowerCase();\nconst fromClean = fromRaw.replace('whatsapp:', '');\nlet intencion = 'desconocido';\nif (/^(1|si|s[i\u00ed]|confirmo|confirmado|ok|dale|perfecto|listo)$/i.test(respuesta)) intencion = 'confirmar';\nelse if (/^(2|no|cancelo|cancelado|cancela|no puedo)$/i.test(respuesta)) intencion = 'cancelar';\nelse if (/^(3|reagendar|reagen|otro horario|cambiar|cambio)$/i.test(respuesta)) intencion = 'reagendar';\nreturn [{ json: { from_raw: fromRaw, telefono: fromClean, respuesta, intencion } }];"
},
"id": "node-parse",
"name": "Parsear Respuesta",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
460,
300
]
},
{
"parameters": {
"method": "GET",
"url": "={{$env[\"SUPABASE_URL\"]}}/rest/v1/recordatorios_log",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "={{$env[\"SUPABASE_SERVICE_KEY\"]}}"
},
{
"name": "Authorization",
"value": "=Bearer {{$env[\"SUPABASE_SERVICE_KEY\"]}}"
}
]
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "select",
"value": "id,turno_id,centro_id"
},
{
"name": "telefono",
"value": "=eq.{{$json.telefono}}"
},
{
"name": "order",
"value": "created_at.desc"
},
{
"name": "limit",
"value": "1"
}
]
},
"options": {}
},
"id": "node-sb-log",
"name": "Buscar Log",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
680,
300
]
},
{
"parameters": {
"jsCode": "const logArr = $input.first().json;\nconst log = Array.isArray(logArr) ? logArr[0] : logArr;\nconst parsed = $('Parsear Respuesta').first().json;\nif (!log?.turno_id) return [{ json: { ...parsed, turno_id: null, error: 'no_log' } }];\nreturn [{ json: { ...parsed, turno_id: log.turno_id, centro_id: log.centro_id } }];"
},
"id": "node-combine",
"name": "Combinar",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
900,
300
]
},
{
"parameters": {
"dataType": "string",
"value1": "={{$json.intencion}}",
"rules": {
"rules": [
{
"value2": "confirmar",
"output": 0
},
{
"value2": "cancelar",
"output": 1
},
{
"value2": "reagendar",
"output": 2
}
]
},
"fallbackOutput": 3
},
"id": "node-switch",
"name": "Switch Intenci\u00f3n",
"type": "n8n-nodes-base.switch",
"typeVersion": 1,
"position": [
1120,
300
]
},
{
"parameters": {
"method": "PATCH",
"url": "={{$env[\"SUPABASE_URL\"]}}/rest/v1/turnos?id=eq.{{$json.turno_id}}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "={{$env[\"SUPABASE_SERVICE_KEY\"]}}"
},
{
"name": "Authorization",
"value": "=Bearer {{$env[\"SUPABASE_SERVICE_KEY\"]}}"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Prefer",
"value": "return=minimal"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "{\"estado\": \"confirmado\"}",
"options": {}
},
"id": "node-confirmar",
"name": "Confirmar Turno",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1340,
120
]
},
{
"parameters": {
"method": "PATCH",
"url": "={{$env[\"SUPABASE_URL\"]}}/rest/v1/turnos?id=eq.{{$json.turno_id}}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "={{$env[\"SUPABASE_SERVICE_KEY\"]}}"
},
{
"name": "Authorization",
"value": "=Bearer {{$env[\"SUPABASE_SERVICE_KEY\"]}}"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Prefer",
"value": "return=minimal"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "{\"estado\": \"cancelado\"}",
"options": {}
},
"id": "node-cancelar",
"name": "Cancelar Turno",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1340,
280
]
},
{
"parameters": {
"method": "POST",
"url": "=https://api.twilio.com/2010-04-01/Accounts/{{$env[\"TWILIO_ACCOUNT_SID\"]}}/Messages.json",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Basic {{Buffer.from($env[\"TWILIO_ACCOUNT_SID\"] + ':' + $env[\"TWILIO_AUTH_TOKEN\"]).toString('base64')}}"
},
{
"name": "Content-Type",
"value": "application/x-www-form-urlencoded"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/x-www-form-urlencoded",
"body": "=From={{encodeURIComponent($env[\"TWILIO_FROM_WHATSAPP\"])}}&To={{encodeURIComponent($json.from_raw)}}&Body={{encodeURIComponent('\u00a1Entendido! Pod\u00e9s escribirnos directamente para reagendar: https://wa.me/543624075957?text=Hola%2C+quiero+reagendar+mi+turno')}}",
"options": {}
},
"id": "node-reagendar",
"name": "Responder Reagendar",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1340,
440
]
},
{
"parameters": {
"respondWith": "text",
"responseBody": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response></Response>",
"options": {
"responseCode": 200
}
},
"id": "node-respond-ok",
"name": "Responder Twilio",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
1560,
280
]
}
],
"connections": {
"Webhook Twilio": {
"main": [
[
{
"node": "Parsear Respuesta",
"type": "main",
"index": 0
}
]
]
},
"Parsear Respuesta": {
"main": [
[
{
"node": "Buscar Log",
"type": "main",
"index": 0
}
]
]
},
"Buscar Log": {
"main": [
[
{
"node": "Combinar",
"type": "main",
"index": 0
}
]
]
},
"Combinar": {
"main": [
[
{
"node": "Switch Intenci\u00f3n",
"type": "main",
"index": 0
}
]
]
},
"Switch Intenci\u00f3n": {
"main": [
[
{
"node": "Confirmar Turno",
"type": "main",
"index": 0
}
],
[
{
"node": "Cancelar Turno",
"type": "main",
"index": 0
}
],
[
{
"node": "Responder Reagendar",
"type": "main",
"index": 0
}
],
[]
]
},
"Confirmar Turno": {
"main": [
[
{
"node": "Responder Twilio",
"type": "main",
"index": 0
}
]
]
},
"Cancelar Turno": {
"main": [
[
{
"node": "Responder Twilio",
"type": "main",
"index": 0
}
]
]
},
"Responder Reagendar": {
"main": [
[
{
"node": "Responder Twilio",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Vitalis - Respuestas WhatsApp Inbound. Uses httpRequest. Webhook trigger; 9 nodes.
Source: https://github.com/gkovalek/agendavitalis/blob/main/n8n/workflow-3-respuestas-inbound.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.
Flujowhatsapp. Uses @aldinokemal2104/n8n-nodes-gowa, postgres, httpRequest. Webhook trigger; 65 nodes.
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
WF_UNIFIED_LEGAL_AUTOMATION. Uses googleSheets, httpRequest, telegram, telegramTrigger. Webhook trigger; 53 nodes.
Backbrief: transcripts (Zoom webhook -> Slack + vault). Uses httpRequest, slack. Webhook trigger; 52 nodes.