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": "whatsapp-router",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "whatsapp-webhook",
"responseMode": "responseNode",
"options": {}
},
"id": "webhook-node",
"name": "WhatsApp Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
250,
300
]
},
{
"parameters": {
"functionCode": "// Intent Detection with stricter regex\nconst message = $json.body?.body || $json.body?.message || '';\nconst from = $json.body?.from || $json.body?.sender || '';\n\nconst intents = [\n { name: 'MENU', patterns: [/^(menu|bantuan|help|mulai|start|halo|hai|p)$/i] },\n { name: 'PIN_REQUEST', patterns: [/pin baru|lupa pin|reset pin|minta pin/i] },\n { name: 'TOGGLE', patterns: [/^(tutup lapak|buka lapak|tutuplapak|bukalapak)$/i] },\n { name: 'STATUS', patterns: [/^(status|cek berkas|cek status|tracking)/i] },\n { name: 'UMKM_JASA', patterns: [/^(umkm|jasa|produk|tukang|usaha)/i] },\n { name: 'LOKER', patterns: [/^(loker|lowongan|kerja|pekerjaan)/i] },\n { name: 'SYARAT', patterns: [/^(syarat|ketentuan|prosedur|cara)/i] },\n { name: 'COMPLAINT', patterns: [/^(pengaduan|lapor|keluhan|komplain)/i] }\n];\n\nlet detectedIntent = 'UNKNOWN';\n\nfor (const intent of intents) {\n for (const pattern of intent.patterns) {\n if (pattern.test(message)) {\n detectedIntent = intent.name;\n break;\n }\n }\n if (detectedIntent !== 'UNKNOWN') break;\n}\n\nreturn {\n json: {\n from: from,\n message: message,\n intent: detectedIntent,\n timestamp: new Date().toISOString()\n }\n};"
},
"id": "intent-detection",
"name": "Detect Intent",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
450,
300
]
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"string": [
{
"value1": "={{$json.intent}}",
"operation": "equals",
"value2": "MENU"
}
]
},
"renameOutput": true,
"outputKey": "menu"
},
{
"conditions": {
"string": [
{
"value1": "={{$json.intent}}",
"operation": "equals",
"value2": "UMKM_JASA"
}
]
},
"renameOutput": true,
"outputKey": "umkm_jasa"
},
{
"conditions": {
"string": [
{
"value1": "={{$json.intent}}",
"operation": "equals",
"value2": "LOKER"
}
]
},
"renameOutput": true,
"outputKey": "loker"
},
{
"conditions": {
"string": [
{
"value1": "={{$json.intent}}",
"operation": "equals",
"value2": "TOGGLE"
}
]
},
"renameOutput": true,
"outputKey": "toggle"
},
{
"conditions": {
"string": [
{
"value1": "={{$json.intent}}",
"operation": "equals",
"value2": "STATUS"
}
]
},
"renameOutput": true,
"outputKey": "status"
},
{
"conditions": {
"string": [
{
"value1": "={{$json.intent}}",
"operation": "equals",
"value2": "COMPLAINT"
}
]
},
"renameOutput": true,
"outputKey": "complaint"
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"id": "switch-node",
"name": "Route by Intent",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
650,
300
]
},
{
"parameters": {
"functionCode": "// Menu Response - 4 Main Options\nconst menuText = `\ud83d\udccc MENU KECAMATAN BESUK\n1\ufe0f\u20e3 Layanan Administrasi\n2\ufe0f\u20e3 UMKM & Jasa\n3\ufe0f\u20e3 Lowongan Kerja\n4\ufe0f\u20e3 Pengaduan\n\nKetik angka atau kata kunci.\n\ud83d\udcde Kantor Kecamatan Besuk\nSenin-Jumat: 08.00-15.00 WIB\n_Ketik MENU kapan saja untuk kembali_`;\n\nreturn {\n json: {\n to: $json.from,\n message: menuText\n }\n};"
},
"id": "menu-response",
"name": "Send Menu",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
850,
150
]
},
{
"parameters": {
"functionCode": "// UMKM & Jasa Prompt\nconst promptText = `\ud83d\udecd\ufe0f UMKM & JASA KECAMATAN BESUK\n\nSilakan ketik produk atau jasa yang dicari.\nContoh:\n- UMKM Kerupuk\n- Jasa Tukang Piket\n- UMKM Madu\n\nKetik MENU untuk kembali.`;\n\nreturn {\n json: {\n to: $json.from,\n message: promptText\n }\n};"
},
"id": "umkm-jasa-prompt",
"name": "UMKM & Jasa Prompt",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
850,
250
]
},
{
"parameters": {
"functionCode": "// Loker Prompt\nconst promptText = `\ud83c\udfd7\ufe0f LOWONGAN KERJA KECAMATAN BESUK\n\nSilakan ketik jenis pekerjaan yang dicari.\nContoh:\n- Loker Sopir\n- Loker Admin\n- Kerja Sales\n\nKetik MENU untuk kembali.`;\n\nreturn {\n json: {\n to: $json.from,\n message: promptText\n }\n};"
},
"id": "loker-prompt",
"name": "Loker Prompt",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
850,
350
]
},
{
"parameters": {
"functionCode": "// Owner Toggle - Hidden Feature\nconst promptText = `Anda akan TUTUP LAPAK.\\nMasukkan PIN Owner Anda (6 digit):`;\n\n// Check if message is a PIN (6 digits)\nconst message = $json.message || '';\nif (/^\\d{6}$/.test(message)) {\n return {\n json: {\n to: $json.from,\n action: 'verify_pin',\n pin: message\n }\n };\n}\n\nreturn {\n json: {\n to: $json.from,\n message: promptText,\n action: 'request_pin'\n }\n};"
},
"id": "toggle-handler",
"name": "Handle Toggle",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
850,
450
]
},
{
"parameters": {
"functionCode": "// Status Check Prompt\nconst promptText = `\ud83d\udcc4 CEK STATUS BERKAS\\n\\nSilakan ketik nomor HP yang terdaftar.\\nContoh: 081234567890\\n\\nKetik MENU untuk kembali.`;\n\nreturn {\n json: {\n to: $json.from,\n message: promptText\n }\n};"
},
"id": "status-prompt",
"name": "Status Prompt",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
850,
550
]
},
{
"parameters": {
"functionCode": "// Complaint Prompt\nconst promptText = `\ud83d\udcdd PENGADUAN RESMI\\n\\nSilakan tuliskan keluhan atau laporan Anda secara jelas.\\nContoh:\\n- Jalan rusak di Desa Sumberanyar\\n- Lampu jalan mati di Dusun Krajan\\n\\nSetelah dikirim, sistem akan meminta konfirmasi.`;\n\nreturn {\n json: {\n to: $json.from,\n message: promptText\n }\n};"
},
"id": "complaint-prompt",
"name": "Complaint Prompt",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
850,
650
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ { \"to\": $json.to, \"message\": $json.message } }}",
"options": {}
},
"id": "respond-webhook",
"name": "Respond to Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1050,
300
]
}
],
"connections": {
"WhatsApp Webhook": {
"main": [
[
{
"node": "Detect Intent",
"type": "main",
"index": 0
}
]
]
},
"Detect Intent": {
"main": [
[
{
"node": "Route by Intent",
"type": "main",
"index": 0
}
]
]
},
"Route by Intent": {
"main": [
[
{
"node": "Send Menu",
"type": "main",
"index": 0
}
],
[
{
"node": "UMKM & Jasa Prompt",
"type": "main",
"index": 0
}
],
[
{
"node": "Loker Prompt",
"type": "main",
"index": 0
}
],
[
{
"node": "Handle Toggle",
"type": "main",
"index": 0
}
],
[
{
"node": "Status Prompt",
"type": "main",
"index": 0
}
],
[
{
"node": "Complaint Prompt",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Send Menu": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"UMKM & Jasa Prompt": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Loker Prompt": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Handle Toggle": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Status Prompt": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Complaint Prompt": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"triggerCount": 0,
"updatedAt": "2026-02-15T00:00:00.000Z",
"versionId": "1"
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
whatsapp-router. Webhook trigger; 10 nodes.
Source: https://github.com/benchoaz/KecamatanSAE_final_version/blob/4b5ffebffbf40b8fd53ea57cd13f9523c085c953/n8n-workflows/whatsapp-router.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.
Slack lacks a native bulk delete feature. Users must delete messages manually, which is time-consuming and inefficient for large volumes.
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