DEV Community

Priyansh Kansara
Priyansh Kansara

Posted on

How to Build a WhatsApp Chatbot for Your Business in 30 Minutes

How to Build a WhatsApp Chatbot for Your Business in 30 Minutes

Reading time: 8 minutes
Target audience: Indian SMB owners, developers, and non-technical founders who want a working WhatsApp chatbot fast


Introduction

WhatsApp has 500 million+ users in India. Your customers are already on it — the question is whether you're talking to them or your competitor is.

In this tutorial, you'll build a working WhatsApp chatbot from scratch using Meta's Cloud API, Python (Flask), and a simple rule-based reply engine. No paid tools. No third-party platforms. Just code.

By the end, you'll have a bot that:

  • Replies to customer messages automatically
  • Handles FAQs (pricing, hours, location)
  • Escalates to a human agent when stuck
  • Runs on your own server

Time required: 30 minutes (if you have a Meta Developer account ready)
Cost: ₹0 for development (Meta gives 1,000 free service conversations/month)


Prerequisites

Before starting, make sure you have:

  1. A Meta Developer account — sign up at developers.facebook.com
  2. A Facebook Business Manager account — create at business.facebook.com
  3. A phone number — dedicated to WhatsApp (not your personal number)
  4. Python 3.8+ installed
  5. A public HTTPS URL — we'll use ngrok for local development

Step 1: Create a Meta App and Get API Credentials (5 min)

  1. Go to developers.facebook.com → My Apps → Create App
  2. Select Business as the app type
  3. Add the WhatsApp product to your app
  4. You'll see a temporary access token and your Phone Number ID and WhatsApp Business Account ID

Save these three values — you'll need them:

PHONE_NUMBER_ID=your_phone_number_id
WHATSAPP_BUSINESS_ACCOUNT_ID=your_business_account_id
ACCESS_TOKEN=your_temporary_access_token
Enter fullscreen mode Exit fullscreen mode

Note: The temporary token expires in 24 hours. For production, generate a System User Token that never expires.


Step 2: Set Up Your Python Project (3 min)

Create a new project folder and install dependencies:

mkdir whatsapp-chatbot && cd whatsapp-chatbot
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
pip install flask requests python-dotenv
Enter fullscreen mode Exit fullscreen mode

Create a .env file:

PHONE_NUMBER_ID=your_phone_number_id
ACCESS_TOKEN=your_access_token
VERIFY_TOKEN=my_custom_verify_token_123
Enter fullscreen mode Exit fullscreen mode

Create app.py:

import os
import requests
from flask import Flask, request, jsonify
from dotenv import load_dotenv

load_dotenv()

app = Flask(__name__)

PHONE_NUMBER_ID = os.getenv("PHONE_NUMBER_ID")
ACCESS_TOKEN = os.getenv("ACCESS_TOKEN")
VERIFY_TOKEN = os.getenv("VERIFY_TOKEN")

GRAPH_API_URL = f"https://graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/messages"


def send_whatsapp_message(to, text):
    """Send a text message via WhatsApp Cloud API."""
    headers = {
        "Authorization": f"Bearer {ACCESS_TOKEN}",
        "Content-Type": "application/json",
    }
    payload = {
        "messaging_product": "whatsapp",
        "to": to,
        "type": "text",
        "text": {"body": text},
    }
    response = requests.post(GRAPH_API_URL, headers=headers, json=payload)
    return response.json()


def get_reply(message_text):
    """Simple rule-based reply engine."""
    text = message_text.lower().strip()

    # FAQ responses
    if any(word in text for word in ["price", "cost", "fee", "charge", "rate"]):
        return (
            "Our pricing:\n"
            "• Basic Plan: ₹5,000/month\n"
            "• Standard Plan: ₹8,000/month\n"
            "• Premium Plan: ₹12,000/month\n\n"
            "Want a custom quote? Share your requirements!"
        )

    if any(word in text for word in ["hour", "time", "open", "close", "timing"]):
        return "We're open Monday to Saturday, 9 AM to 7 PM IST."

    if any(word in text for word in ["location", "address", "where", "office"]):
        return "We're located in Ahmedabad, Gujarat. Here's the map: https://maps.google.com"

    if any(word in text for word in ["human", "agent", "person", "call", "talk"]):
        return "Connecting you to a human agent. Please hold for 2-3 minutes. You can also call us at +91-XXXX-XXXXXX."

    if any(word in text for word in ["hi", "hello", "hey", "namaste"]):
        return (
            "Hello! Welcome to Our Business. How can I help you today?\n\n"
            "Reply with:\n"
            "1️⃣ Pricing\n"
            "2️⃣ Timings\n"
            "3️⃣ Location\n"
            "4️⃣ Talk to human"
        )

    # Default fallback
    return (
        "I'm not sure I understand. Here's what I can help with:\n\n"
        "• Pricing\n"
        "• Business hours\n"
        "• Location\n"
        "• Talk to a human\n\n"
        "Or type your question and I'll do my best!"
    )


@app.route("/webhook", methods=["GET"])
def verify_webhook():
    """Verify webhook with Meta."""
    mode = request.args.get("hub.mode")
    token = request.args.get("hub.verify_token")
    challenge = request.args.get("hub.challenge")

    if mode == "subscribe" and token == VERIFY_TOKEN:
        print("Webhook verified!")
        return challenge, 200
    return "Forbidden", 403


@app.route("/webhook", methods=["POST"])
def handle_message():
    """Handle incoming WhatsApp messages."""
    data = request.get_json()

    try:
        entry = data["entry"][0]
        changes = entry["changes"][0]
        value = changes["value"]

        if "messages" in value:
            message = value["messages"][0]
            from_number = message["from"]
            message_type = message["type"]

            if message_type == "text":
                incoming_text = message["text"]["body"]
                print(f"Message from {from_number}: {incoming_text}")

                reply = get_reply(incoming_text)
                send_whatsapp_message(from_number, reply)
                print(f"Replied: {reply}")

    except (KeyError, IndexError) as e:
        print(f"Error processing message: {e}")

    return jsonify({"status": "ok"}), 200


@app.route("/")
def home():
    return "WhatsApp Chatbot is running!"


if __name__ == "__main__":
    app.run(port=5000, debug=True)
Enter fullscreen mode Exit fullscreen mode

Step 3: Expose Your Server with ngrok (2 min)

Meta needs a public HTTPS URL to send webhook events. For local development, use ngrok:

# Install ngrok from https://ngrok.com/download
ngrok http 5000
Enter fullscreen mode Exit fullscreen mode

You'll see output like:

Forwarding  https://abc123.ngrok-free.app -> http://localhost:5000
Enter fullscreen mode Exit fullscreen mode

Copy the HTTPS URL — you'll use it in the next step.


Step 4: Configure the Webhook (3 min)

  1. Go to your Meta App → WhatsApp → Configuration
  2. Under Webhook, click Edit
  3. Enter:
    • Callback URL: https://your-ngrok-url.ngrok-free.app/webhook
    • Verify Token: my_custom_verify_token_123 (must match your .env)
  4. Click Verify and Save

Meta will send a GET request to your webhook. If the verify token matches, you're connected.

  1. Subscribe to the messages event:
    • In the webhook configuration, click Manage
    • Subscribe to messages

Step 5: Send a Test Message (2 min)

Add a phone number to your WhatsApp Business Account test numbers:

  1. Meta App → WhatsApp → API Setup
  2. Under Test Number, add your personal phone number
  3. Send a message to your WhatsApp Business number from that phone

Your bot should reply instantly!

Test it:

  • Send "hello" → get the welcome menu
  • Send "pricing" → get pricing info
  • Send "human" → get escalation message
  • Send "random text" → get fallback

Step 6: Add Message Templates for Outbound Messages (5 min)

Your bot can reply to customers, but to initiate conversations (order updates, appointment reminders), you need pre-approved message templates.

Create a template via the Graph API:

curl -X POST "https://graph.facebook.com/v21.0/YOUR_BUSINESS_ACCOUNT_ID/message_templates" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "order_confirmation",
    "category": "UTILITY",
    "language": "en_US",
    "components": [
      {
        "type": "BODY",
        "text": "Hi {{1}}, your order #{{2}} has been confirmed! Expected delivery: {{3}}. Track here: {{4}}"
      }
    ]
  }'
Enter fullscreen mode Exit fullscreen mode

Template categories and India pricing:

Category Rate (India) Use Case
Marketing ₹0.86/message Promotions, offers
Utility ₹0.115/message Order updates, reminders
Authentication ₹0.115/message OTPs, verification
Service Free (24-hr window) Customer-initiated replies

Pro tip: Utility messages are 7.5× cheaper than marketing. Classify correctly.


Step 7: Add AI-Powered Responses (Optional, 5 min)

Replace the rule-based get_reply() function with an AI-powered version using OpenAI:

import openai

openai.api_key = os.getenv("OPENAI_API_KEY")

def get_reply(message_text):
    """AI-powered reply using OpenAI."""
    response = openai.ChatCompletion.create(
        model="gpt-4o-mini",
        messages=[
            {
                "role": "system",
                "content": (
                    "You are a helpful customer support assistant for an Indian business. "
                    "Keep replies under 100 words. Use simple language. "
                    "If you don't know something, say 'Let me connect you to a human agent.'"
                ),
            },
            {"role": "user", "content": message_text},
        ],
        max_tokens=150,
    )
    return response.choices[0].message.content
Enter fullscreen mode Exit fullscreen mode

Now your bot can handle any question, not just pre-programmed ones.


Step 8: Deploy to Production (5 min)

For production, you need a real server. Options:

Platform Cost Difficulty
Railway.app ₹0 (free tier) Easy
Render.com ₹0 (free tier) Easy
AWS EC2 ₹500/month Medium
DigitalOcean ₹400/month Medium

Deploy to Railway (easiest):

# Install Railway CLI
npm install -g @railway/cli

# Login and deploy
railway login
railway init
railway up
Enter fullscreen mode Exit fullscreen mode

Update your webhook URL in Meta App configuration to your production URL.


Common Issues and Fixes

Problem Solution
Webhook verification fails Check VERIFY_TOKEN matches exactly in both .env and Meta dashboard
Messages not received Ensure you subscribed to messages event in webhook settings
Template rejected Templates must be in the correct category. No promotional content in UTILITY.
Token expired Generate a System User Token in Meta Business Settings
ngrok URL changed ngrok free tier gives a new URL each session. Update webhook config.

What You Built

In 30 minutes, you now have:

  • ✅ A working WhatsApp chatbot that replies to customers
  • ✅ FAQ handling for common questions
  • ✅ Human escalation flow
  • ✅ Message templates for outbound notifications
  • ✅ Optional AI integration for open-ended questions
  • ✅ A deployment path to production

Next steps:

  • Add a database (SQLite/PostgreSQL) to store conversations
  • Integrate with your CRM or Google Sheets
  • Add WhatsApp Flows for forms and surveys
  • Set up analytics to track response times and resolution rates

Full Source Code

The complete code for this tutorial is available on GitHub:
github.com/DawnofGenX/whatsapp-chatbot-tutorial


Found this helpful? Share it with a fellow developer. Have questions? Drop them in the comments below.

Top comments (0)