WABA API
Manage WhatsApp Business Account (WABA) settings, retrieve account information, and configure webhook subscriptions for real-time notifications.
Official Documentation: WhatsApp Business Accounts API
Overview
The WABA API provides account-level management capabilities:
- Get Account Info: Retrieve WABA metadata and settings
- Manage Subscriptions: Configure webhook subscriptions
- Update Webhooks: Modify webhook URLs and verify tokens
- Unsubscribe: Remove webhook subscriptions
Endpoints
GET /{WABA_ID}?fieldsGET /{WABA_ID}/subscribed_appsPOST /{WABA_ID}/subscribed_appsDELETE /{WABA_ID}/subscribed_appsImportant Notes
Quick Start
import WhatsApp from 'meta-cloud-api';
const client = new WhatsApp({ accessToken: process.env.CLOUD_API_ACCESS_TOKEN!, phoneNumberId: Number(process.env.WA_PHONE_NUMBER_ID), businessAcctId: process.env.WA_BUSINESS_ACCOUNT_ID!,});
// Get WABA account infoconst account = await client.waba.getWabaAccount([ 'id', 'name', 'timezone_id', 'message_template_namespace',]);
// Get webhook subscriptionsconst subscriptions = await client.waba.getAllWabaSubscriptions();
// Update webhook subscriptionawait client.waba.updateWabaSubscription({ override_callback_uri: 'https://example.com/webhook', verify_token: 'your-verify-token',});
// Unsubscribe from webhooksawait client.waba.unsubscribeFromWaba();Get WABA Account Information
Retrieve WhatsApp Business Account details and settings.
Get All Available Fields
const account = await client.waba.getWabaAccount([ 'id', 'name', 'timezone_id', 'message_template_namespace', 'account_review_status', 'business_verification_status', 'country', 'currency', 'ownership_type', 'primary_business_location',]);
console.log(account);// {// id: '123456789',// name: 'My Business',// timezone_id: 'America/Los_Angeles',// account_review_status: 'APPROVED',// currency: 'USD'// }Get Specific Fields
// Just the essentialsconst basicInfo = await client.waba.getWabaAccount([ 'id', 'name', 'timezone_id',]);
// Account status fieldsconst status = await client.waba.getWabaAccount([ 'account_review_status', 'business_verification_status',]);Check Account Status
const account = await client.waba.getWabaAccount([ 'account_review_status', 'business_verification_status',]);
if (account.account_review_status !== 'APPROVED') { console.warn('Account review pending');}
if (account.business_verification_status !== 'verified') { console.warn('Business verification incomplete');}Manage Webhook Subscriptions
Configure and manage webhook subscriptions for real-time notifications.
Get Current Subscriptions
const subscriptions = await client.waba.getAllWabaSubscriptions();
console.log(subscriptions);// {// data: [// {// whatsapp_business_api_data: {// subscribed_fields: ['messages', 'message_status']// }// }// ]// }Subscribe to Webhooks
await client.waba.updateWabaSubscription({ override_callback_uri: 'https://api.example.com/webhook', verify_token: 'my-secure-verify-token-123',});
console.log('Webhook subscription configured');Update Webhook URL
// Change webhook endpointawait client.waba.updateWabaSubscription({ override_callback_uri: 'https://new-domain.com/webhook', verify_token: process.env.WEBHOOK_VERIFY_TOKEN!,});Unsubscribe from Webhooks
await client.waba.unsubscribeFromWaba();
console.log('Webhook subscription removed');Complete Webhook Setup
Example of comprehensive webhook configuration:
import express from 'express';import WhatsApp from 'meta-cloud-api';
const app = express();const VERIFY_TOKEN = process.env.WEBHOOK_VERIFY_TOKEN!;
// Webhook verification endpoint (GET)app.get('/webhook', (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 === VERIFY_TOKEN) { console.log('Webhook verified'); res.status(200).send(challenge); } else { res.sendStatus(403); }});
// Webhook notification endpoint (POST)app.post('/webhook', express.json(), (req, res) => { console.log('Webhook received:', JSON.stringify(req.body, null, 2)); res.sendStatus(200);});
app.listen(3000, async () => { console.log('Webhook server running on port 3000');
// Configure WABA subscription const client = new WhatsApp({ accessToken: process.env.CLOUD_API_ACCESS_TOKEN!, phoneNumberId: Number(process.env.WA_PHONE_NUMBER_ID), businessAcctId: process.env.WA_BUSINESS_ACCOUNT_ID!, });
await client.waba.updateWabaSubscription({ override_callback_uri: 'https://yourdomain.com/webhook', verify_token: VERIFY_TOKEN, });
console.log('WABA webhook configured');});Response Formats
Get WABA Account Response
{ id: '123456789', name: 'My Business Name', timezone_id: 'America/Los_Angeles', message_template_namespace: 'abc123_def456', account_review_status: 'APPROVED', business_verification_status: 'verified', country: 'US', currency: 'USD', ownership_type: 'SELF', primary_business_location: 'US'}Get Subscriptions Response
{ data: [ { application: { id: 'APP_ID', name: 'My App' }, whatsapp_business_api_data: { subscribed_fields: [ 'messages', 'message_status', 'message_echoes' ] } } ]}Update Subscription Response
{ success: true}Error Handling
try { await client.waba.updateWabaSubscription({ override_callback_uri: 'https://example.com/webhook', verify_token: 'token', });} catch (error) { if (error.response) { const { code, message } = error.response.data.error;
switch (code) { case 100: console.error('Invalid webhook URL or verify token'); break; case 190: console.error('Invalid access token'); break; case 200: console.error('Insufficient permissions'); break; default: console.error(`Error ${code}: ${message}`); } }}Best Practices
-
Request Only Needed Fields: Optimize API calls
// ✅ Good - specific fieldsawait client.waba.getWabaAccount(['id', 'name', 'timezone_id']);// ❌ Wasteful - retrieves everythingawait client.waba.getWabaAccount([]); -
Store WABA ID Securely: Use environment variables
// ✅ Goodconst wabaId = process.env.WA_BUSINESS_ACCOUNT_ID;// ❌ Bad - hardcodedconst wabaId = '123456789'; -
Use Strong Verify Tokens: Generate random, secure tokens
import crypto from 'crypto';function generateVerifyToken(): string {return crypto.randomBytes(32).toString('hex');}const verifyToken = generateVerifyToken();// Store securely: process.env.WEBHOOK_VERIFY_TOKEN -
Validate Webhook Signatures: Verify authenticity
import crypto from 'crypto';function verifyWebhookSignature(payload: string,signature: string,appSecret: string): boolean {const expectedSignature = crypto.createHmac('sha256', appSecret).update(payload).digest('hex');return signature === `sha256=${expectedSignature}`;} -
Monitor Account Status: Check periodically
async function checkAccountHealth() {const account = await client.waba.getWabaAccount(['account_review_status','business_verification_status',]);if (account.account_review_status !== 'APPROVED') {await alertTeam('WABA account review status changed');}}// Check dailysetInterval(checkAccountHealth, 24 * 60 * 60 * 1000); -
Handle Timezone Correctly: Use WABA timezone for scheduling
import { DateTime } from 'luxon';const account = await client.waba.getWabaAccount(['timezone_id']);// Schedule message in account's timezoneconst accountTime = DateTime.now().setZone(account.timezone_id);console.log('Account local time:', accountTime.toISO());
Available WABA Fields
When calling getWabaAccount(), you can request these fields:
id: WABA identifiername: Business account nametimezone_id: Account timezone (e.g., ‘America/Los_Angeles’)message_template_namespace: Template namespace identifieraccount_review_status: Review status (APPROVED, PENDING, REJECTED)business_verification_status: Verification status (verified, unverified, pending)country: Country code (ISO 3166-1 alpha-2)currency: Currency code (ISO 4217)ownership_type: SELF or AGENCYprimary_business_location: Primary business country code
Account Review Statuses
- APPROVED: Account fully operational
- PENDING: Under review
- REJECTED: Review failed, action required
- DISABLED: Account disabled
const account = await client.waba.getWabaAccount(['account_review_status']);
switch (account.account_review_status) { case 'APPROVED': console.log('Account ready to use'); break; case 'PENDING': console.log('Account under review'); break; case 'REJECTED': console.error('Account rejected - review required'); break; case 'DISABLED': console.error('Account disabled - contact support'); break;}Webhook Event Types
When configuring webhooks, you can receive these event types:
messages: Incoming messages from usersmessage_status: Message delivery and read statusmessage_echoes: Messages sent by your businessmessage_template_status_update: Template approval status changesphone_number_quality_update: Phone number quality changesaccount_update: Account-level changesaccount_alerts: Important account notifications
Webhook Security
Verify Token
// Generate secure verify tokenconst VERIFY_TOKEN = crypto.randomBytes(32).toString('hex');
// Store in environment variables// WEBHOOK_VERIFY_TOKEN=abc123...
// Use in verification endpointapp.get('/webhook', (req, res) => { if (req.query['hub.verify_token'] === process.env.WEBHOOK_VERIFY_TOKEN) { res.send(req.query['hub.challenge']); } else { res.sendStatus(403); }});Signature Validation
app.post('/webhook', express.json(), (req, res) => { const signature = req.headers['x-hub-signature-256']; const payload = JSON.stringify(req.body);
if (!verifyWebhookSignature( payload, signature, process.env.APP_SECRET! )) { return res.sendStatus(403); }
// Process webhook res.sendStatus(200);});Related Documentation
- Webhooks Overview - Complete webhook guide
- Phone Numbers API - Manage phone numbers
- Templates API - Create message templates
- Messages API - Send messages
Source Code
View the source code on GitHub: WabaApi.ts