Tutorial

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-up

Connecting Meta webhook

In Meta Developer Console → WhatsApp → Configuration → Webhook:

  • Callback URL: https://yourapp.vercel.app/api/whatsapp-webhook
  • Verify token: match WA_VERIFY_TOKEN above
  • 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:

ModelCost/MBest for
auto (DeepSeek V3)$0.34Default. Fast, cheap, handles 90% of WhatsApp use cases.
auto-fast (Qwen Turbo)$0.12When you need sub-second first-token latency.
qwen/qwen-plus$0.13Chinese / bilingual WhatsApp audiences.
claude-sonnet$3.45Complex support (legal, medical, financial). Worth the 10× cost.
zhipu/glm-4-flash$0.01Free-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 24h

2. 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 dayKey

3. 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 drop

4. 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

  1. Sign up — email only, 2 free trial calls, no card
  2. Copy your API key from the dashboard
  3. Change base_url in 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