A WhatsApp + OpenAI Order Bot for a Sweet Shop in a Weekend (Hindi-First, GST-Aware)
A 4-shop Indore mithai brand wanted festive WhatsApp orders. We shipped a Hindi-first GPT-4o-mini bot on Twilio + Cloud API in 38 hours. ₹62k build, ₹4,200/month run.
Hrishikesh Baidya
September 6, 202512 min read
0%
A 4-shop mithai brand in Indore — call them Mishrilal Mithai — was about to lose another Diwali to phone orders. Their owner showed us 1,400 missed WhatsApp messages from last September, mostly customers asking "kaju katli ka rate kya hai" or "5 kg ladoo Saturday ko mil jayega?". By Sunday night we had a Hindi-first WhatsApp bot live on their existing Twilio number, taking GST-correct order quotes and routing the hard 7% to a human staffer. Build time: 38 hours across two engineers. Total spend: ₹62,000 fixed-build + ₹4,200/month running.
38 hrs
Build time, Friday eve to Sunday night
₹62k
Fixed-price build (2 engineers)
₹4.2k
Monthly run cost (1,800 conversations)
93%
Auto-resolved without human escalation
## The Answer in 60 Words
We pointed Twilio's WhatsApp Business API at a Node.js webhook that proxies into GPT-4o-mini with a Hindi-Hinglish system prompt, a JSON menu of 41 SKUs with HSN codes, and 3 escalation rules. Customers send "5 kg kaju katli Saturday delivery", the bot replies with quote + 5% GST + UPI link in 1.8 seconds. Hard cases get pushed to the shop owner's phone.
## Why This Matters Now
Meta switched WhatsApp Business API to per-message pricing on July 1, 2025 — utility templates inside the 24-hour service window are now free, marketing templates in India cost roughly ₹0.78 each ([Twilio pricing changelog](https://help.twilio.com/articles/30304057900699)). For a sweet shop doing 60 inbound conversations a day during festive weeks, you can run a bot on under ₹150/day in WhatsApp fees. Combined with GPT-4o-mini at $0.15/$0.60 per million tokens, the unit economics finally make sense for Tier-2 SMB retail. We tested this exact setup in early September 2025 specifically so clients could ride the Ganesh Chaturthi → Diwali wave.
## The Client (Specific Details)
- Sector: Mithai + namkeen (kaju katli, soan papdi, ghewar, 41 active SKUs)
- Location: Indore, MP — 4 retail outlets, 22 staff, GSTIN starts with 23
- Order volume: 280 orders/week off-season, peaks at 1,100/week during Diwali fortnight
- Existing stack: A standalone Twilio number for receipts, no chatbot, manual reply by 2 staff
- Owner's exact words: "Last Diwali humne 4 lakh ka business kho diya kyunki phone band tha"
## The Architecture (One Diagram, in Words)
Customer sends WhatsApp message → Meta Cloud API → Twilio webhook → Express.js receiver on a ₹740/month Hetzner CX22 → GPT-4o-mini with system prompt + retrieval over a 41-SKU menu JSON → Postgres logs the conversation + extracts an order draft → bot replies via Twilio with the quote + UPI deep-link → escalation rule fires for 3 conditions → owner gets a Slack ping with full transcript.
WA
Twilio + WhatsApp Cloud API
Twilio acts as the BSP wrapper. Inbound webhook on POST /sms. Outbound replies via Twilio's REST API. The 24-hour customer service window keeps replies free.
AI
GPT-4o-mini with Hinglish prompt
Single OpenAI call per turn, model gpt-4o-mini-2024-07-18. System prompt is 800 tokens, full menu JSON is injected on every call (4.2k tokens) — total cost per conversation: ₹0.34.
DB
Postgres for state + order drafts
Two tables: conversations (msg log) and order_drafts (extracted JSON). Owner sees pending drafts on a 4-row Tally-like dashboard before confirming.
esc
3 hard-coded escalation rules
Custom orders > ₹15,000, complaints (regex match), or third bot reply without progress → push the thread to owner's personal WhatsApp + Slack ping.
## The Hindi-First System Prompt (Real Text We Shipped)
The prompt is the entire product. Here is the exact one running in production, lightly redacted:
You are Mishri, the order assistant for Mishrilal Mithai (Indore, since 1962).
Reply in Hinglish — Devanagari OR Roman script, match the customer's script.
Be warm, short (under 40 words per reply), and never invent prices.
Menu is in the JSON below. Every SKU has price_per_kg, hsn_code, gst_rate.
Do NOT promise delivery dates beyond the next 3 days.
Process:
1. Greet in Hinglish on first message.
2. If customer names an item, confirm rate + ask quantity.
3. Quote total = (price * qty) + GST. Show the GST line item clearly.
4. Ask for delivery address pincode. Confirm slot.
5. End with a UPI deep-link: upi://pay?pa=mishrilal@hdfcbank&am=<total>&cu=INR
Escalate (reply with EXACT token "ESCALATE_TO_OWNER") if:
- Total exceeds 15000
- Customer mentions complaint, refund, kharab, ganda, or stale
- You have replied 3 times and no order has been confirmed
Always price kaju katli at the festival rate during Sep-Nov.
Never apologize for prices. If asked about discounts, say
"Diwali offer chal raha hai, 5kg+ par 6% chhoot."
Menu JSON: {{ MENU_JSON }}
We learned 4 things tuning this. First, Hinglish-script-mirroring is non-negotiable — customers who type Roman script feel insulted by Devanagari replies, and vice versa. Second, the model invents prices when the menu JSON is missing one field — we added a "if you do not see this SKU in JSON, escalate" clause and the hallucinations stopped. Third, the GST line item must be explicit — Indore CAs check screenshots. Fourth, the UPI deep-link converts 2.4x better than asking for bank details.
## The 38-Hour Build Plan (Copy This)
1
Friday 18:00 — Twilio Sandbox + ngrok
Sign up at twilio.com, activate the WhatsApp Sandbox in 4 minutes. Spin up an Express.js server locally, expose with ngrok. Send "join <keyword>" from your phone. First inbound webhook hits your laptop within 90 seconds. Verify: log the req.body, see {From: 'whatsapp:+91...', Body: 'hello'}.
2
Friday 21:00 — Menu JSON + price audit
Sit with the shop owner, photograph the price board, type 41 SKUs into a JSON file. Each row: name_hi, name_en, price_per_kg, hsn_code (1704 for sugar confectionery), gst_rate (5%). The audit is the slow step — half the prices on the board were stale. Owner re-priced 14 SKUs Friday night.
3
Saturday 09:00 — System prompt v1 + first OpenAI call
Wire up the OpenAI SDK. Write the prompt above, inject the menu JSON on every call. Run 20 test conversations from your own phone — kaju katli rate, ladoo 5kg, complaint about freshness. Tune the prompt every 4 messages. By Saturday lunch you have v3 of the prompt.
4
Saturday 14:00 — Postgres + state machine
Two tables. conversations (id, from_number, msg_in, msg_out, ts). order_drafts (id, from_number, items_json, total_inr, status). On every inbound message, append to conversations and ask GPT to also return a JSON order_draft alongside the human reply (use a 2-message function-call pattern).
5
Saturday 19:00 — Escalation rules
Three regex + threshold rules in the webhook handler. Total > 15000 INR. Body contains complaint, refund, kharab, ganda, stale, baasi. Three bot replies without an order_draft confirmed. Each fires a Twilio API call to push the transcript to the owner's personal number + a Slack webhook.
6
Sunday 10:00 — UPI deep-link + receipt template
Generate upi://pay?pa=<handle>&am=<total>&cu=INR&tn=<orderid> per quote. Submit a Meta-approved utility template "order_receipt" via Twilio Console — gets approved in 2 hours on a clean account. Fall back to free-form reply inside the 24-hour window if the template review is delayed.
7
Sunday 15:00 — Production webhook + WhatsApp number switch
Push the Express app to the Hetzner box behind Caddy + HTTPS. Move Twilio webhook URL from ngrok to the Hetzner domain. Apply for a real Meta-verified WhatsApp Business number through Twilio (5-day approval typically) — until then, run the Sandbox for the owner's family + 8 trusted regulars.
8
Sunday 22:00 — Soft launch + watch logs
Owner WhatsApped 12 regulars: "naya order system, try kar ke batao". Eight ordered. Two complained about a price (we updated the menu JSON in 90 seconds, no redeploy needed because we read the JSON on every request). Bot handled 11/12 without escalation.
## The Cost Breakdown (Real Numbers)
A single human agent handling the same 1,800 conversations across 30 days would cost the shop ₹22,000–₹28,000 in salary plus weekend-off issues. The bot does not eat soan papdi during shift.
## The Pre-Launch Checklist
Menu JSON has all 41 SKUs with current prices, HSN code 1704, GST rate 5
System prompt has explicit "no invented prices" + "no delivery beyond 3 days" clauses
3 escalation rules wired and tested with synthetic messages
Owner's personal WhatsApp number is the escalation target (not a shared inbox)
Slack webhook fires within 8 seconds of an escalation trigger
UPI deep-link tested on PhonePe, GPay, and Paytm — all open the payment screen
Meta-approved utility template "order_receipt" live in Twilio Console
Postgres snapshot scheduled nightly to S3
Token-cost alarm at $1.50/day in OpenAI dashboard
Owner trained on flipping the master kill switch (env DISABLE_BOT=1) in 1 step
## Common Mistakes (Each One Cost Us a Saturday)
Symptom: bot replies in Devanagari to a Roman-Hinglish customer. Cause: prompt drift — the model defaults to Devanagari for Hindi tokens. Fix: add an explicit "mirror the script of the last user message" instruction with a 2-line example. We saw a 22% drop in conversation length after this fix.
Symptom: hallucinated prices on a brand-new SKU. Cause: menu JSON missing the field, model fills in a plausible number. Fix: add a "if SKU is not in the JSON, reply 'sirji ek minute, owner ko check karne deta hu' and emit ESCALATE_TO_OWNER" clause. Eliminates the entire failure mode.
Symptom: customer asks for "thoda discount", bot offers a discount that doesn't exist. Cause: model trying to please. Fix: hard-code the discount policy in the prompt ("Diwali offer: 6% on 5kg+; nothing else allowed; if customer pushes, ESCALATE_TO_OWNER"). Owner approves all custom discounts manually.
Symptom: 12-message conversation with no order, customer ghosts. Cause: bot is too polite, never asks for a close. Fix: rule that after 4 turns without an order_draft, the bot says "main aapka order draft kar du? confirm bolne par link bhej dunga" — converted 31% of stalled threads.
Symptom: WhatsApp template "REJECTED" after submission. Cause: emoji or marketing language in a "utility" template. Fix: keep templates in plain text, no exclamation marks, no "buy now" — Meta's reviewers are strict but predictable. Our second submission passed in 90 minutes.
## A Real Conversation From Day 4 of Production
> Customer (Hinglish): bhai 3 kg ladoo Saturday morning ko Vijay Nagar?
> Bot: Namaste! Ladoo (motichoor) ka rate ₹520/kg hai. 3 kg = ₹1,560 + 5% GST ₹78 = ₹1,638. Saturday morning ka slot 10-12 ka kar du Vijay Nagar?
> Customer: haan kar do. UPI bhejo
> Bot: Order draft ID #4192. UPI link: upi://pay?pa=mishrilal@hdfcbank&am=1638&cu=INR&tn=4192 — pay karne par owner ko notification chala jayega aur 30 min me confirmation aa jayegi.
> Customer: [pays]
> Bot: Payment receive ho gaya, dhanyawaad! Saturday 10-12 par delivery confirm. Driver ka number 30 min me aayega.
Total time from first message to paid order: 2 minutes 47 seconds. Owner saw a Slack message "ORDER PAID #4192 ₹1,638" and printed the kitchen ticket.
## When Not to Build This
Skip the bot if: (a) you do under 25 inbound WhatsApp messages a day — the build economics do not work; just answer manually. (b) Your menu changes hourly (a tiffin service with a different lunch every day) — you will burn the engineering budget on JSON updates. Use a static template flow on the Cloud API instead. (c) You sell custom-cut sweets where every order is bespoke — the LLM cannot price-quote without a human in the loop, so you will hit the escalation rule on every single conversation.
## A Detail That Saved Diwali
On day 9 of production, the bot started replying with broken Devanagari for one customer — square boxes instead of characters. The customer's iPhone had a font rendering issue. We added a fallback: if our Postgres logs show the same emoji-character pattern in the customer's last 3 incoming messages, we reply in Roman script regardless of the prompt's mirror rule. Lost 20 minutes to find. The shop owner sent us a thank-you box of ghewar.
## How We Cross-Linked Into the Stack
This bot lives next to two other things we have built for SMBs in 2025: a [WhatsApp + OpenAI support bot in 6 hours](/blog/whatsapp-openai-customer-support-bot-6-hours-stack-gotchas) for a Surat textile exporter, and a [Hindi voice bot for a Tier-2 insurance agent](/blog/hindi-voice-bot-tier-2-insurance-twilio-sarvam-claude-sonnet) using Sarvam + Claude. Same architecture pattern, different conversational surface — and the same lesson: the prompt is the product, the LLM is the runtime. Hrishikesh, our CTO, runs each of these projects with the engineer who will own the post-launch tuning.
For founders comparing options, our AI automation team ships the same WhatsApp pattern for restaurants, clinics, and clinics-of-clinics. We saw the same payback curve on TalkDrill when we moved English-fluency feedback into a conversational flow — the conversational interface is the moat, not the model.
Our in-house voice AI work on TalkDrill (5,000+ Indian users on a similar Twilio + LLM stack) gave us the prompt-engineering muscle to ship Mishrilal in a weekend instead of a fortnight.
## FAQ
### Can I run this on the WhatsApp Cloud API directly without Twilio?
Yes — the Cloud API is free at low volume and Meta-native. We pick Twilio for clients who want a single billing relationship, conversation logs, and templated number-management. For a one-shop owner-operator, native Cloud API + a free webhook host saves about ₹500/month.
### What happens when OpenAI goes down?
We added a fallback in week 2: if the OpenAI call fails or exceeds 8 seconds, the bot replies with a templated "thoda traffic hai, owner ko bhej raha hu" and triggers the escalation. We have hit this once in 90 days — total 11 minutes of OpenAI degradation.
### Can the bot take payments without UPI?
Yes — we deep-link to Razorpay invoice URLs as a second option. UPI converts roughly 2.4x better in Tier-2 cities, so we default to UPI and only show the Razorpay link when the customer asks for "card option".
### How do you handle GST for inter-state delivery?
The prompt knows the shop's GSTIN starts with 23 (MP). For a delivery pincode whose state code differs, the bot computes IGST instead of CGST + SGST. The pincode-to-state lookup is a 19,000-row Postgres table the shop owner does not need to maintain.
### What's the model's accuracy on Hindi number understanding?
GPT-4o-mini handles "saade chaar kilo" (4.5 kg), "do sau gram" (200 g), and "paav kilo" (250 g) correctly in our test set of 240 utterances. Below 90% on hyperlocal slang ("aadhi-pao" in some dialects) — we accept the tradeoff and let the bot ask "kitne kg, sirji?".
### Can the same bot answer general FAQ like opening hours?
Yes — we added a static "facts" block to the system prompt: hours, address, owner's name, festival schedule. It costs 200 extra tokens per call (₹0.04) and removes 22% of inbound messages from the order-conversation path.
### How do I prove the bot is GST-compliant to my CA?
Every order draft writes to a Postgres row with line-item GST split, HSN code, and the customer's pincode-derived state. Owner's CA logs in monthly to a 1-page dashboard. The bot is a quote machine; the shop's existing Tally still posts the journal entry.
Want a WhatsApp order bot live on your number for the festive season?
We ship a Hindi-first WhatsApp + OpenAI bot for Indian SMB retailers in 7 working days. Fixed price ₹65k–₹95k depending on SKU count and integrations. Includes the Meta-verified number application, the prompt tuning, and 30 days of post-launch monitoring. Suitable if you take ≥ 30 inbound WhatsApp messages a day and your menu fits in a JSON file.