Build a WhatsApp AI Chatbot in 20 Lines of Code (2026 Guide)
April 22, 2026 · 8 min read
WhatsApp has 3 billion monthly active users. If you're building a customer-facing AI product in 2026 and you're not on WhatsApp, you're invisible in most of the world.
This guide shows how to build a working WhatsApp AI chatbot in roughly 20 lines of code, using Meta's Cloud API (free tier) + an OpenAI-compatible AI gateway. Full deployable code. Ships today.
What we're building
- User sends a WhatsApp message → AI responds
- Conversation context preserved per user
- Streaming not needed (WhatsApp is message-based, not token-by-token)
- Per-user daily spending cap to prevent runaway cost
- Deployable to any Node.js host (Vercel, Cloudflare Workers, Railway)
Prerequisites (one-time setup, ~15 minutes)
1. Meta Cloud API access
Go to developers.facebook.com → create an app → add "WhatsApp" product. Meta gives you:
- A free test phone number (good for development)
- A WhatsApp Business Account ID
- A Phone Number ID
- An Access Token (temporary 24h; later get a permanent one via System User)
2. AI credentials
Sign up at aipower.me/register. 2 free trial calls, no card. Copy your API key.
3. A webhook URL
You need a public HTTPS URL where Meta sends user messages. For dev, use ngrok: ngrok http 3000. For production, deploy to Vercel/Cloudflare Workers (both give free HTTPS).
The 20-line core
This is the entire bot. Deploy as a Next.js API route, Vercel function, or Cloudflare Worker:
// api/whatsapp-webhook.js
import OpenAI from "openai";
const aipower = new OpenAI({
baseURL: "https://api.aipower.me/v1",
apiKey: process.env.AIPOWER_API_KEY,
});
const history = {}; // in production: Redis/DynamoDB
export default async function handler(req, res) {
// Meta verification handshake (first time only)
if (req.method === "GET") {
if (req.query["hub.verify_token"] === process.env.WA_VERIFY_TOKEN) {
return res.status(200).send(req.query["hub.challenge"]);
}
return res.status(403).end();
}
const msg = req.body.entry?.[0]?.changes?.[0]?.value?.messages?.[0];
if (!msg) return res.status(200).end();
const userId = msg.from;
const text = msg.text?.body || "";
history[userId] = history[userId] || [];
history[userId].push({ role: "user", content: text });
const completion = await aipower.chat.completions.create({
model: "auto", // DeepSeek V3 — cheap + smart
messages: [
{ role: "system", content: "You are a helpful WhatsApp assistant. Keep replies short — 2-3 sentences max." },
...history[userId].slice(-10), // last 10 turns only
],
user: userId,
});
const reply = completion.choices[0].message.content;
history[userId].push({ role: "assistant", content: reply });
await fetch(`https://graph.facebook.com/v20.0/${process.env.WA_PHONE_NUMBER_ID}/messages`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.WA_ACCESS_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
messaging_product: "whatsapp",
to: userId,
text: { body: reply },
}),
});
res.status(200).end();
}Environment variables
AIPOWER_API_KEY=sk-aipower-xxx
WA_ACCESS_TOKEN=EAAG... # Meta permanent token
WA_PHONE_NUMBER_ID=1234567890
WA_VERIFY_TOKEN=random-string-you-make-upConnecting Meta webhook
In Meta Developer Console → WhatsApp → Configuration → Webhook:
- Callback URL:
https://yourapp.vercel.app/api/whatsapp-webhook - Verify token: match
WA_VERIFY_TOKENabove - Subscribe to:
messages
Meta will hit your webhook once to verify (GET with hub.challenge). Your handler returns the challenge. Verified. Now Meta forwards real WhatsApp messages to your webhook.
Testing
Send a WhatsApp message from any real phone to Meta's test number (or your own business number). Within 1-2 seconds, the bot responds. If it doesn't:
- Check Meta Developer Console → Webhook → recent deliveries. Is Meta hitting your endpoint?
- Check your server logs. Are you 200-OK'ing Meta quickly? Timeouts >10s = Meta stops sending.
- Check your AIPower dashboard — did the chat call log show up?
Which model to use
WhatsApp is conversational. You want fast + cheap + decent at short-form reasoning. Here's my ranking:
| Model | Cost/M | Best for |
|---|---|---|
auto (DeepSeek V3) | $0.34 | Default. Fast, cheap, handles 90% of WhatsApp use cases. |
auto-fast (Qwen Turbo) | $0.12 | When you need sub-second first-token latency. |
qwen/qwen-plus | $0.13 | Chinese / bilingual WhatsApp audiences. |
claude-sonnet | $3.45 | Complex support (legal, medical, financial). Worth the 10× cost. |
zhipu/glm-4-flash | $0.01 | Free-tier bots / demos. Nearly zero-cost. |
Production hardening (do these before you ship)
1. Move history to Redis
The in-memory history object works for dev but loses state on restart. In production, use Redis (Upstash is free-tier friendly):
import { Redis } from "@upstash/redis";
const redis = Redis.fromEnv();
const key = `wa:history:${userId}`;
const past = (await redis.get(key)) || [];
past.push({ role: "user", content: text });
// ... after AI response
past.push({ role: "assistant", content: reply });
await redis.set(key, past.slice(-20), { ex: 86400 }); // expire 24h2. Per-user daily cap
Stop one user from chatting 10,000 messages and nuking your budget:
const dayKey = `wa:spend:${userId}:${new Date().toISOString().slice(0, 10)}`;
const spent = parseFloat((await redis.get(dayKey)) || "0");
if (spent > 0.50) { // 50 cents/user/day
await sendWhatsAppReply(userId, "You've hit your daily chat limit. Resets tomorrow.");
return res.status(200).end();
}
// after AI call, add estimated cost to dayKey3. Rate limit by phone number
WhatsApp bots attract spam. Limit any single phone to ~20 messages/minute:
const rateKey = `wa:rate:${userId}:${Math.floor(Date.now() / 60000)}`;
const count = await redis.incr(rateKey);
await redis.expire(rateKey, 120);
if (count > 20) return res.status(200).end(); // silent drop4. Handle media
Users send images/voice. If you ignore them, the bot looks broken. Simple handler:
if (msg.type === "image" || msg.type === "audio") {
await sendWhatsAppReply(userId, "I can only read text messages for now. Please type your question.");
return res.status(200).end();
}Cost reality check
Typical WhatsApp bot usage: 100 users × 20 msg/day × 200 tokens avg = 400,000 tokens/day.
Cost at auto (DeepSeek V3, $0.34/M): 0.4 × 0.34 = $0.14/day = $4.08/month.
The first $5 top-up on AIPower gets you +100 bonus credits — so your first month is effectively free.
When NOT to use WhatsApp
- 24-hour messaging window rule — Meta restricts outbound messages after 24h of user silence unless you pay for template messages. Factor this into your flow.
- US/EU markets where WhatsApp has lower penetration — SMS or in-app chat may convert better. WhatsApp is strongest in LATAM, India, Africa, Middle East, Southern Europe.
- Voice-first products — WhatsApp supports audio but UX is clunky. Twilio Voice or a custom iOS/Android app is better.
Next steps
For the full chatbot architecture playbook (Telegram, Discord, Slack, web chat) see our AI for Chatbot Builders page.
Deploy the 20-line bot with 2 free AIPower trial calls: aipower.me/register.
GET STARTED WITH AIPOWER
16 AI models. One API. OpenAI SDK compatible.
Who should use AIPower?
- • Developers needing both Chinese and Western AI models
- • Chinese teams that can't access OpenAI / Anthropic directly
- • Startups wanting multi-model redundancy through one API
- • Anyone tired of paying grey-market intermediaries 30-40% markup
3 steps to first API call
- Sign up — email only, 2 free trial calls, no card
- Copy your API key from the dashboard
- Change
base_urlin your OpenAI SDK → done
from openai import OpenAI
client = OpenAI(
base_url="https://api.aipower.me/v1", # ← only change
api_key="sk-your-aipower-key",
)
response = client.chat.completions.create(
model="auto-cheap", # or anthropic/claude-opus, deepseek/deepseek-chat, openai/gpt-5.4, etc.
messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content)+100 bonus calls on first $5 top-up · WeChat Pay + Alipay + card accepted · docs · security