# WhatsApp Business API Integration for Indian Businesses
TL;DR
WhatsApp has 500M+ Indian users. WhatsApp Business API lets your DomainIndia-hosted website send order updates, OTPs, and promotional messages programmatically. This guide covers Meta Cloud API setup (free tier), BSP alternatives (Gupshup, Wati, Interakt), webhook handling, and template approval.
## Which API is right for you
| Provider | Setup speed | Cost | Best for |
| Meta Cloud API (direct) | 2-3 days | Per conversation, ~₹0.80-3.50 | Tech teams who can integrate |
| Gupshup | 1 day (they manage) | Similar + their fee | SMBs wanting managed | |
| Wati, Interakt, AiSensy | 1 hour (no-code + API) | Monthly subscription + per-msg | Non-tech founders, marketing teams |
Meta's Cloud API launched 2022 as a free-tier alternative to BSP (Business Solution Providers). For most tech-capable teams, it's the best path.
## WhatsApp conversation pricing (2026)
Meta charges per 24-hour "conversation" window, varying by country + category:
| Category | India rate (approx) | Use case |
| Utility | ₹0.80 | Order confirmation, appointment reminder |
| Authentication | ₹0.12 | OTP delivery |
| Marketing | ₹0.73 | Promotional campaigns |
| Service (inside 24h of user message) | Free | Replying to customer queries |
Service conversations are free if initiated by the user. Business-initiated messages cost based on category.
## Step 1 — Meta Cloud API setup
2
My Apps → Create App → Business type → Continue
4
Get a test phone number (provided free for testing)
5
Later: add production phone number via Meta Business Manager (requires business verification — PAN, GST, website)
6
Generate temporary access token (24h for testing) or permanent via System User in Business Manager
## Step 2 — Send your first message
```bash
curl -X POST
'https://graph.facebook.com/v20.0/{PHONE_NUMBER_ID}/messages'
-H 'Authorization: Bearer {ACCESS_TOKEN}'
-H 'Content-Type: application/json'
-d '{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "template",
"template": {
"name": "hello_world",
"language": { "code": "en_US" }
}
}'
```
`hello_world` is pre-approved by Meta. For custom templates, you submit text for approval.
**PHP:**
```php
function sendWhatsApp($to, $templateName, $params = []) {
$url = "https://graph.facebook.com/v20.0/" . getenv('WA_PHONE_ID') . "/messages";
$body = [
'messaging_product' => 'whatsapp',
'to' => $to,
'type' => 'template',
'template' => [
'name' => $templateName,
'language' => ['code' => 'en_IN'],
'components' => $params,
],
];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($body),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WA_ACCESS_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
]);
return json_decode(curl_exec($ch), true);
}
// Order confirmation
sendWhatsApp('919876543210', 'order_confirmation', [
[
'type' => 'body',
'parameters' => [
['type' => 'text', 'text' => 'Rajesh'], // {{1}}
['type' => 'text', 'text' => 'ORD-1234'], // {{2}}
['type' => 'text', 'text' => '₹1,500'], // {{3}}
],
],
]);
```
**Node.js:**
```javascript
import axios from 'axios';
async function sendWhatsApp(to, template, params) {
const resp = await axios.post(
`https://graph.facebook.com/v20.0/${process.env.WA_PHONE_ID}/messages`,
{
messaging_product: 'whatsapp',
to,
type: 'template',
template: {
name: template,
language: { code: 'en_IN' },
components: params,
},
},
{ headers: { Authorization: `Bearer ${process.env.WA_ACCESS_TOKEN}` } }
);
return resp.data;
}
```
## Step 3 — Template approval
Meta approves every message template before you can send. Process:
1
Business Manager → WhatsApp → Message templates → Create
2
Name: order_confirmation (lowercase, underscore)
3
Category: Utility / Authentication / Marketing
4
Language: English, Hindi, Tamil, etc.
6
Submit for approval — usually 15 min to 24 hours
**Approval tips:**
- Clear purpose — transactional, not promotional "check out our deals"
- No excessive emojis (max 2)
- No spammy URLs (shortened links often rejected)
- Variable placement at start/end is safer than middle
- Reject reason? — fix and resubmit with new name
## Step 4 — Handle incoming messages (webhook)
Users replying to your messages = incoming events.
Expose webhook endpoint at `https://yourcompany.com/webhook/whatsapp`:
```javascript
// Verification (GET) — Meta verifies endpoint
app.get('/webhook/whatsapp', (req, res) => {
const mode = req.query['hub.mode'];
const token = req.query['hub.verify_token'];
const challenge = req.query['hub.challenge'];
if (mode === 'subscribe' && token === process.env.WA_VERIFY_TOKEN) {
return res.send(challenge);
}
res.sendStatus(403);
});
// Event receiver (POST)
app.post('/webhook/whatsapp', express.json(), async (req, res) => {
const entry = req.body.entry?.[0];
const changes = entry?.changes?.[0];
const value = changes?.value;
// Incoming message
if (value?.messages) {
for (const msg of value.messages) {
const from = msg.from;
const text = msg.text?.body;
console.log(`${from}: ${text}`);
// Process — maybe auto-reply, create ticket, etc.
await handleIncomingMessage(from, text);
}
}
// Delivery/read receipts
if (value?.statuses) {
for (const s of value.statuses) {
await updateDeliveryStatus(s.id, s.status);
}
}
res.sendStatus(200);
});
```
Register webhook URL in Meta dashboard.
## Step 5 — Send interactive messages (buttons, lists)
Beyond plain text:
**Quick reply buttons:**
```json
{
"type": "interactive",
"interactive": {
"type": "button",
"body": { "text": "Did your package arrive?" },
"action": {
"buttons": [
{ "type": "reply", "reply": { "id": "yes", "title": "Yes" } },
{ "type": "reply", "reply": { "id": "no", "title": "No, issues" } }
]
}
}
}
```
**Product catalog** (e-commerce):
```json
{
"type": "interactive",
"interactive": {
"type": "product_list",
"header": { "type": "text", "text": "Today's Deals" },
"action": {
"catalog_id": "YOUR_CATALOG_ID",
"sections": [...]
}
}
}
```
Customers browse, tap, add to cart — all inside WhatsApp.
## Step 6 — OTP via WhatsApp
For authentication — far better than SMS deliverability in India.
Create template category: Authentication:
```
Your verification code is {{1}}. It expires in 10 minutes. Do not share this code.
```
```javascript
const otp = generate6DigitOTP();
await redis.setex(`otp:${phone}`, 600, otp);
await sendWhatsApp(phone, 'otp_login', [
{ type: 'body', parameters: [{ type: 'text', text: otp }] },
]);
```
Cost: ~₹0.12 per OTP (Authentication category) vs ~₹0.20 for SMS.
## Common pitfalls
## FAQ
Q
Can I use a normal WhatsApp number (not Business API)?
No — normal WhatsApp's automation is against ToS. Risk of ban. Business API is the only supported way for automation.
Q
Which BSP is best?
Gupshup (biggest in India, good support), Wati (no-code friendly), Interakt (Shopify integration), AiSensy (affordable monthly). Meta Cloud API direct if you have tech team.
Q
How long does business verification take?
1-7 business days. Need: company PAN, GST, bank statement, company website (must be live), CIN (for Pvt Ltd).
Q
Can I send marketing to anyone?
Only users who opt-in. Meta strictly enforces. Required: explicit consent checkbox on your website or other channels before first WhatsApp message.
Q
Group messaging?
Business API doesn't support group messaging. Broadcast lists only via native WhatsApp Business app (limited to 256 contacts per list).
Send WhatsApp updates from your DomainIndia-hosted site.
Get hosting