AutomationFlowsData & Sheets › Route Whatsapp Home-service Requests by Urgency with Groq, Supabase, and Sheets

Route Whatsapp Home-service Requests by Urgency with Groq, Supabase, and Sheets

ByKanishka Shrivastava @kanishka-shrivastava on n8n.io

This workflow routes incoming WhatsApp home-service requests by using Groq to classify urgency and extract key details, logs every request to Supabase, and either alerts an on-call technician for emergencies or appends routine jobs to a Google Sheets queue while confirming the…

Event trigger★★★★☆ complexityAI-powered17 nodesChain LlmGroq ChatOutput Parser StructuredSupabaseWhatsAppGoogle SheetsWhatsApp Trigger
Data & Sheets Trigger: Event Nodes: 17 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #17322 — we link there as the canonical source.

This workflow follows the Chainllm → Google Sheets 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 →

Download .json
{
  "id": "FtpbRCegncW8eK59",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Route home-service requests by urgency over WhatsApp",
  "tags": [],
  "nodes": [
    {
      "id": "bb22ec94-1cdf-4e90-a6c2-2f2c80e118f2",
      "name": "Template Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -144,
        0
      ],
      "parameters": {
        "color": 4,
        "width": 680,
        "height": 1072,
        "content": "## \ud83d\udd27 Route Home-Service Requests by Urgency\n\n## Who's it for\nElectricians, plumbers, AC repair technicians, and similar home-service businesses that take requests over WhatsApp and want emergencies handled immediately while routine requests get queued up properly instead of mixed in with everything else.\n\n## How it works\nWhen a customer messages in, AI extracts the issue type, urgency, and location from their message. Every request is logged regardless of urgency. Emergency requests immediately ping your on-call technician with the details and send the customer a confirmation that help is on the way. Routine requests are added to a service queue sheet instead, and the customer gets a message letting them know when to expect a callback, so nothing urgent gets buried in a backlog and nothing routine gets treated like a fire drill.\n\n## How to set up\n1. Connect your WhatsApp Business Cloud credentials to the trigger and both send nodes.\n2. Connect your Groq or Gemini API credentials to the Chat Model node.\n3. Connect your Supabase credentials and create the table described in the sticky note near the Log Request node.\n4. Connect your Google Sheets credentials and create a queue sheet with the columns listed near the Add to Queue node.\n5. Open the Set Configuration node and fill in your WhatsApp phone number ID, on-call technician's number, Sheet ID, and response window.\n6. Activate the workflow.\n\n## Requirements\n- WhatsApp Business Cloud API access\n- Groq or Gemini API key\n- Supabase project\n- Google Sheets account\n\n## How to customize\nEdit the classification prompt to change what counts as an emergency for your trade (e.g. \"no hot water\" might be routine for a plumber but urgent in winter). Update the on-call technician's number as your rotation changes."
      },
      "typeVersion": 1
    },
    {
      "id": "69c115c7-fa19-4490-a311-5776f3292b89",
      "name": "Section - Trigger and Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        384
      ],
      "parameters": {
        "color": 7,
        "width": 508,
        "height": 316,
        "content": "## 1\ufe0f\u20e3 2\ufe0f\u20e3 Trigger + Configuration\nFires on every incoming WhatsApp message."
      },
      "typeVersion": 1
    },
    {
      "id": "350c8d1b-127c-4ad9-b12c-b44b8c40531f",
      "name": "Section - AI Extraction",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1088,
        336
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 572,
        "content": "## 3\ufe0f\u20e3 AI Extraction\nDecides issue type, urgency, and location from the customer's message. Edit the prompt to match what counts as an emergency for your trade."
      },
      "typeVersion": 1
    },
    {
      "id": "ca6c33fc-15b5-4170-869b-cc5ae8972e0a",
      "name": "Supabase Schema Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1552,
        336
      ],
      "parameters": {
        "color": 3,
        "width": 300,
        "content": "\u26a0\ufe0f Table schema\nservice_requests: customer_name, customer_number, issue_type, location, description, urgency, created_at (timestamptz, default now())."
      },
      "typeVersion": 1
    },
    {
      "id": "2db54ccc-df90-43fe-8d40-1d9a8a0bba0c",
      "name": "Section - Emergency Branch",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2112,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 516,
        "content": "## 4\ufe0f\u20e3 If Emergency\nThe on-call technician gets pinged immediately with the details, and the customer gets confirmation that help is coming, both happen in parallel, not one waiting on the other."
      },
      "typeVersion": 1
    },
    {
      "id": "d1c8fce5-02af-45ab-8b11-895510a33459",
      "name": "Extract Request Details",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1216,
        528
      ],
      "parameters": {
        "text": "=Read this home-service request and extract the details.\n\nMessage: {{ $('Set Configuration').item.json.customer_message }}\n\nExtract: issue_type (a short label like \"electrical outage\", \"water leak\", \"AC not cooling\"), location (if mentioned, otherwise \"not specified\"), and a one-sentence description. Also decide urgency: \"emergency\" if this needs attention within hours (safety risk, total outage, active flooding/leak), or \"routine\" if it can reasonably wait a day or two.",
        "batching": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.8
    },
    {
      "id": "848ed36e-4d8f-46d0-9b1d-1b52fcffe530",
      "name": "Extraction Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "position": [
        1184,
        736
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "771d07e5-b30a-4ce3-a8b4-b119a58c32d0",
      "name": "Extraction Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1392,
        752
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"issue_type\": {\n      \"type\": \"string\"\n    },\n    \"location\": {\n      \"type\": \"string\"\n    },\n    \"description\": {\n      \"type\": \"string\"\n    },\n    \"urgency\": {\n      \"type\": \"string\",\n      \"enum\": [\n        \"emergency\",\n        \"routine\"\n      ]\n    }\n  },\n  \"required\": [\n    \"issue_type\",\n    \"location\",\n    \"description\",\n    \"urgency\"\n  ]\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "f87a7e94-fc36-4ea1-81b6-a8657174567f",
      "name": "Log Request",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1680,
        528
      ],
      "parameters": {
        "operation": "insert"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6a37968f-3d12-4c99-bf83-f4e90ddc74d3",
      "name": "Is Emergency?",
      "type": "n8n-nodes-base.if",
      "position": [
        1904,
        528
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Extract Request Details').item.json.output.urgency }}",
              "rightValue": "emergency"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "fb7baa31-d484-4b29-98a5-d162a296d56b",
      "name": "Notify On-Call Technician",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        2288,
        240
      ],
      "parameters": {
        "textBody": "=EMERGENCY: {{ $('Extract Request Details').item.json.output.issue_type }} at {{ $('Extract Request Details').item.json.output.location }}. {{ $('Extract Request Details').item.json.output.description }} Customer: {{ $('Set Configuration').item.json.customer_name }}, {{ $('Set Configuration').item.json.customer_number }}",
        "operation": "send",
        "phoneNumberId": "={{ $('Set Configuration').item.json.whatsapp_phone_number_id }}",
        "additionalFields": {},
        "recipientPhoneNumber": "={{ $('Set Configuration').item.json.oncall_technician_number }}"
      },
      "credentials": {
        "whatsAppApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7c9ab878-059b-4783-9c1a-8c7ccba01925",
      "name": "Confirm Emergency to Customer",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        2288,
        416
      ],
      "parameters": {
        "textBody": "=Got it, this sounds urgent. Our technician has been notified and will call you shortly to confirm arrival time.",
        "operation": "send",
        "phoneNumberId": "={{ $('Set Configuration').item.json.whatsapp_phone_number_id }}",
        "additionalFields": {},
        "recipientPhoneNumber": "={{ $('Set Configuration').item.json.customer_number }}"
      },
      "credentials": {
        "whatsAppApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3b1319a0-391b-44bd-b971-79cf457c2341",
      "name": "Add to Service Queue",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2384,
        864
      ],
      "parameters": {
        "columns": {
          "value": {
            "status": "queued",
            "location": "={{ $('Extract Request Details').item.json.output.location }}",
            "issue_type": "={{ $('Extract Request Details').item.json.output.issue_type }}",
            "description": "={{ $('Extract Request Details').item.json.output.description }}",
            "customer_name": "={{ $('Set Configuration').item.json.customer_name }}",
            "customer_number": "={{ $('Set Configuration').item.json.customer_number }}"
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Set Configuration').item.json.queue_sheet_name }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Set Configuration').item.json.sheet_id }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "1ab29097-74d0-4e4e-842e-7e918384c13f",
      "name": "Confirm Queued to Customer",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        2400,
        1024
      ],
      "parameters": {
        "textBody": "=Thanks for reaching out! We've added your request ({{ $('Extract Request Details').item.json.output.issue_type }}) to our queue and will contact you within {{ $('Set Configuration').item.json.routine_response_days }} days to schedule a visit.",
        "operation": "send",
        "phoneNumberId": "={{ $('Set Configuration').item.json.whatsapp_phone_number_id }}",
        "additionalFields": {},
        "recipientPhoneNumber": "={{ $('Set Configuration').item.json.customer_number }}"
      },
      "credentials": {
        "whatsAppApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f77eedab-fd72-4b9a-8c61-2c2b12baded6",
      "name": "New Service Request",
      "type": "n8n-nodes-base.whatsAppTrigger",
      "position": [
        656,
        528
      ],
      "parameters": {
        "options": {},
        "updates": [
          "messages"
        ]
      },
      "credentials": {
        "whatsAppTriggerApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5e7994d3-aba2-478b-a1cf-d226cfa01fc9",
      "name": "Set Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        880,
        528
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "1bfb8edb-7ece-43ef-bdbe-d8fbc1eaec80",
              "name": "business_name",
              "type": "string",
              "value": "REPLACE_WITH_BUSINESS_NAME"
            },
            {
              "id": "8024c167-c84e-469a-99f1-60c90b83a554",
              "name": "whatsapp_phone_number_id",
              "type": "string",
              "value": "REPLACE_WITH_WHATSAPP_PHONE_NUMBER_ID"
            },
            {
              "id": "f39a7248-b2a0-4927-b0dd-50923627b1b0",
              "name": "oncall_technician_number",
              "type": "string",
              "value": "REPLACE_WITH_TECHNICIAN_WHATSAPP_NUMBER"
            },
            {
              "id": "d8e6bae5-7c08-47aa-8860-c7d087935efe",
              "name": "supabase_table_requests",
              "type": "string",
              "value": "service_requests"
            },
            {
              "id": "59f47b46-97b1-45e2-8e29-2bf22b281efc",
              "name": "sheet_id",
              "type": "string",
              "value": "REPLACE_WITH_GOOGLE_SHEET_ID"
            },
            {
              "id": "302e7185-9e12-4897-b80a-d811f6991d53",
              "name": "queue_sheet_name",
              "type": "string",
              "value": "Queue"
            },
            {
              "id": "5d8332fc-8a19-41c6-8b60-5eb6feaa8290",
              "name": "routine_response_days",
              "type": "number",
              "value": 2
            },
            {
              "id": "d50ce126-7ade-4a47-8268-5ebb47f82af4",
              "name": "customer_message",
              "type": "string",
              "value": "={{ $json.messages[0].text.body }}"
            },
            {
              "id": "ba5ce2d1-9bc7-45cf-ba04-68044ceaa82c",
              "name": "customer_number",
              "type": "string",
              "value": "={{ $json.messages[0].from }}"
            },
            {
              "id": "49232585-66ea-4182-a068-331f109fb4f1",
              "name": "customer_name",
              "type": "string",
              "value": "={{ $json.contacts[0].profile.name }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c0116245-5ddd-43c7-bede-5d9a0e43685b",
      "name": "Section - Emergency Branch1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2208,
        640
      ],
      "parameters": {
        "color": 7,
        "width": 672,
        "height": 564,
        "content": "## 5\ufe0f\u20e3 If Routine\nAdded to the service queue sheet instead of triggering an immediate response, then the customer gets a realistic timeframe rather than being left wondering."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "bab98f81-3d6f-4a57-971f-0cefd7e54411",
  "nodeGroups": [],
  "connections": {
    "Log Request": {
      "main": [
        [
          {
            "node": "Is Emergency?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Emergency?": {
      "main": [
        [
          {
            "node": "Notify On-Call Technician",
            "type": "main",
            "index": 0
          },
          {
            "node": "Confirm Emergency to Customer",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Add to Service Queue",
            "type": "main",
            "index": 0
          },
          {
            "node": "Confirm Queued to Customer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extraction Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Extract Request Details",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Set Configuration": {
      "main": [
        [
          {
            "node": "Extract Request Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Service Request": {
      "main": [
        [
          {
            "node": "Set Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extraction Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Extract Request Details",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Extract Request Details": {
      "main": [
        [
          {
            "node": "Log Request",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow routes incoming WhatsApp home-service requests by using Groq to classify urgency and extract key details, logs every request to Supabase, and either alerts an on-call technician for emergencies or appends routine jobs to a Google Sheets queue while confirming the…

Source: https://n8n.io/workflows/17322/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

• Multi-Layer Message Analysis - Every customer interaction passes through three specialized AI classifiers: privacy detection (identifies sensitive data and security requirements), intent recognition

OpenAI, OpenAI Chat, Tool Think +13
Data & Sheets

This workflow responds to incoming WhatsApp inquiries by extracting event details with Groq, checking availability in Google Calendar, looking up rates in Google Sheets, and then sending either a quot

WhatsApp Trigger, Chain Llm, Groq Chat +5
Data & Sheets

This n8n workflow automates the transformation of spreadsheet data into professional charts and graphs using AI-driven analysis. Triggered via Slack, it processes uploaded files (Excel, CSV, Google Sh

Agent, Postgres, HTTP Request +8
Data & Sheets

Handles GDPR Article 15 (access) and Article 17 (erasure) requests end-to-end — from inbound email to legally-compliant response — with zero manual intervention and a full audit trail. 📬 Monitors Gmai

Gmail Trigger, Agent, OpenAI Chat +5
Data & Sheets

This workflow automatically detects completed orders in PostgreSQL and prepares them for AI-based post-purchase communication. It enriches each order with customer, product, and payment data, then gen

Postgres Trigger, Postgres, Agent +4