Broadcast Messages
The Broadcast Messages feature enables you to send messages to multiple recipients efficiently while automatically handling WhatsApp API rate limits and providing real-time progress tracking.
Overview
Send the same message or personalized template messages to thousands of recipients with:
Intelligent Rate Limiting : Automatic compliance with WhatsApp’s 80 msg/sec and 1000 msg/min limits
Progress Tracking : Real-time updates on send status, success rate, and estimated completion time
Error Handling : Individual message failures don’t stop the entire broadcast
Batch Processing : Efficient chunked processing for optimal throughput
Abort Control : Stop broadcasts mid-process when needed
Use Cases
Order confirmations
Shipping updates
Delivery notifications
Cart abandonment reminders
Medical appointment confirmations
Service reminders
Event notifications
Promotional messages (using approved templates)
Product launches
Special offers
System status updates
Emergency alerts
Important announcements
Survey requests
Feedback collection
Service updates
Quick Start
Simple Text Broadcast
import { WhatsAppClient } from 'whatsapp-client-sdk' ;
const client = new WhatsAppClient ({
accessToken: 'your-token' ,
phoneNumberId: 'your-phone-id'
});
const phoneNumbers = [
'+1234567890' ,
'+0987654321' ,
'+1122334455'
];
const result = await client . sendBroadcastText (
phoneNumbers ,
'Hello! This is a broadcast message.'
);
console . log ( `Sent: ${ result . successful } / ${ result . total } ` );
console . log ( `Failed: ${ result . failed } ` );
console . log ( `Duration: ${ result . duration } ms` );
Personalized Template Broadcast
const recipients = [
{
phoneNumber: '+1234567890' ,
variables: {
name: 'John' ,
order_id: '#12345' ,
amount: '$99.99'
}
},
{
phoneNumber: '+0987654321' ,
variables: {
name: 'Jane' ,
order_id: '#12346' ,
amount: '$149.99'
}
}
];
const result = await client . sendBulkTemplates (
recipients ,
'order_confirmation' , // Your approved template name
'en_US'
);
Advanced Usage
Progress Tracking
Monitor your broadcast in real-time:
const result = await client . sendBroadcastText (
phoneNumbers ,
'Your message here' ,
{
onProgress : ( progress ) => {
console . log ( `Progress: ${ progress . percentage . toFixed ( 1 ) } %` );
console . log ( `Sent: ${ progress . sent } / ${ progress . total } ` );
console . log ( `Failed: ${ progress . failed } ` );
console . log ( `Pending: ${ progress . pending } ` );
console . log ( `ETA: ${ Math . round ( progress . estimatedTimeRemaining / 1000 ) } s` );
},
onMessageSent : ( result ) => {
if ( result . success ) {
console . log ( `✓ Sent to ${ result . phoneNumber } ` );
} else {
console . log ( `✗ Failed to ${ result . phoneNumber } : ${ result . error } ` );
}
}
}
);
Custom Batch Configuration
const result = await client . sendBroadcastText (
phoneNumbers ,
'Your message' ,
{
batchSize: 100 , // Messages per batch (default: 50)
delayBetweenBatches: 5000 , // Delay in ms (default: auto-calculated)
stopOnError: false // Continue on errors (default: false)
}
);
Abort Broadcast
// Start broadcast
const broadcastPromise = client . sendBroadcastText (
largePhoneNumberList ,
'Message'
);
// Abort after 5 seconds
setTimeout (() => {
if ( client . isBroadcastRunning ()) {
client . abortBroadcast ();
console . log ( 'Broadcast aborted!' );
}
}, 5000 );
const result = await broadcastPromise ;
console . log ( `Sent before abort: ${ result . successful } ` );
Rate Limiting
The SDK automatically handles WhatsApp Business API rate limits:
Limit Value SDK Behavior Messages per second 80 Throttles to ~77 msg/sec (safety margin) Messages per minute 1000 Batches with calculated delays Concurrent requests No official limit Limits to 10 concurrent within batch
How It Works
Chunking : Large batches are split into chunks of 10 messages
Throttling : Each message takes minimum 13ms (~77 msg/sec)
Batch Delays : Automatic delays between batches to respect per-minute limits
Sequential Processing : Chunks processed sequentially to prevent spikes
API Reference
sendBroadcast(phoneNumbers, message, options?)
Send the same message to multiple recipients.
Parameters:
phoneNumbers (string[]): Array of recipient phone numbers
message (OutgoingMessage): Message object with type and content
options (BroadcastOptions): Optional configuration
Returns: Promise<BroadcastResult>
sendBroadcastText(phoneNumbers, text, options?)
Shorthand for sending text broadcasts.
Parameters:
phoneNumbers (string[]): Array of recipient phone numbers
text (string): Message text
options (BroadcastOptions): Optional configuration
Returns: Promise<BroadcastResult>
sendBulkTemplates(recipients, templateName, languageCode, options?)
Send personalized template messages to multiple recipients.
Parameters:
recipients (BroadcastRecipient[]): Recipients with variables
templateName (string): Approved template name
languageCode (string): Template language (e.g., ‘en_US’)
options (BroadcastOptions): Optional configuration
Returns: Promise<BroadcastResult>
abortBroadcast()
Stop the currently running broadcast.
Returns: void
isBroadcastRunning()
Check if a broadcast is currently in progress.
Returns: boolean
Types
BroadcastOptions
interface BroadcastOptions {
batchSize ?: number ; // Messages per batch (default: 50)
delayBetweenBatches ?: number ; // Delay in ms (default: auto)
onProgress ?: ( progress : BroadcastProgress ) => void ;
onMessageSent ?: ( result : MessageSendResult ) => void ;
stopOnError ?: boolean ; // Stop on first error (default: false)
}
BroadcastResult
interface BroadcastResult {
broadcastId : string ; // Unique broadcast identifier
total : number ; // Total messages attempted
successful : number ; // Successfully sent
failed : number ; // Failed to send
results : MessageSendResult []; // Individual results
duration : number ; // Total duration in ms
startTime : number ; // Start timestamp
endTime : number ; // End timestamp
}
BroadcastProgress
interface BroadcastProgress {
total : number ; // Total messages
sent : number ; // Messages sent (successful + failed)
failed : number ; // Failed messages
pending : number ; // Remaining messages
percentage : number ; // Completion percentage (0-100)
startTime : number ; // Start timestamp
currentTime : number ; // Current timestamp
estimatedTimeRemaining ?: number ; // Estimated ms remaining
}
MessageSendResult
interface MessageSendResult {
phoneNumber : string ;
success : boolean ;
messageId ?: string ; // WhatsApp message ID if successful
error ?: string ; // Error message if failed
timestamp : number ; // Send attempt timestamp
}
BroadcastRecipient
interface BroadcastRecipient {
phoneNumber : string ;
variables ?: Record < string , string >; // Template variable substitutions
}
Best Practices
1. Use Templates for Marketing
Text messages only work within the 24-hour conversation window. For marketing or notifications outside this window, use approved message templates.
// Using templates
await client . sendBulkTemplates ( recipients , 'promo_template' , 'en_US' );
2. Handle Individual Failures
const result = await client . sendBroadcastText ( numbers , text );
// Check failed messages
const failedNumbers = result . results
. filter ( r => ! r . success )
. map ( r => ({ phone: r . phoneNumber , error: r . error }));
if ( failedNumbers . length > 0 ) {
console . log ( 'Failed messages:' , failedNumbers );
// Implement retry logic or alert system
}
3. Respect User Preferences
// Filter opt-out users before sending
const activeUsers = await getActiveSubscribers (); // Your DB logic
const phoneNumbers = activeUsers . map ( u => u . phoneNumber );
await client . sendBroadcastText ( phoneNumbers , message );
4. Optimize Batch Size
// For smaller lists (< 500), use larger batches
await client . sendBroadcastText ( numbers , text , {
batchSize: 100
});
// For very large lists (10k+), use default or smaller batches
await client . sendBroadcastText ( numbers , text , {
batchSize: 50 // More frequent progress updates
});
5. Monitor and Log
const result = await client . sendBroadcastText ( numbers , text , {
onProgress : ( progress ) => {
// Log to your monitoring system
logger . info ( 'Broadcast progress' , {
broadcastId: result . broadcastId ,
progress: progress . percentage ,
failed: progress . failed
});
}
});
// Store results for analysis
await db . saveBroadcastResults ( result );
Examples
Example 1: Simple Broadcast with Progress Tracking
async function sendAnnouncementBroadcast () {
const phoneNumbers = [
'+1234567890' ,
'+0987654321' ,
'+1122334455' ,
// Add more recipients...
];
const message = 'Hello! This is an important announcement for all our customers. 🎉' ;
try {
const result = await client . sendBroadcastText ( phoneNumbers , message , {
batchSize: 50 ,
onProgress : ( progress ) => {
console . log ( `📊 Progress: ${ progress . sent } / ${ progress . total } ( ${ progress . percentage . toFixed ( 1 ) } %)` );
console . log ( ` ✅ Successful: ${ progress . sent - progress . failed } ` );
console . log ( ` ❌ Failed: ${ progress . failed } ` );
if ( progress . estimatedTimeRemaining ) {
console . log ( ` ⏱️ ETA: ${ Math . round ( progress . estimatedTimeRemaining / 1000 ) } s \n ` );
}
},
});
console . log ( ' \n ✅ Broadcast completed!' );
console . log ( ` Total: ${ result . total } ` );
console . log ( ` Successful: ${ result . successful } ` );
console . log ( ` Failed: ${ result . failed } ` );
console . log ( ` Duration: ${ ( result . duration / 1000 ). toFixed ( 2 ) } s` );
// Handle failed messages
if ( result . failed > 0 ) {
const failedNumbers = result . results
. filter ( r => ! r . success )
. map ( r => ({ phone: r . phoneNumber , error: r . error }));
console . log ( ' \n ❌ Failed recipients:' , failedNumbers );
// Implement retry logic here
}
} catch ( error ) {
console . error ( '❌ Broadcast failed:' , error . message );
}
}
Example 2: Detailed Message Tracking
async function sendPromotionWithTracking () {
const phoneNumbers = [ '+1234567890' , '+0987654321' , '+1122334455' ];
const message = '🎁 Special offer! Use code WELCOME10 for 10% off.' ;
const successfulRecipients = [];
const failedRecipients = [];
const result = await client . sendBroadcastText ( phoneNumbers , message , {
onMessageSent : ( msgResult ) => {
if ( msgResult . success ) {
successfulRecipients . push ( msgResult . phoneNumber );
console . log ( `✅ Sent to ${ msgResult . phoneNumber } (ID: ${ msgResult . messageId } )` );
} else {
failedRecipients . push ( msgResult );
console . log ( `❌ Failed: ${ msgResult . phoneNumber } - ${ msgResult . error } ` );
}
},
onProgress : ( progress ) => {
// Visual progress bar
const bar = '█' . repeat ( Math . floor ( progress . percentage / 5 )) +
'░' . repeat ( 20 - Math . floor ( progress . percentage / 5 ));
console . log ( `[ ${ bar } ] ${ progress . percentage . toFixed ( 1 ) } %` );
},
});
console . log ( ' \n 📊 Final Report:' );
console . log ( ` Broadcast ID: ${ result . broadcastId } ` );
console . log ( ` Success Rate: ${ (( result . successful / result . total ) * 100 ). toFixed ( 1 ) } %` );
console . log ( ` Duration: ${ ( result . duration / 1000 ). toFixed ( 2 ) } s` );
}
Example 3: Personalized Template Broadcast
async function sendOrderConfirmations () {
// Each recipient with personalized data
const recipients = [
{
phoneNumber: '+1234567890' ,
variables: {
name: 'John Doe' ,
orderNumber: 'ORD-12345' ,
deliveryDate: 'December 25, 2024' ,
},
},
{
phoneNumber: '+0987654321' ,
variables: {
name: 'Jane Smith' ,
orderNumber: 'ORD-12346' ,
deliveryDate: 'December 26, 2024' ,
},
},
];
try {
const result = await client . sendBulkTemplates (
recipients ,
'order_confirmation' , // Your pre-approved template name
'en_US' ,
{
batchSize: 30 ,
onProgress : ( progress ) => {
console . log ( `📤 Sending: ${ progress . sent } / ${ progress . total } ` );
},
onMessageSent : ( msgResult ) => {
if ( msgResult . success ) {
console . log ( `✅ Template sent to ${ msgResult . phoneNumber } ` );
} else {
console . log ( `❌ Failed: ${ msgResult . phoneNumber } - ${ msgResult . error } ` );
}
},
}
);
console . log ( ' \n ✅ Template broadcast completed!' );
console . log ( ` Success: ${ result . successful } / ${ result . total } ` );
console . log ( ` Avg time per message: ${ ( result . duration / result . total ). toFixed ( 0 ) } ms` );
} catch ( error ) {
console . error ( '❌ Template broadcast failed:' , error . message );
}
}
Template Setup Required : Before using template broadcasts, ensure your template is approved in WhatsApp Business Manager. Template approval can take 1-48 hours.
Limitations
Important Limitations
24-Hour Window : Text broadcasts require an active conversation window (user messaged you in last 24h). Use templates otherwise.
Template Approval : Template messages must be pre-approved by Meta. This can take 1-48 hours.
Rate Limits : While the SDK handles rate limiting, sending to 100k+ recipients will take considerable time (~20+ minutes).
No Retry Logic : Currently, failed messages are not automatically retried. Implement your own retry logic if needed.
Single Broadcast : Only one broadcast can run at a time per client instance.
Troubleshooting
Messages failing with rate limit errors
Solution : The SDK should handle this automatically. If you’re still seeing errors:
Reduce batchSize option
Increase delayBetweenBatches
Ensure you’re not running multiple broadcasts simultaneously
All messages failing immediately
Broadcast slower than expected
This is normal : For 10,000 recipients at 80 msg/sec, expect ~2 minutes minimum. The SDK prioritizes delivery success over speed.
Migration Guide
If you’re upgrading from a previous version without broadcast support:
// OLD: Sending one by one
for ( const phone of phoneNumbers ) {
await client . sendText ( phone , message );
}
// NEW: Broadcast
await client . sendBroadcastText ( phoneNumbers , message );
Next Steps
Version
Broadcast feature added in version 1.6.0