WhatsApp Business API Integration Guide
This guide covers WhatsApp Business API setup via Gupshup for Juniro's transactional messaging needs.
Why Gupshup (Not Twilio)
| Factor | Gupshup | Twilio |
|---|---|---|
| Cost | Lower (closer to Meta rates) | Higher markup (+25-50%) |
| India support | Excellent (HQ in India) | Good |
| US support | Full coverage | Full coverage |
| India numbers | Easy to acquire | May need extra docs |
| Meta partnership | Partner of the Year 2023 & 2024 | Standard partner |
| Scale | 120B+ messages/year | Large scale |
Bottom line: Same capabilities, lower cost, better India support.
When to Implement
| Stage | WhatsApp Approach |
|---|---|
| Pre-launch (now) | Manual WhatsApp from personal phone — free, personal, effective |
| Post-launch | Gupshup WhatsApp API — automated confirmations, reminders |
| At scale (1000+ bookings/mo) | Essential for automation |
Recommendation: Start the approval process 4-6 weeks before you need it. Verification can take 2-3 weeks.
Use Cases for Juniro
Phase 1: Post-Launch (Priority)
| Use Case | Trigger | Message Type |
|---|---|---|
| Booking confirmation | Parent books class | Utility |
| Class reminder | 24 hours before class | Utility |
| Provider notification | New booking received | Utility |
| Cancellation notice | Class cancelled | Utility |
Phase 2: Growth
| Use Case | Trigger | Message Type |
|---|---|---|
| Welcome message | New signup (opted-in) | Marketing |
| Review request | 24 hours after class | Utility |
| Waitlist notification | Spot available | Utility |
| Payment reminder | Payment due/failed | Utility |
Phase 3: Engagement
| Use Case | Trigger | Message Type |
|---|---|---|
| New class alert | Provider adds class in saved category | Marketing |
| Referral program | Friend signs up | Marketing |
| Re-engagement | Inactive for 30 days | Marketing |
Message Categories & Pricing
Meta charges based on message category and destination country.
Categories
| Category | Description | Example |
|---|---|---|
| Utility | Transactional, expected by user | Booking confirmation, reminders |
| Authentication | OTPs, verification | Login codes |
| Marketing | Promotional, optional | New class alerts, offers |
Pricing (via Gupshup, approximate)
| Destination | Utility | Marketing | Authentication |
|---|---|---|---|
| India | ~$0.005 | ~$0.012 | ~$0.004 |
| US | ~$0.015 | ~$0.025 | ~$0.014 |
Prices are Meta's rate + small Gupshup markup. Check Gupshup pricing for current rates.
Free Messages
Messages within a 24-hour customer service window (after user messages you first) are free.
Phone Number Strategy
Recommended: Two Numbers (Local Experience)
Use separate numbers for each market so users see a familiar local number:
| Market | Number | Why |
|---|---|---|
| India | +91 number | Indian users trust local numbers |
| US | +1 number | US users expect US numbers |
Meta Business Verification (one time)
↓
WhatsApp Business Account (WABA)
↓
┌───────────────────────────────────┐
│ +91 XXXXX XXXXX (India users) │
│ +1 XXX XXX XXXX (US users) │
└───────────────────────────────────┘
Why Two Numbers?
| Factor | One Number | Two Numbers |
|---|---|---|
| User trust | Foreign number looks suspicious | Local number feels familiar |
| Response rates | Lower | Higher |
| Cost | ~$1-2/mo | ~$3-4/mo |
| Setup complexity | Simpler | Slightly more work |
| Meta approval | One | One (same WABA) |
How It Works
- One Meta Business Verification — you don't need separate approvals
- One WhatsApp Business Account (WABA) — both numbers under same account
- Two phone numbers — each registered as WhatsApp sender
- Same templates — approved once, work on both numbers
Routing Logic
function getWhatsAppNumber(userCountry) {
if (userCountry === 'IN') {
return process.env.TWILIO_WHATSAPP_NUMBER_INDIA; // +91...
}
return process.env.TWILIO_WHATSAPP_NUMBER_US; // +1...
}
Alternative: One Number (Simpler)
If you prefer simplicity, one US number works globally:
One WhatsApp Business Number (+1)
↓
Message users in any country
├── India (+91) ✓
├── US (+1) ✓
└── Any country ✓
This works but Indian users may be less likely to engage with a foreign number.
Setup Process Overview
┌─────────────────────────────────────────────────────────────────┐
│ SETUP TIMELINE (4-6 weeks) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Week 1 Week 2 Week 3 Week 4 │
│ ─────── ─────── ─────── ─────── │
│ Gupshup Meta Phone Templates │
│ Account Business Numbers Approved │
│ Setup Verification Verified Ready! │
│ (5-20 days) │
│ │
└─────────────────────────────────────────────────────────────────┘
Step-by-Step Setup
Step 1: Create Gupshup Account
- Go to gupshup.io
- Click "Start for Free" or "Sign Up"
- Create an account with business email
- Complete business profile
- Add payment method (pay-as-you-go)
Time: 15 minutes
Step 2: Create Meta Business Portfolio
- Go to business.facebook.com
- Create a Meta Business Portfolio (if you don't have one)
- Add business details:
- Legal business name: Juniro (or your registered name)
- Business address
- Business website: juniro.com
- Business email
- Get administrator access with full permissions
Time: 30 minutes
Step 3: Start Meta Business Verification
- In Meta Business Settings → Security Center
- Click Start Verification
- Provide required documents:
| Document Type | Examples |
|---|---|
| Business registration | Certificate of incorporation, LLC filing |
| Tax document | EIN letter, GST registration (India) |
| Utility bill | Recent bill with business name & address |
| Bank statement | Statement showing business name |
- Submit and wait for review
Time: 5-20 business days (varies by region)
Tips for faster approval:
- Ensure business name matches exactly across all documents
- Use high-quality scans (not photos)
- Business website should be live with matching info
Step 4: Register WhatsApp Sender (Gupshup)
- Go to Gupshup Dashboard → WhatsApp → Get Started
- Click Create WhatsApp Business Account
- Connect your Meta Business Portfolio
- Follow the setup flow:
- Select your Meta Business Portfolio
- Create or select WhatsApp Business Account (WABA)
- Choose display name (appears to recipients)
Display Name Guidelines:
- ✓ "Juniro"
- ✓ "Juniro Kids Activities"
- ✗ "Best Kids Activities" (too generic)
- ✗ All caps "JUNIRO"
Time: 30 minutes (after Meta verification complete)
Step 5: Acquire and Verify Phone Numbers
Get Two Phone Numbers via Gupshup
| Number | Steps | Cost |
|---|---|---|
| US (+1) | Gupshup Dashboard → Numbers → Add US Number | ~$1-2/mo |
| India (+91) | Gupshup Dashboard → Numbers → Add India Number | ~$1-2/mo |
Requirements:
- Numbers must be able to receive SMS/voice (for OTP verification)
- India numbers are easier to acquire via Gupshup than other providers
Adding US Number:
- Gupshup Dashboard → Phone Numbers
- Select: United States
- Choose a number or use your own
- Verify via OTP
Adding India Number:
- Gupshup Dashboard → Phone Numbers
- Select: India
- Choose a number or use your own
- May require: Business PAN or GST (Gupshup makes this easier)
Alternative: Use Your Own Numbers
- Register existing numbers with Gupshup
- Verify ownership via SMS/voice OTP
Verification Process (for each number):
- In WhatsApp Sender setup, add phone number
- Meta sends OTP via SMS or voice call
- Enter OTP to verify ownership
- Number is now WhatsApp-enabled
- Repeat for second number
Time: 30 minutes (both numbers)
Step 6: Create Message Templates
Templates are required for outbound messages (business-initiated).
Submit via: Gupshup Dashboard → WhatsApp → Templates → Create Template
Template Structure:
Template Name: booking_confirmation
Category: Utility
Language: English
Header (optional): Booking Confirmed! ✅
Body:
Hi {{1}},
{{2}} is enrolled in {{3}}!
📅 {{4}}
⏰ {{5}}
📍 {{6}}
See you there!
Footer (optional): Reply HELP for assistance
Placeholders:
{{1}}= Parent name{{2}}= Child name{{3}}= Class name{{4}}= Date{{5}}= Time{{6}}= Location
Approval Time: Usually minutes (automated review), up to 24 hours
Step 7: Test in Sandbox (Optional)
Before going live, test with Gupshup's Sandbox:
- Gupshup Dashboard → WhatsApp → Sandbox
- Connect your WhatsApp to the sandbox number
- Test sending/receiving messages
- No approval needed for sandbox testing
Message Templates for Juniro
Utility Templates (High Priority)
1. Booking Confirmation
Name: booking_confirmation
Category: Utility
Hi {{1}}! ✅
{{2}} is booked for {{3}}.
📅 {{4}}
⏰ {{5}}
📍 {{6}}
Questions? Reply to this message.
— Juniro
2. Class Reminder (24h)
Name: class_reminder_24h
Category: Utility
Hi {{1}}! 👋
Reminder: {{2}} has {{3}} tomorrow.
📅 {{4}}
⏰ {{5}}
📍 {{6}}
See you there!
— Juniro
3. Provider New Booking
Name: provider_new_booking
Category: Utility
New booking! 🎉
{{1}} enrolled {{2}} in your {{3}} class.
📅 {{4}}
⏰ {{5}}
View details in your Juniro dashboard.
4. Cancellation Notice
Name: class_cancelled
Category: Utility
Hi {{1}},
{{2}} on {{3}} has been cancelled.
Reason: {{4}}
You'll receive a full refund within 5-7 days.
Questions? Reply here.
— Juniro
Marketing Templates (Lower Priority)
5. Welcome Message
Name: welcome_parent
Category: Marketing
Hey {{1}}! 👋
Welcome to Juniro — your new way to find kids' activities.
🔍 Browse 100+ activities
📅 Book instantly
⭐ Read real parent reviews
Start exploring: juniro.com
Reply STOP to opt out.
Template Approval Tips
Do's
- Be specific about what placeholders contain
- Make it clear the user requested/expects this message
- Include opt-out instructions for marketing messages
- Use proper grammar and formatting
Don'ts
- Don't start or end with a placeholder
- Don't use generic placeholders like "Important:
{{1}}" - Don't duplicate existing templates
- Don't include promotional content in Utility templates
Common Rejection Reasons
| Reason | Fix |
|---|---|
| Placeholder at start/end | Move placeholder to middle of sentence |
| Too generic | Add specific context about the message purpose |
| Policy violation | Remove prohibited content (gambling, adult, etc.) |
| Wrong category | Marketing content in Utility → recategorize |
| Duplicate | Check existing templates, modify if similar |
Opt-in Requirements
WhatsApp requires explicit user consent before sending messages.
Where to Collect Opt-in
| Touchpoint | Implementation |
|---|---|
| Signup form | Checkbox: "Send booking updates via WhatsApp" |
| Booking flow | "Get class reminders on WhatsApp?" |
| Account settings | WhatsApp notification preferences |
| Post-booking | "Want WhatsApp reminders for future classes?" |
Opt-in Language Example
☑️ Send me booking confirmations and class reminders via WhatsApp
By checking this box, you agree to receive transactional messages
from Juniro on WhatsApp. You can opt out anytime by replying STOP.
Storing Consent
Track in your database:
user: {
phone: "+919876543210",
whatsappOptIn: true,
whatsappOptInDate: "2025-02-14",
whatsappOptInSource: "booking_flow"
}
Technical Integration
Sending a Message (Node.js)
// Gupshup WhatsApp API
const GUPSHUP_API_URL = 'https://api.gupshup.io/wa/api/v1/template/msg';
// Get the right WhatsApp number based on user's country
function getWhatsAppFromNumber(userPhone) {
if (userPhone.startsWith('+91')) {
return process.env.GUPSHUP_WHATSAPP_NUMBER_INDIA;
}
return process.env.GUPSHUP_WHATSAPP_NUMBER_US;
}
// Send template message via Gupshup
async function sendBookingConfirmation(to, data) {
const fromNumber = getWhatsAppFromNumber(to);
const response = await fetch(GUPSHUP_API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'apikey': process.env.GUPSHUP_API_KEY,
},
body: new URLSearchParams({
source: fromNumber,
destination: to.replace('+', ''), // Gupshup expects without +
template: JSON.stringify({
id: 'booking_confirmation', // Your template ID
params: [
data.parentName,
data.childName,
data.className,
data.date,
data.time,
data.location,
],
}),
}),
});
const result = await response.json();
return result.messageId;
}
// Example: India user sees message from +91 number
sendBookingConfirmation('+919876543210', {
parentName: 'Priya',
childName: 'Aarav',
className: 'Swimming Basics',
date: 'Saturday, Feb 15',
time: '10:00 AM',
location: 'AquaKids, Jubilee Hills',
});
// Example: US user sees message from +1 number
sendBookingConfirmation('+14045551234', {
parentName: 'Sarah',
childName: 'Emma',
className: 'Soccer Camp',
date: 'Saturday, Feb 15',
time: '9:00 AM',
location: 'Piedmont Park, Atlanta',
});
Webhook for Incoming Messages
// pages/api/webhooks/gupshup-whatsapp.ts
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const body = await request.json();
// Gupshup webhook payload structure
const { type, payload } = body;
if (type === 'message') {
const { source, payload: messagePayload } = payload;
const from = source; // 919876543210
const message = messagePayload?.text; // User's message
console.log(`WhatsApp from +${from}: ${message}`);
// Handle STOP/HELP keywords
if (message?.toUpperCase() === 'STOP') {
await updateWhatsAppOptOut(`+${from}`);
}
}
// Acknowledge receipt
return NextResponse.json({ status: 'ok' });
}
Environment Variables
# .env.local
GUPSHUP_API_KEY=your-gupshup-api-key
GUPSHUP_APP_NAME=juniro
# WhatsApp Numbers (two numbers for local experience)
GUPSHUP_WHATSAPP_NUMBER_US=14155238886
GUPSHUP_WHATSAPP_NUMBER_INDIA=919876543210
Cost Estimation
Scenario: 500 bookings/month
| Message Type | Count | Rate (India) | Cost |
|---|---|---|---|
| Booking confirmation | 500 | $0.004 | $2.00 |
| 24h reminder | 500 | $0.004 | $2.00 |
| Provider notification | 500 | $0.004 | $2.00 |
| Total | 1,500 | ~$6/month |
Scenario: 2,000 bookings/month
| Message Type | Count | Rate (mixed) | Cost |
|---|---|---|---|
| Booking confirmation | 2,000 | $0.008 avg | $16.00 |
| 24h reminder | 2,000 | $0.008 avg | $16.00 |
| Provider notification | 2,000 | $0.008 avg | $16.00 |
| Review request | 1,000 | $0.008 avg | $8.00 |
| Total | 7,000 | ~$56/month |
Plus Gupshup phone numbers: ~$2-4/month for both
Checklist: WhatsApp Setup
Prerequisites
- Gupshup account created
- Payment method added to Gupshup
- Meta Business Portfolio created
- Administrator access to Meta Business Portfolio
Meta Verification (5-20 days)
- Business registration document uploaded
- Tax document uploaded
- Verification submitted
- Verification approved ✓
Gupshup Setup
- WhatsApp Business Account created in Gupshup
- US phone number (+1) added
- India phone number (+91) added
- US number verified with OTP
- India number verified with OTP
- Display name approved
Templates
-
booking_confirmationtemplate submitted -
class_reminder_24htemplate submitted -
provider_new_bookingtemplate submitted - All templates approved ✓
Integration
- Gupshup API integration complete
- Environment variables configured
- Test message sent successfully
- Webhook endpoint for incoming messages
Compliance
- Opt-in checkbox added to signup/booking flow
- Opt-in consent stored in database
- STOP/HELP keyword handling implemented
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Template rejected | Placeholder at start/end | Restructure message |
| Template rejected | Wrong category | Recategorize (Utility vs Marketing) |
| Verification delayed | Document mismatch | Ensure exact name match |
| Message not delivered | User not on WhatsApp | Fallback to SMS |
| Rate limited | Too many messages | Implement queuing |
Resources
- Gupshup WhatsApp API Docs
- Gupshup Getting Started
- Meta Business Verification
- WhatsApp Business Policy
- Gupshup Template Guide
Summary
| Item | Details |
|---|---|
| Provider | Gupshup (Meta Partner of the Year) |
| When to start | 4-6 weeks before needed |
| Total setup time | 2-4 weeks (mostly waiting for verification) |
| Cost to start | Pay-as-you-go + ~$2-4/mo for 2 numbers |
| Ongoing cost | ~$0.005-0.025 per message |
| Numbers needed | 2 (US +1 and India +91 for local trust) |
| Meta approvals | 1 (covers both numbers) |
| Priority use cases | Booking confirmations, reminders |