A sweet shop in Kanpur was taking Diwali orders on a personal WhatsApp number — one cousin typing replies, losing track of who ordered what, and hand-writing bills with the wrong GST. Over one weekend in August 2025 we built a WhatsApp bot that takes the order in Hindi, confirms quantities, shows a GST-correct bill, and drops every order into a Google Sheet the counter watches. WhatsApp Cloud API for messaging, OpenAI for understanding the Hindi, a tiny GST calculator for the bill. Here's the full build — including the festive-load gotcha that nearly broke it.
5%
GST on Most Packaged Mithai
₹0
WhatsApp Service-Conversation Cost
3x
Festive Order Spike Handled
## The 60-Word Answer
Use the WhatsApp Cloud API to receive and send messages via webhook. Pass each incoming Hindi message to OpenAI with a system prompt and an order-taking function, so the model extracts items and quantities from natural language. Run the items through a small GST calculator (most packaged mithai is 5%), reply with an itemised bill, and log confirmed orders to a Google Sheet. The whole thing is one webhook handler.
## Why a Bot, Not Just a Person on WhatsApp
A person on WhatsApp works until festive rush, when 200 messages arrive in an hour and orders get lost between "2 kg kaju katli" and "wait make it 1.5." A bot reads every message, never loses an order, and produces a consistent, GST-correct bill — which matters because hand-written festive bills are where small shops get GST wrong and where buyers who want input credit walk away. The bot doesn't replace the shop's warmth; it replaces the dropped orders and the wrong arithmetic during the three weeks a year that decide the shop's revenue.
📲
WhatsApp Cloud API
Meta's official, free-to-start messaging API. Incoming messages hit your webhook; you reply with a POST. No third-party BSP needed to begin.
🧠
OpenAI order extraction
Reads "2 kilo kaju katli aur ek dabba soan papdi" and returns structured items and quantities. Handles Hindi, Hinglish, and corrections naturally.
🧾
GST calculator
A small, auditable function — not the LLM — computes the bill. Most packaged mithai is 5% GST. Keep tax math in code you can verify, never in the model.
📋
Google Sheet order log
Every confirmed order appends a row the counter staff watch live. Zero new software for the shop to learn — they already trust a spreadsheet.
## What You'll Need
- A Meta Business account and a WhatsApp Cloud API app (free to set up in Meta for Developers)
- A WhatsApp Business phone number and a permanent access token
- An OpenAI API key
- Node.js 20+ and a public HTTPS endpoint for the webhook
- A Google Sheet plus a service-account key for the Sheets API
- The shop's menu with prices and the correct GST rate per item (confirm with their CA)
## Step 1: Receive WhatsApp Messages via Webhook
The Cloud API calls your webhook on every incoming message. You verify the webhook once, then handle message events.
// webhook.js
import express from "express";
const app = express();
app.use(express.json());
// Meta verifies your webhook once with a GET
app.get("/webhook", (req, res) => {
const VERIFY = process.env.WA_VERIFY_TOKEN;
if (req.query["hub.verify_token"] === VERIFY) {
return res.send(req.query["hub.challenge"]);
}
res.sendStatus(403);
});
// Incoming messages arrive as POST
app.post("/webhook", async (req, res) => {
res.sendStatus(200); // ACK immediately — process async
const msg = req.body?.entry?.[0]?.changes?.[0]?.value?.messages?.[0];
if (!msg || msg.type !== "text") return;
await handleMessage(msg.from, msg.text.body);
});
Tip: Always return 200 to Meta immediately, then do the slow work (OpenAI, Sheets) asynchronously. If your webhook takes too long to respond, Meta retries — and you process the same order twice. This is the festive-load gotcha in miniature; more on it below.
## Step 2: Understand the Order With OpenAI
A function-calling prompt turns messy Hindi into structured items. The model extracts; it does not price.
// understand.js
import OpenAI from "openai";
const openai = new OpenAI();
const MENU = "kaju katli, soan papdi, motichoor ladoo, gulab jamun, barfi";
const tools = [{
type: "function",
function: {
name: "record_order_items",
description: "Record the sweets the customer wants, with quantity and unit.",
parameters: {
type: "object",
properties: {
items: {
type: "array",
items: {
type: "object",
properties: {
name: { type: "string", description: one of: ${MENU} },
qty: { type: "number" },
unit: { type: "string", enum: ["kg", "box", "piece"] }
},
required: ["name", "qty", "unit"]
}
}
},
required: ["items"]
}
}
}];
export async function understand(history) {
const system = You take sweet-shop orders on WhatsApp for a Kanpur mithai shop.
Customers write in Hindi or Hinglish. Menu: ${MENU}.
Extract items, quantity and unit. Ask a short clarifying question if unclear.
Reply warmly in the customer's language. Do NOT calculate prices — that is done separately.;
return openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "system", content: system }, ...history],
tools, tool_choice: "auto", temperature: 0.3
});
}
## Step 3: The GST-Correct Bill (Code, Not the Model)
This is the part you must keep out of the LLM. Tax math goes in a small, testable function. Most packaged Indian sweets fall under 5% GST, split as 2.5% CGST + 2.5% SGST for an intra-state sale — but always confirm rates with the shop's CA, since some items differ.
// gst.js
const PRICES = { // per unit, in ₹
"kaju katli": { kg: 900 },
"soan papdi": { box: 250, kg: 500 },
"motichoor ladoo": { kg: 400 },
"gulab jamun": { box: 200 },
"barfi": { kg: 450 }
};
const GST_RATE = 0.05; // 5% on packaged mithai (confirm per item)
export function buildBill(items) {
const lines = items.map(it => {
const unitPrice = PRICES[it.name]?.[it.unit] ?? 0;
const amount = unitPrice * it.qty;
return { ...it, unitPrice, amount };
});
const subtotal = lines.reduce((s, l) => s + l.amount, 0);
const gst = +(subtotal * GST_RATE).toFixed(2);
const cgst = +(gst / 2).toFixed(2);
const sgst = +(gst / 2).toFixed(2);
const total = +(subtotal + gst).toFixed(2);
return { lines, subtotal, cgst, sgst, total };
}
Never let the LLM do the GST arithmetic. Models are confident and occasionally wrong at multi-step math, and a wrong tax figure on a real bill is a compliance problem, not a typo. The model extracts the order; deterministic code computes the money. We unit-test buildBill against the shop's CA-approved examples.
## Step 4: Reply, Confirm, and Log to the Sheet
// handle.js
import { understand } from "./understand.js";
import { buildBill } from "./gst.js";
export async function handleMessage(from, text) {
const history = loadHistory(from);
history.push({ role: "user", content: text });
const res = await understand(history);
const m = res.choices[0].message;
if (m.tool_calls) {
const { items } = JSON.parse(m.tool_calls[0].function.arguments);
const bill = buildBill(items);
const reply =
bill.lines.map(l => ${l.qty}${l.unit} ${l.name} — ₹${l.amount}).join("\n")
+ \nSubtotal: ₹${bill.subtotal}
+ \nCGST 2.5%: ₹${bill.cgst} SGST 2.5%: ₹${bill.sgst}
+ \nTotal: ₹${bill.total}\n\nConfirm karein? (haan/nahi);
await sendWhatsApp(from, reply);
saveDraftOrder(from, bill);
} else if (/haan|yes|confirm|ha\b/i.test(text)) {
const bill = getDraftOrder(from);
await appendToSheet(from, bill); // log confirmed order
await sendWhatsApp(from, "Order confirm! Aapka order taiyaar ho raha hai. Dhanyavaad 🙏");
} else {
await sendWhatsApp(from, m.content); // a clarifying question
}
}
## Step 5: Verify Before Diwali
1
Order in Hindi: "2 kilo kaju katli aur ek dabba soan papdi"
Expect a bill: 2kg kaju katli ₹1,800, 1 box soan papdi ₹250, subtotal ₹2,050, CGST ₹51.25, SGST ₹51.25, total ₹2,152.50. Check the GST math by hand against your CA's example.
2
Correction: "nahi, kaju katli 1.5 kilo kar do"
Expect the bot to update the quantity and re-issue the bill, not start over. This is where function-calling beats a rigid form.
3
Confirmation logs one row, not two
Say "haan" and check the Sheet appended exactly one order. Send the same message twice quickly to test idempotency — the festive-load test.
## The Festive-Load Gotcha
Symptom: during a rush, the same order lands in the Sheet two or three times. Cause: Meta retries the webhook if you don't ACK fast enough, and under load your handler was slow — so Meta re-sent the message and you processed it again. Fix: ACK with 200 instantly, process asynchronously, and dedupe on Meta's message id (store seen IDs for a few minutes). We hit exactly this on a 3x order spike; the fix was a 5-line dedupe and an instant ACK. Test it before the festival, not during.
## When NOT to Build This
Skip the bot if the shop does a handful of orders a day (a person is friendlier and the bot is overkill), if the menu changes hourly with no fixed prices (the bot needs a price list to bill), or if the owner won't trust any number the machine produces (then automate the order capture but leave billing to a human). And keep GST out of the model regardless — if you can't put correct rates in code, don't ship the billing part at all. Capture orders, hand off the bill.
## Real Example: The Kanpur Mithai Shop
A family mithai shop in Kanpur, ~40 WhatsApp orders a day normally, spiking to 120+ during the Diwali fortnight, all on one cousin's phone.
We shipped the bot above on a weekend. It took orders in Hindi and Hinglish, produced GST-correct bills the shop's CA had pre-approved, and logged confirmed orders to a Sheet the counter watched. The festive-load dedupe fix earned its keep on day one of the rush, when traffic tripled and the naive version would have double-booked. The cousin went back to packing sweets instead of typing. We later generalised this into a full
WhatsApp + OpenAI order bot writeup and paired it with a
Tally sync that closes the books daily.
The same WhatsApp Cloud API foundation runs under our
GSTR-3B reminder workflow for a CA firm, and the Hindi-understanding piece reuses the patterns behind
TalkDrill, our in-house English-speaking app. Our
AI automation team ships these vernacular commerce bots for Indian retailers regularly.
## Frequently Asked Questions
### Is the WhatsApp Cloud API free?
The Cloud API itself is free to set up, and service conversations (where the customer messages you first) are free within a rolling window under Meta's current pricing. Business-initiated template messages are charged. For an order bot where customers message first, most conversations cost nothing — but check Meta's latest pricing, which changes.
### Can the WhatsApp bot understand orders written in Hindi?
Yes. Passing the message to OpenAI with a function-calling prompt lets the model extract items, quantities, and units from natural Hindi or Hinglish — including corrections like "make it 1.5 kg instead." The model handles the language; a separate code function handles the pricing and GST.
### What GST rate applies to sweets and mithai?
Most packaged Indian sweets (mithai) attract 5% GST, split as 2.5% CGST and 2.5% SGST for an intra-state sale. Some items and packaging can differ, so always confirm the exact rate per product with the shop's chartered accountant before wiring it into the billing code.
### Should the AI calculate the GST bill?
No. Keep all tax arithmetic in a small, testable code function, never in the language model. Models can be confidently wrong at multi-step math, and an incorrect tax figure on a real bill is a compliance issue. The model extracts the order; deterministic code computes the money.
### How do I stop duplicate orders during a festive rush?
Acknowledge Meta's webhook with a 200 response instantly, process the order asynchronously, and dedupe on the message ID (store seen IDs for a few minutes). Meta retries the webhook if you respond slowly under load, which is what causes the same order to land in your log twice.
### How long does it take to build a WhatsApp order bot?
A focused engineer can ship a working v1 over a weekend: a few hours for the webhook and WhatsApp send/receive, a few for the OpenAI extraction and the GST calculator with tests, and a few for the Google Sheet logging and a dedupe pass. Menu setup with the shop takes additional coordination time.
Want a WhatsApp order bot live on your number before the next festival?
We build Hindi and vernacular WhatsApp order bots for Indian retailers — natural-language ordering, GST-correct bills, and a simple order log your staff already trust — in 7–10 working days. Typical project: ₹55k–₹1.1L. Suitable for sweet shops, bakeries, and small retailers with a fixed menu. We test the festive-load path before you go live.
Book a 20-min Call
As
Hrishikesh, our CTO, puts it: let the AI read the Hindi, let the code do the maths, and let the shopkeeper pack the sweets. Everyone does what they're good at.