Essential commands, configurations, and code snippets for WhatsApp Business API integration with Twilio.
# Core Configuration
whatsapp-enabled,true
whatsapp-api-key,EAAQyour_api_key_here
whatsapp-phone-number-id,YOUR_PHONE_NUMBER_ID
whatsapp-business-account-id,YOUR_WABA_ID
whatsapp-webhook-verify-token,4qIogZadggQ.BEoMeciXIdl_MlkV_1DTx8Z_i0bYPxtSJwKSbH0FKlY
whatsapp-application-id,YOUR_APP_ID
# Optional: Advanced Settings
whatsapp-webhook-url,https://your-domain.com/webhooks/whatsapp
whatsapp-timeout,30000
whatsapp-retry-attempts,3
whatsapp-rate-limit,50
whatsapp-from-number,+553322980098
# Meta WhatsApp Configuration
export WHATSAPP_API_KEY="EAAQyour_api_key_here"
export WHATSAPP_PHONE_NUMBER_ID="YOUR_PHONE_NUMBER_ID"
export WHATSAPP_WABA_ID="YOUR_WABA_ID"
export WHATSAPP_VERIFY_TOKEN="4qIogZadggQ.BEoMeci..."
export WHATSAPP_APPLICATION_ID="YOUR_APP_ID"
export WHATSAPP_APP_SECRET="your_app_secret_here"
# Twilio Configuration
export TWILIO_ACCOUNT_SID="ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export TWILIO_AUTH_TOKEN="your_auth_token_here"
export TWILIO_PHONE_NUMBER="+553322980098"
# Webhook Configuration
export WEBHOOK_URL="https://your-domain.com/webhooks/whatsapp"
export WEBHOOK_PORT="3000"
# Base URL
https://graph.facebook.com/v18.0
# Send Message
POST /{phone-number-id}/messages
# Get Phone Number Info
GET /{phone-number-id}
# Mark as Read
POST /{message-id}
# Upload Media
POST /{phone-number-id}/media
# Get Message Templates
GET /{waba-id}/message_templates
# Base URL
https://api.twilio.com/2010-04-01
# Incoming Call Webhook
POST /twilio/voice
# Gather Handler
POST /twilio/gather
# Get Call Logs
GET /Accounts/{AccountSid}/Calls.json
curl -X POST \
'https://graph.facebook.com/v18.0/YOUR_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer EAAQyour_api_key_here' \
-H 'Content-Type: application/json' \
-d '{
"messaging_product": "whatsapp",
"to": "5511999999999",
"type": "text",
"text": {
"body": "Hello from General Bots!"
}
}'
curl -X POST \
'https://graph.facebook.com/v18.0/YOUR_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer EAAQyour_api_key_here' \
-H 'Content-Type: application/json' \
-d '{
"messaging_product": "whatsapp",
"to": "5511999999999",
"type": "image",
"image": {
"link": "https://example.com/image.jpg",
"caption": "Check this out!"
}
}'
curl -X POST \
'https://graph.facebook.com/v18.0/YOUR_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer EAAQyour_api_key_here' \
-H 'Content-Type: application/json' \
-d '{
"messaging_product": "whatsapp",
"to": "5511999999999",
"type": "template",
"template": {
"name": "hello_world",
"language": {
"code": "en_US"
}
}
}'
curl -X POST \
'https://graph.facebook.com/v18.0/wamid.HBgLNTE1OTk5OTk5OTk5FQIAERgSMzg1QTlCNkE2RTlFRTdFNDdF' \
-H 'Authorization: Bearer EAAQyour_api_key_here' \
-H 'Content-Type: application/json' \
-d '{
"messaging_product": "whatsapp",
"status": "read"
}'
REM Send simple text
SEND WHATSAPP TO "+5511999999999" WITH "Hello!"
REM Send with formatting
SEND WHATSAPP TO "+5511999999999" WITH "*Bold* and _italics_"
REM Send location
SEND WHATSAPP TO "+5511999999999" WITH LOCATION AT "-23.5505,-46.6333"
REM Send image
SEND WHATSAPP TO "+5511999999999" WITH IMAGE FROM "https://example.com/img.jpg"
REM Send document
SEND WHATSAPP TO "+5511999999999" WITH DOCUMENT FROM "https://example.com/doc.pdf"
REM Handle incoming messages
ON WHATSAPP MESSAGE RECEIVED
LET SENDER$ = GET WHATSAPP SENDER NUMBER
LET MESSAGE$ = GET WHATSAPP MESSAGE BODY
LET ID$ = GET WHATSAPP MESSAGE ID
LET TIMESTAMP$ = GET WHATSAPP MESSAGE TIMESTAMP
LOG "From: " + SENDER$ + " Msg: " + MESSAGE$
REM Process message
PROCESS MESSAGE SENDER$, MESSAGE$
END ON
| Code | Meaning | Solution |
| 200 | Success | Request completed |
| 400 | Bad Request | Check request body |
| 401 | Unauthorized | Verify access token |
| 403 | Forbidden | Check permissions |
| 404 | Not Found | Verify phone number ID |
| 429 | Rate Limited | Implement backoff |
| 500 | Server Error | Retry later |
{
"error": {
"message": "Invalid parameter",
"type": "WhatsAppApiError",
"code": 130426,
"error_data": {
"details": "Phone number ID is required"
}
}
}
| Error Code | Description | Solution |
| 130426 | Invalid parameter | Check phone number format |
| 130472 | Rate limit hit | Reduce message frequency |
| 131056 | 24-hour window | Use message templates |
| 131047 | Media upload failed | Check media URL |
| 131053 | Template not approved | Submit template for review |
// Remove all non-digits
function formatPhone(phone) {
return phone.replace(/\D/g, '');
}
// Examples
Input: +55 (11) 99999-9999
Output: 5511999999999
Input: +1-555-123-4567
Output: 15551234567
Input: 55 11 99999 9999
Output: 5511999999999
| Country | Code | Example |
| Brazil | 55 | 5511999999999 |
| USA | 1 | 15551234567 |
| Mexico | 52 | 5215512345678 |
| Argentina | 54 | 5491112345678 |
| Portugal | 351 | 351912345678 |
{
"object": "whatsapp_business_account",
"entry": [{
"id": "YOUR_WABA_ID",
"changes": [{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "+553322980098",
"phone_number_id": "YOUR_PHONE_NUMBER_ID"
},
"contacts": [{
"profile": {
"name": "John Doe"
},
"wa_id": "5511999999999"
}],
"messages": [{
"from": "5511999999999",
"id": "wamid.HBgLNTE1OTk5OTk5OTk5FQIAERgSMzg1QTlCNkE2RTlFRTdFNDdF",
"timestamp": "1704067200",
"text": {
"body": "Hello bot!"
},
"type": "text"
}]
},
"field": "messages"
}]
}]
}
{
"object": "whatsapp_business_account",
"entry": [{
"id": "YOUR_WABA_ID",
"changes": [{
"value": {
"status": "sent",
"id": "wamid.HBgLNTE1OTk5OTk5OTk5FQIAERgSMzg1QTlCNkE2RTlFRTdFNDdF",
"timestamp": "1704067201"
},
"field": "message_template_status_update"
}]
}]
}
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather action="https://your-domain.com/twilio/gather"
method="POST"
numDigits="6"
timeout="10">
<Say voice="alice" language="pt-BR">
Please enter your verification code followed by the pound sign.
</Say>
</Gather>
<Redirect>
https://twimlets.com/voicemail?Email=your-email@example.com
</Redirect>
</Response>
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>Please leave your message after the tone.</Say>
<Record action="https://your-domain.com/twilio/recording"
method="POST"
maxLength="30" />
<Say>Thank you for your message.</Say>
</Response>
# Test webhook endpoint
curl -X POST https://your-domain.com/webhooks/whatsapp \
-H "Content-Type: application/json" \
-d '{"test": true}'
# Test Meta API
curl -X GET "https://graph.facebook.com/v18.0/YOUR_PHONE_NUMBER_ID" \
-H "Authorization: Bearer EAAQyour_api_key_here"
# Test Twilio webhook
curl -X POST https://your-domain.com/twilio/voice \
-d "CallSid=CA123&From=+1234567890&To=+553322980098"
# Check SSL certificate
openssl s_client -connect your-domain.com:443
# General Bots logs
tail -f .gbot/logs/bot.log
# Webhook server logs (PM2)
pm2 logs whatsapp-webhook
# System logs
journalctl -u whatsapp-webhook -f
# Twilio debugger
# https://console.twilio.com/us1/develop/monitor/debugger
# Meta webhook status
# https://developers.facebook.com/apps/YOUR_APP_ID/webhooks/
| Tier | Messages/Day | Messages/Second |
| Tier 1 | 1,000 | 1 |
| Tier 2 | 10,000 | 5 |
| Tier 3 | 100,000 | 50 |
| Tier 4 | Unlimited | 1,000 |
const rateLimiter = {
requests: [],
maxRequests: 50,
timeWindow: 60000, // 1 minute
canMakeRequest() {
const now = Date.now();
this.requests = this.requests.filter(t => now - t < this.timeWindow);
return this.requests.length < this.maxRequests;
},
recordRequest() {
this.requests.push(Date.now());
}
};
REM Bold text
*bold text*
REM Italics
_italics_
REM Strikethrough
~strikethrough~
REM Monospace
```monospace```
REM Combined
*_bold and italic_*
REM Line breaks
Line 1
Line 2
REM Formatted menu
SEND WHATSAPP TO "+5511999999999" WITH "🤖 *Bot Menu*" + CHR$(10) + CHR$(10) + "1. 📊 Status" + CHR$(10) + "2. 🌐 Weather" + CHR$(10) + "3. 📧 Contact"
REM Address
SEND WHATSAPP TO "+5511999999999" WITH "📍 *Address:*" + CHR$(10) + "123 Main St" + CHR$(10) + "São Paulo, SP" + CHR$(10) + "Brazil"
REM Code snippet
SEND WHATSAPP TO "+5511999999999" WITH "```bash" + CHR$(10) + "npm install" + CHR$(10) + "```"
Meta for Developers:
https://developers.facebook.com/
Meta Business Suite:
https://business.facebook.com/
WhatsApp Business API:
https://developers.facebook.com/docs/whatsapp/
Webhook Configuration:
https://developers.facebook.com/apps/YOUR_APP_ID/webhooks/
Message Templates:
https://business.facebook.com/latest/wa/manage/message-templates/
Twilio Console:
https://console.twilio.com/
Twilio Debugger:
https://console.twilio.com/us1/develop/monitor/debugger
TwiML Bins:
https://console.twilio.com/us1/develop/twiml/bins
Phone Numbers:
https://console.twilio.com/us1/develop/phone-numbers/manage/active
Documentation:
https://botbook.general-bots.com/
Community Discord:
https://discord.gg/general-bots
GitHub Repository:
https://github.com/general-bots/general-bots
# Check Twilio webhook is configured
twilio phone-numerals:info +553322980098
# Test webhook manually
curl -X POST https://your-domain.com/twilio/voice \
-d "CallSid=CA123&From=+1234567890"
# Verify voice capability is enabled
# In Twilio Console: Phone Numbers > Active Numbers > Your Number
# Check "Voice" is enabled
# Verify access token
curl -X GET "https://graph.facebook.com/v18.0/me" \
-H "Authorization: Bearer YOUR_TOKEN"
# Check phone number ID
curl -X GET "https://graph.facebook.com/v18.0/YOUR_PHONE_NUMBER_ID" \
-H "Authorization: Bearer YOUR_TOKEN"
# Test message format
# Ensure phone number: 5511999999999 (no +, no spaces)
# Verify webhook subscription
curl -X GET "https://graph.facebook.com/v18.0/YOUR_APP_ID/subscriptions" \
-H "Authorization: Bearer YOUR_TOKEN"
# Test webhook endpoint
curl -X POST https://your-domain.com/webhooks/whatsapp \
-H "Content-Type: application/json" \
-d '{"object":"whatsapp_business_account","entry":[]}'
# Check webhook is subscribed to "messages" field
# In Meta Dashboard: WhatsApp > API Setup > Webhook > Manage
function validatePhoneNumber(phone) {
// Remove non-digits
const cleaned = phone.replace(/\D/g, '');
// Check length (10-15 digits)
if (cleaned.length < 10 || cleaned.length > 15) {
return false;
}
// Check if all digits
if (!/^\d+$/.test(cleaned)) {
return false;
}
return cleaned;
}
function formatMessage(template, variables) {
let message = template;
for (const [key, value] of Object.entries(variables)) {
message = message.replace(new RegExp(`{{${key}}}`, 'g'), value);
}
return message;
}
// Usage
const template = 'Hello {{name}}, your order {{orderId}} is confirmed!';
const variables = { name: 'John', orderId: '12345' };
const message = formatMessage(template, variables);
// Result: "Hello John, your order 12345 is confirmed!"
async function sendWithRetry(whatsapp, to, message, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await whatsapp.sendText(to, message);
} catch (error) {
if (attempt === maxRetries) {
throw error;
}
// Exponential backoff
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
# Node.js
npm install express twilio body-parser axios
# Python
pip install flask requests twilio
# BASIC
REM No installation required
# Reverse proxy (nginx)
apt install nginx
# Process manager (PM2)
npm install -g pm2
# SSL certificate (Let's Encrypt)
apt install certbot python3-certbot-nginx
Replace with your IDs:
WhatsApp Settings:
https://business.facebook.com/latest/settings/whatsapp_account/?business_id=YOUR_BUSINESS_ID&selected_asset_id=YOUR_WABA_ID&selected_asset_type=whatsapp-business-account
Webhook Configuration:
https://developers.facebook.com/apps/YOUR_APP_ID/webhooks/
Message Templates:
https://business.facebook.com/latest/wa/manage/message-templates/?waba_id=YOUR_WABA_ID
API Usage:
https://developers.facebook.com/apps/YOUR_APP_ID/usage/
For detailed documentation: See README.md
For troubleshooting: See troubleshooting.md
For code examples: See WhatsApp Examples
For webhook setup: See WhatsApp Webhooks