---
title: "Build a WhatsApp Order Bot with n8n Webhooks and AI"
description: "Step-by-step: receive WhatsApp orders via n8n webhook, parse them with an AI node, and send a confirmation — always-on, public URL, AI credits included."
canonical: https://agentroost.app/en/blog/whatsapp-order-bot-n8n-webhooks-ai
date: 2026-06-11T12:00:00Z
---

[Canonical URL](https://agentroost.app/en/blog/whatsapp-order-bot-n8n-webhooks-ai)

A customer texts your WhatsApp number: *"Hi, I'd like 2 large pepperoni pizzas and a Diet Coke delivered to 14 Baker St at 7pm."* Thirty seconds later they get a confirmation with the order summarised and a reference number. No human touched it.

That's the workflow this guide builds. You'll use your own n8n instance, an AI/LLM node to pull structured data out of free-form text, a WhatsApp API webhook to receive the message, and a reply step to close the loop. The whole thing runs 24/7 with a public HTTPS URL — no server to babysit.

---

## What you need before you start

- A WhatsApp Business API account (Meta Cloud API or a provider like 360dialog / Vonage). Meta's Cloud API has a testing conversation allowance that's enough to validate the flow.
- Your own n8n instance. If you don't have one yet, skip to the [how to run this on AgentRoost](#how-to-run-this-on-agentroost) section first — it takes about two minutes and your public webhook URL is ready immediately.
- Basic familiarity with n8n's canvas (dragging nodes, filling fields). No coding required.

---

## The flow at a glance

```
[Webhook] → [Set: extract fields] → [AI/LLM Node: parse order]
         → [IF: valid order?] → [WhatsApp: send confirmation]
                              → [WhatsApp: ask to clarify]
```

Five nodes. Let's build each one.

---

## Step 1 — Webhook node: receive the WhatsApp message

Add a **Webhook** node and set:

- **HTTP Method**: `POST`
- **Path**: `order-intake` (becomes `https://<your-id>.agentroost.app/webhook/order-intake`)
- **Authentication**: None for now (you'll add HMAC verification once it's working — Meta sends an `X-Hub-Signature-256` header you can validate in a later iteration)
- **Response Mode**: `Last Node` — so the response comes from your confirmation step, not immediately

Copy the production URL from the node header. You'll paste this into your Meta webhook configuration as the callback URL.

> **Test mode tip**: Switch the node to "Test" first and use the "Listen for test event" button. Then send a sample POST with a tool like curl or Postman before wiring up Meta.

Sample payload Meta sends (trimmed):

```json
{
  "entry": [{
    "changes": [{
      "value": {
        "messages": [{
          "from": "447700900123",
          "text": { "body": "2 large pepperoni + Diet Coke to 14 Baker St at 7pm" },
          "id": "wamid.abc123"
        }]
      }
    }]
  }]
}
```

---

## Step 2 — Set node: pull out the raw text

Add a **Set** node after the Webhook. You want to surface two fields cleanly for the next step:

| Field name | Expression |
|---|---|
| `customerPhone` | `{{ $json.entry[0].changes[0].value.messages[0].from }}` |
| `rawMessage` | `{{ $json.entry[0].changes[0].value.messages[0].text.body }}` |
| `messageId` | `{{ $json.entry[0].changes[0].value.messages[0].id }}` |

Set **Keep Only Set** to `true`. This trims the payload so the AI node receives a lean object instead of Meta's full envelope — smaller context, cheaper token use, cleaner output.

---

## Step 3 — AI/LLM node: parse the order into structured data

This is the core step. Add an **AI/LLM** node (n8n calls it **Basic LLM Chain** or **AI Agent** depending on your version; use **Basic LLM Chain** here since you want a one-shot extraction, not tool use).

**System prompt:**

```
You are an order intake parser for a food delivery business.
Extract the order from the customer's message and return ONLY valid JSON with this shape:
{
  "items": [{ "name": "string", "qty": number }],
  "deliveryAddress": "string or null",
  "deliveryTime": "string or null",
  "isComplete": true | false
}
Set isComplete to false if the address OR the items are missing or unclear.
Do not add any explanation outside the JSON.
```

**User message (expression):**

```
{{ $json.rawMessage }}
```

**Model**: Any chat model works. On AgentRoost, AI credits are already loaded — you don't need to paste an OpenAI key or pick a billing tier. Choose a fast, cost-efficient model (e.g. `gpt-4o-mini` or a comparable open-weights model) in the model dropdown. No extra configuration.

**Output**: The node returns the AI's text response. Add a **Code** node or use n8n's built-in `JSON.parse()` expression to convert it to an object:

```javascript
// In a Code node (JavaScript mode)
const raw = $input.item.json.text; // the LLM's output string
return [{ json: JSON.parse(raw) }];
```

---

## Step 4 — IF node: route on completeness

Add an **IF** node:

- **Condition**: `{{ $json.isComplete }}` equals `true`
- True branch → confirmation message
- False branch → clarification request

This prevents sending a garbled confirmation when the customer forgets their address.

---

## Step 5 — WhatsApp node: send confirmation (or ask again)

n8n's **HTTP Request** node handles the Meta Cloud API reply since there is no built-in WhatsApp node in community editions.

**Confirmation branch** — POST to `https://graph.facebook.com/v19.0/<PHONE_NUMBER_ID>/messages`:

```json
{
  "messaging_product": "whatsapp",
  "to": "{{ $('Set').item.json.customerPhone }}",
  "type": "text",
  "text": {
    "body": "Got it! Order confirmed:\n{{ $json.items.map(i => i.qty + 'x ' + i.name).join(', ') }}\nDelivery: {{ $json.deliveryAddress }} at {{ $json.deliveryTime }}\nRef: {{ $('Webhook').item.json.entry[0].changes[0].value.messages[0].id.slice(-6).toUpperCase() }}"
  }
}
```

Add an `Authorization: Bearer <your_token>` header and `Content-Type: application/json`.

**Clarification branch** — same endpoint, different body:

```json
{
  "text": {
    "body": "Thanks! Just to confirm — could you send us your delivery address and preferred time? We have your items noted."
  }
}
```

---

## Tips and common pitfalls

**Webhook verification (GET request)**: Meta sends a `hub.challenge` GET to your URL when you first register it. Add a second **Webhook** node listening on the same path for `GET` and respond with `{{ $json.query['hub.challenge'] }}`. Without this, Meta rejects your callback URL.

**Duplicate message delivery**: Meta retries webhooks if your endpoint doesn't return `200` within 20 seconds. With `Response Mode: Last Node`, make sure none of your nodes time out. If the AI call is slow, switch to `Response Mode: Immediately` and send the WhatsApp reply asynchronously.

**JSON parse failures**: The LLM occasionally wraps its output in markdown fences. Add a sanitise step before `JSON.parse()`:

```javascript
const clean = raw.replace(/^```json\s*/,'').replace(/```$/,'').trim();
return [{ json: JSON.parse(clean) }];
```

**Testing without a real WhatsApp number**: Use Meta's test number in the developer console. You can send messages to it from your own WhatsApp, and it will POST to your webhook exactly as production would.

---

## How to run this on AgentRoost

You need your n8n editor open with a public webhook URL before you can register anything with Meta. Here's the two-minute path:

1. Go to [agentroost.app](https://agentroost.app) and sign up — email/password, Google, Microsoft, or Discord.
2. Choose the **n8n** framework, give your instance a name.
3. Your private n8n editor opens at `https://<your-id>.agentroost.app`. That subdomain is your public webhook base URL — paste it into Meta's callback field as-is.
4. Import the workflow above (or build it node by node). The AI/LLM node connects to included credits automatically. No OpenAI key, no Anthropic key, no credit card on another service.

Everything runs 24/7 on dedicated hardware. You own your instance, your workflows, and your data — this is your n8n, you just skipped the Docker, SSL, and server bill.

Plans start at **$19.99/mo all-in** — roughly the cost of a small VPS plus a modest LLM credit balance, bundled. 14-day money-back guarantee, cancel anytime.

[Compare plans](/en/pricing) or [see the n8n framework details](/en/agents/n8n).

---

## What to build next

Once the basic order intake works:

- **Google Sheets node** — append each parsed order to a sheet for your kitchen or fulfilment team.
- **Schedule Trigger** — send a daily summary to your ops WhatsApp group at 6pm.
- **Twilio / SMS fallback** — if the WhatsApp send fails, retry via SMS using an HTTP Request node to the Twilio API.
- **Webhook HMAC validation** — verify `X-Hub-Signature-256` in a Code node at the top of the flow before processing anything.

The same pattern — webhook in, AI parses, action goes out — applies to support ticket triage, lead qualification forms, and invoice extraction. Once you have your n8n instance running, the canvas is open.
