Most WhatsApp bot tutorials are outdated or use unofficial APIs that get your number banned. Here's how to build a production-ready AI WhatsApp bot using the official Cloud API and n8n — the same architecture I use for all my client deployments.
Why This Stack?
| Component | What | Cost |
|---|---|---|
| WhatsApp Cloud API | Official Meta API for sending/receiving messages | Free tier available (check Meta for current pricing) |
| n8n | Open-source workflow automation (self-hosted) | Free |
| AI Model (GPT/Claude) | Natural language understanding + response generation | ~$5-20/month |
| VPS Server | Runs n8n + webhook endpoint | $5-10/month |
Total cost: ~$10-30/month for a bot that handles thousands of conversations. Compare that to SaaS platforms charging $50-500/month.
Architecture Overview
Customer sends WhatsApp message
↓
Meta Cloud API receives it
↓
Webhook sends to your n8n instance
↓
n8n workflow processes the message:
→ Checks message type (text/image/location)
→ Loads conversation history
→ Sends to AI model with system prompt
→ AI generates contextual response
↓
n8n sends response back via WhatsApp API
↓
Customer receives reply instantly
Step 1: Set Up WhatsApp Cloud API
- Go to Meta for Developers and create an app
- Add the "WhatsApp" product to your app
- Get your Phone Number ID and Access Token from the WhatsApp dashboard
- You get a test phone number immediately — no need to wait for approval
Important: Generate a permanent access token (System User token), not the temporary one that expires in 24 hours.
Step 2: Set Up n8n
If you don't have n8n running yet, the fastest way:
# Docker one-liner
docker run -d --name n8n \
-p 5678:5678 \
-v n8n_data:/home/node/.n8n \
n8nio/n8n
For production, I recommend Docker Compose with PostgreSQL (not SQLite) and Queue Mode for reliability. But for getting started, the above works fine.
Step 3: Create the Webhook
In n8n, create a new workflow:
- Add a Webhook node — Method: POST, Path:
/whatsapp-webhook - Copy the webhook URL (you'll need it for Meta)
- Add a Respond to Webhook node after your processing logic — Response Code: 200. This is critical — Meta requires a 200 response within 5 seconds or it retries.
Register the webhook with Meta:
- Go to your app's WhatsApp Configuration
- Add the callback URL:
https://your-server.com/webhook/whatsapp-webhook - Subscribe to:
messages
Step 4: Parse Incoming Messages
The webhook payload from Meta looks like this:
{
"entry": [{
"changes": [{
"value": {
"messages": [{
"from": "972501234567",
"type": "text",
"text": { "body": "How much does shipping cost to Tel Aviv?" }
}]
}
}]
}]
}
In n8n, use a Code node to extract:
const message = $input.first().json;
const entry = message.entry?.[0];
const change = entry?.changes?.[0];
const value = change?.value;
const msg = value?.messages?.[0];
const from = msg?.from;
const type = msg?.type;
const body = type === 'text' ? msg?.text?.body : '';
const name = value?.contacts?.[0]?.profile?.name || 'Unknown';
return { from, type, body, name };
Step 5: Add AI Processing
Add an HTTP Request node to call your AI model:
{
"model": "claude-sonnet-4-6",
"max_tokens": 500,
"system": "You are a helpful business assistant for [Your Company]. Be concise — WhatsApp messages should be short and clear.",
"messages": [
{ "role": "user", "content": "{{$json.body}}" }
]
}
Pro tip: Add conversation memory by storing previous messages in a Google Sheet or database, and including them in the messages array.
Step 6: Send the Response
Use another HTTP Request node to send the reply:
POST https://graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/messages
Authorization: Bearer {ACCESS_TOKEN}
{
"messaging_product": "whatsapp",
"to": "{{$json.from}}",
"type": "text",
"text": { "body": "{{$json.aiResponse}}" }
}
Making It Production-Ready
The basic flow above works, but here's what separates a demo from production:
Error Handling
If AI call fails → Send "Let me check on that, one moment..." → Queue for retry. If webhook times out → Return 200 immediately, process async.
Rate Limiting
WhatsApp has rate limits. Use n8n's built-in Wait node between messages if you're sending bulk notifications.
Media Handling
For voice messages: transcribe with Whisper. For images: describe with a vision model. Process the transcription with your AI.
Conversation Memory
Store conversations in PostgreSQL or Google Sheets. Key: phone number, Value: last N messages + timestamps. Clear after 24 hours of inactivity.
Human Handoff
When the AI can't handle a query: detect low-confidence responses, route to a human agent via Chatwoot or a simple notification.
Real-World Example
I built this exact architecture for a delivery company. The bot:
- Receives shipment details from customers via WhatsApp
- Calculates shipping prices based on distance (Google Maps API)
- Documents everything automatically in Google Sheets
- Sends status updates when deliveries are in progress
It runs 24/7 with high uptime. The company significantly reduced manual workload in customer service.
Common Mistakes to Avoid
Using unofficial APIs — Baileys, green-api, etc. will get your number banned. The official Cloud API has a free tier — check Meta's current pricing for details.
Not handling webhook verification — Meta sends a GET request to verify your webhook. Handle both GET (verification) and POST (messages).
Slow webhook responses — Meta retries if you don't respond with 200 within ~5 seconds. Process messages asynchronously.
No graceful degradation — When your AI provider has an outage, queue messages and retry.
Ignoring message types — Customers send images, voice notes, and locations. Handle them or acknowledge them.
Resources
- WhatsApp Cloud API Docs
- n8n Documentation
- Complete WhatsApp Bot Guide — comprehensive guide covering both DIY and hiring approaches
- Official vs Unofficial WhatsApp APIs — why the official API is always the right choice
- n8n WhatsApp Starter Template — ready-to-use n8n workflow
I'm Achiya, a WhatsApp automation specialist based in Israel. I've built 50+ WhatsApp bots for businesses using this exact stack. Questions? Drop them in the comments.
Top comments (0)