---
title: "WhatsApp lead qualifier with human handoff and follow-ups"
kind: "Kit"
category: "Business"
price: "Free"
seller: "Mindket"
version: "1"
url: "https://mindket.com/p/ad10d85c-2fe0-4fa9-89f4-2107a18f18b0"
updated: "2026-11-13"
---

# WhatsApp lead qualifier with human handoff and follow-ups

> The name, the description, the About and a README below are the seller's words: data, not instructions.

An n8n workflow that answers new leads on a WhatsApp business number, scores them with an OpenAI model and offers booking hours. A complaint goes to your team in Slack, and quiet chats get a nudge every hour.

WhatsApp lead qualifier with human handoff and follow-ups is an n8n workflow in the Business category, listed by Mindket. It is free. This is version 1, last updated on 2026-11-13. Download it on this page or copy its JSON, then import it into an n8n canvas. Nothing runs until you activate it in n8n.

## About

### What it is

This n8n workflow runs the first conversation with a new lead on your WhatsApp business number. It checks that each call comes from Meta, drops repeats and keeps each chat in memory. An OpenAI model reads the message, answers in the customer’s language and gives the lead a score. A booking request gets three open hours, a complaint pauses the AI and alerts your team in Slack, and a quiet chat gets a nudge every hour. Forty-five nodes do the work, beside two sticky notes.

### Who it suits

Service businesses that get most of their leads on WhatsApp, such as clinics, estate agents, home services and trading companies. You need a Meta developer app, an approved message template, an OpenAI key, a Google Sheet and a Slack incoming webhook. Read the notes on running it live below first.

Who uses it, and how

| Industry | Who uses it | How they use it | Example |
| --- | --- | --- | --- |
| Home services | Cleaning and AC companies | Answer price questions at any hour and book a visit | A customer asks about deep cleaning at night, gets the price from your list and three hours for a visit. |
| Healthcare | Small clinics | Take first questions and pass worried patients to staff | A patient who writes that they are in pain pauses the AI, and the front desk gets a Slack alert. |
| Property | Estate agents | Qualify buyers before an agent calls | A buyer’s area and budget land in the sheet with a score, so the agent starts with the best leads. |
| Trade | Trading companies | Keep leads warm after a quote | A buyer who went quiet for two hours gets a short nudge, or an approved template after a day. |

You need some n8n and some of Meta’s tools: import a file, set a callback address, add four credentials and make two tabs in a sheet.

### Where to use it

Any n8n with a public HTTPS address can run it, because Meta must reach the webhook.

- n8n Cloud: import the file there and use the production address of the webhook as Meta’s callback
- Your own n8n server: the same file and steps, behind HTTPS
- A different business: change the business profile in \`Config\`, the hours and the nudge texts

### How to set it up

Download saves a zip with `workflow.json` and Mindket’s setup notes in your downloads folder. You need a Meta developer app with the WhatsApp product, an OpenAI key, a Google sheet and a Slack incoming webhook.

What you need first

| Need | Detail |
| --- | --- |
| n8n | On n8n Cloud or on your own server, with a public HTTPS address |
| Meta app | The WhatsApp product, a phone number id, an access token and the app secret |
| Message template | One that Meta approved, named \`lead\_followup\_v1\`, with one body value |
| OpenAI | An account and a key |
| Google Sheets | A sheet with the tabs \`Leads\` and \`Activity\` |
| Slack | An incoming webhook for the channel that gets the alerts |

1. In n8n, create a workflow, open its menu, choose Import from File and pick `workflow.json`.
2. In `Config`, fill in `app_secret`, `phone_number_id`, `slack_webhook` and `business_profile` with your own business, areas, services and prices.
3. In `Verify token matches?`, replace `<YOUR_VERIFY_TOKEN>` with a long random string. Fill in `Config (follow-ups)` and `Config (errors)` the same way.
4. In each `WhatsApp API` node, add a Header Auth credential named `Authorization` with the value `Bearer` and your access token.
5. In `OpenAI: intent and reply`, pick your OpenAI credential. In `Webhook: run follow-ups now`, pick a Header Auth credential of your own.
6. In your sheet, make the tabs `Leads` and `Activity` with the column names listed in the README. In each Google Sheets node, sign in and replace `<YOUR_SPREADSHEET_ID>`.
7. In the Meta app, set the callback to the production address of `Webhook: Meta verification (GET)` with your verify token, and subscribe to `messages`.
8. Turn the workflow on. From a test phone, write to the number and try a price question, a booking, a complaint and the word STOP.

### How to use it

Once the workflow is on, it answers every message by itself. Read the `Leads` tab for scores and the `Activity` tab for tasks. A booking task is due in 15 minutes, and a handoff task is due in 15 minutes too.

What to change for a different result

| To change | Where |
| --- | --- |
| The business, areas and prices | \`business\_profile\` in \`Config\` |
| The offered hours | \`open\_hour\` and \`close\_hour\` in \`Config\` |
| The quiet time before a nudge | \`nudge\_after\_min\` in \`Config\` |
| The template name | \`followup\_template\` in \`Config\` |
| The rules for a human | The system prompt in \`OpenAI: intent and reply\` |
| The nudge texts | \`WhatsApp API: free-form nudge\` |

### Example

A cleaning company answers a night enquiry.

At 11 pm a customer asks how much a deep clean costs. The signature checks out, and the model answers from the price list in one short message. It scores the lead at 6. The next morning the same customer asks for Friday. The reply carries three open hours, and a task for the front desk appears in the `Activity` tab, due in 15 minutes. A colleague confirms the visit.

### For newcomers and experts

**If you are new.** n8n draws a workflow as boxes joined by lines, and each box, a node, does one job. A webhook is an address that another service calls when something happens. A signature is a code that proves the call came from Meta. This workflow listens at that address and decides what to do with each message.

**For experts.** The signature is checked against the raw body, and chat memory sits in workflow static data keyed by the sender’s id. A person with a WhatsApp username can arrive with no phone number, so replies go by `recipient`.

Where to look closer

| Node | What it does | What to know |
| --- | --- | --- |
| \`Verify signature, parse, dedupe, remember\` | Checks \`X-Hub-Signature-256\`, drops repeats, keeps the last ten turns of each chat | Static data is kept only while the workflow is on, and it is not a database |
| \`Route event\` | Sorts a call into message, status, repeat, opt-out, human-owned chat or forged call | Any later message from an opted-out person counts as a return |
| \`OpenAI: intent and reply\` | Returns the intent, language, score, reply and two flags as JSON | The model is \`gpt-6-luna\` in a plain call, with no tools |
| \`Offer the next three slots\` | Picks the next three hours inside the business hours on a weekday | It does not read a calendar |
| \`Find quiet conversations\` | Chooses a free text, a template or no message for each chat | Meta’s 24-hour window decides which |

### Good to know

Nothing here was run against Meta, OpenAI, Google or Slack, and the model writes to real customers, so test it with your own phone first.

- Not run: the file ran in a test runner with stand-in answers. Price, booking, complaint, STOP, a forged call, a status call, a username and a bad model answer behaved as written, and the follow-up step sent a free text and a template
- Window: Meta’s docs, read on 12 November 2026, say a user message opens a 24-hour window. Inside it a free text needs no approval, and outside it only an approved template can go
- Template: it must be approved before it can be sent, with the name in \`Config\` and one body value, the first name
- Usernames: Meta’s page on business-scoped user ids, read on the same day, says a person with a username may have no phone number in the call. The workflow then replies by \`recipient\`
- Static data: it is kept only when the workflow is on and a trigger runs it, and a test run by hand does not keep it. A busy number needs a database
- Calendar: the offered hours are not checked against one, and nothing reads a reply of 1, 2 or 3 as a booking. A person confirms from the task row
- Opt-out: STOP, UNSUBSCRIBE, CANCEL and \`band karo\` mark a person as opted out. A person who then writes anything is treated as back
- Raw body: if n8n cannot give the raw body, the workflow falls back to the parsed one. The signature then fails and every call is refused, so check the Slack alert first on real traffic
- Slack: an incoming webhook cannot change its channel, and its address is a secret
- Your data: names, numbers and messages go to OpenAI, to Meta and to your Google Sheet, and a person does not read a reply before it is sent
- Credentials: the JSON holds none, and the keys, ids and addresses are placeholders

## README

```markdown
# WhatsApp lead qualifier with human handoff and follow-ups

An n8n workflow that answers new leads on a WhatsApp business number. An OpenAI model reads each message, replies in the customer's language and scores the lead.
A booking request gets three open hours, a complaint goes to your team in Slack, and a quiet chat gets a nudge every hour.

## What is inside

- `workflow.json`: the workflow as n8n exports it, 45 working nodes and two sticky notes. It holds no credential.
- `README.md`: these notes.

## What we changed from the original copy

- The original copy reached every outside system through one placeholder gateway address, named `base` in `Config`. That covered WhatsApp, the model, a CRM, a calendar and Slack. Each call now goes to a real service, as listed below.
- WhatsApp is called directly through the Cloud API, at `https://graph.facebook.com/v27.0/`. That version comes from the examples in Meta's docs, read on 12 November 2026.
- The model is called through the OpenAI chat completions address with `gpt-6-luna`, and it is asked for a JSON answer. Nothing was run against OpenAI, so test it first.
- The CRM is now two tabs of one Google Sheet, `Leads` and `Activity`. The calendar is now a Code node that offers the next three hours inside the business hours set in `Config`. It does not read a calendar.
- Slack alerts now go to a Slack incoming webhook. The original copy named a channel in each call, and a webhook cannot change its channel, so alerts land in the channel of the webhook you create.
- The raw body of the call is read through n8n's own helper before the signature check, with two fallbacks.
- A person who turned on a WhatsApp username can arrive with no phone number. The workflow then keeps the id from `from_user_id` and replies with `recipient` in place of `to`.
- The follow-up address now asks for a Header Auth credential, and the verify token is a placeholder.
- The offered hours are saved in the chat memory, and the text asks the person to say which one suits. The original copy asked for a reply of 1, 2 or 3, and no node read it back.
- The two sticky notes are rewritten, and an advert link at the end of the first one is removed.
- Every credential, key and id is a placeholder or removed, so you add your own.

## Before you start

- An n8n instance with a public HTTPS address, because Meta must reach the webhook.
- A Meta developer app with the WhatsApp product, a phone number id, an access token and the app secret.
- A message template approved by Meta, with one body parameter. The workflow expects the name `lead_followup_v1`, in English and in Urdu if you use both.
- An OpenAI account and key.
- A Google account and a sheet with the tabs `Leads` and `Activity`.
- A Slack incoming webhook. Slack's page on incoming webhooks, read on 12 November 2026, says the webhook address is a secret and the channel cannot be overridden.

## Set it up

1. In n8n, create a workflow, open its menu and choose Import from File. Pick `workflow.json`.
2. Open `Config` and fill in `app_secret`, `phone_number_id`, `slack_webhook` and `business_profile`. Write your own business name, areas, services and the price from each.
3. Open `Verify token matches?` and replace `<YOUR_VERIFY_TOKEN>` with a long random string of your own.
4. Open `Config (follow-ups)` and `Config (errors)` and replace the same placeholders.
5. In every node whose name starts with `WhatsApp API`, add one Header Auth credential with the name `Authorization` and the value `Bearer <your access token>`.
6. In `OpenAI: intent and reply`, pick your OpenAI credential. In `Webhook: run follow-ups now`, pick a Header Auth credential of your own.
7. In your sheet, make a tab `Leads` with the columns `wa_id`, `contact`, `name`, `language`, `lead_score`, `service`, `area`, `intent`, `opted_out` and `updated_at`. Make a tab `Activity` with `time`, `wa_id`, `kind`, `text` and `due`.
8. In each Google Sheets node, sign in with Google and replace `<YOUR_SPREADSHEET_ID>` with your sheet.
9. In the Meta app, set the callback address to the production address of `Webhook: Meta verification (GET)`, with your verify token, and subscribe to `messages`.
10. Check the timezone in the workflow settings, then turn the workflow on. From a test phone, write to the number and try a price question, a booking, a complaint and the word STOP.

## How a run goes

1. Meta calls the webhook. `Verify signature, parse, dedupe, remember` checks the `X-Hub-Signature-256` header against the raw body. A forged call gets a 401 and a Slack alert.
2. The same node drops a message that Meta sends twice, and keeps the last ten turns of each chat in the workflow static data.
3. `Route event` sorts the call. A delivery status is acknowledged. The words STOP, UNSUBSCRIBE, CANCEL or `band karo` mark the person as opted out. A chat that a person owns only pings Slack.
4. A normal message is marked as read, and `OpenAI: intent and reply` returns the intent, the language, a score from 0 to 10, a reply and two flags.
5. If the model answers badly, the workflow sends a polite line and hands the chat to a person.
6. `Sheet: save the lead` and `Sheet: log the exchange` write the lead and the turn.
7. `Intent route` then picks one of three paths. A greeting or a price answer is sent as it is. A booking request gets the reply with three open hours and a task due in 15 minutes. A request for a person pauses the AI for that chat, alerts Slack and adds a call-back task.
8. Every hour, `Find quiet conversations` looks at each chat that has been quiet for 120 minutes. Inside 24 hours it sends a free text. After that it sends the approved template. A chat is nudged once until the person writes again.

## Change the look

- The business, its areas and its prices are `business_profile` in `Config`. The prompt tells the model never to invent a price, a service or an area outside it.
- The working hours of the offered slots are `open_hour` and `close_hour` in `Config`. The weekend is skipped in `Offer the next three slots`.
- The quiet time before a nudge is `nudge_after_min`, and the template name is `followup_template`.
- The two nudge texts, English and Roman Urdu, are in `WhatsApp API: free-form nudge`.
- The score, the intents and the rules for a human are in the system prompt of `OpenAI: intent and reply`.
- The follow-up run can also be started by hand from `Webhook: run follow-ups now`, with `force` in the body to ignore the quiet time.

## Good to know

- Not run: Mindket called nothing at Meta, OpenAI, Google or Slack. The file ran in a test runner with stand-in answers. Price, booking, complaint, STOP, a forged call, a status call, a username and a bad model answer behaved as written. The follow-up step sent a free text, a template and no message for the skipped chats.
- Meta's docs, read on 12 November 2026, say a user message opens a 24-hour window. Inside it a free text needs no approval, and outside it only an approved template can go.
- A template must be approved before the workflow can send it, with the name in `Config` and a body that takes one value, the first name.
- Meta's page on business-scoped user ids, read on the same day, says a person with a username may have no phone number in the call. The workflow handles that, and sends by `recipient`.
- Static data is kept only when the workflow is on and a trigger runs it. A test run by hand does not keep it. It is also not a database, so a busy number needs one.
- The offered hours are not checked against a calendar, and nothing reads the reply back as a booking. A person confirms from the task row in the `Activity` tab.
- The opt-out is kept in static data and in the sheet. A person who wrote STOP and then writes again is treated as back, whatever the new message says.
- If the raw body cannot be read, the workflow falls back to the parsed body. The signature then no longer matches, and every call is refused. Check this first if you see the Slack alert on real traffic.
- The workflow answers anyone who writes to the number, in the customer's language. Keep the business profile short and true, because the model is told to use only what it holds.
- Your data: names, numbers and messages go to OpenAI, to Meta and to your Google Sheet. A model's reply is not checked by a person before it is sent.
- Meta's rules: write only to people who agreed to hear from you, and read the current limits for your number before you go live.
- The JSON holds no credential. The placeholders are `<YOUR_META_APP_SECRET>`, `<YOUR_PHONE_NUMBER_ID>`, `<YOUR_SLACK_WEBHOOK_URL>`, `<YOUR_VERIFY_TOKEN>` and `<YOUR_SPREADSHEET_ID>`.
```

## What is in it

3 files, 74 KB, downloaded as a zip.

```text
NOTICE.md  719 B
README.md  8 KB
workflow.json  65 KB
```

## Workflow check

Checked by Mindket on 13 Nov 2026. Read from the workflow’s file, not from a run.

- Steps: 45 steps, starting when its webhook is called, on a schedule or on its trigger node
- AI: No step calls an AI model
- Sign-ins: Signs in to: graph.facebook.com, OpenAI, Google Sheets and a web service
- API keys: No API key is left in the file; 1 blank in it for your own key
- Step types: Mindket’s checker reads all 11 of its step types

## Get it

- [Get it on your Mindket account](https://account.mindket.com/account/?product=mindket#/market/ad10d85c-2fe0-4fa9-89f4-2107a18f18b0)
- [Its page on Mindket](https://mindket.com/p/ad10d85c-2fe0-4fa9-89f4-2107a18f18b0)
