Block Users API
Block or unblock WhatsApp users to manage unwanted interactions, with support for list management and pagination.
Official Documentation: WhatsApp Block Users API
Overview
The Block Users API enables user blocking management:
- Block Users: Prevent specific users from contacting your business
- Unblock Users: Restore contact capabilities for previously blocked users
- List Blocked Users: Retrieve all currently blocked users with pagination
- Batch Operations: Block or unblock multiple users at once
Endpoints
POST /{PHONE_NUMBER_ID}/block_usersDELETE /{PHONE_NUMBER_ID}/block_usersGET /{PHONE_NUMBER_ID}/block_users?limit&after&beforeImportant 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,});
// Block a userawait client.blockUsers.block(['15551234567']);
// Block multiple usersawait client.blockUsers.block([ '15551234567', '15559876543',]);
// List blocked usersconst blocked = await client.blockUsers.listBlockedUsers({ limit: 10 });
// Unblock a userawait client.blockUsers.unblock(['15551234567']);Block Users
Prevent specific users from contacting your business.
Block Single User
await client.blockUsers.block(['15551234567']);
console.log('User blocked successfully');Block Multiple Users
const usersToBlock = [ '15551234567', '15559876543', '15555555555',];
await client.blockUsers.block(usersToBlock);
console.log(`Blocked ${usersToBlock.length} users`);Block with Validation
function isValidPhoneNumber(phone: string): boolean { // E.164 format: 1-15 digits return /^\d{1,15}$/.test(phone);}
async function blockUser(phoneNumber: string) { if (!isValidPhoneNumber(phoneNumber)) { throw new Error('Invalid phone number format'); }
try { await client.blockUsers.block([phoneNumber]); console.log(`User ${phoneNumber} blocked`); } catch (error) { console.error('Failed to block user:', error.message); }}Block with Reason Logging
interface BlockRecord { phoneNumber: string; reason: string; blockedAt: Date; blockedBy: string;}
async function blockWithReason( phoneNumber: string, reason: string, adminId: string) { // Block the user await client.blockUsers.block([phoneNumber]);
// Log the block action const record: BlockRecord = { phoneNumber, reason, blockedAt: new Date(), blockedBy: adminId, };
await database.blockRecords.insert(record);
console.log(`User ${phoneNumber} blocked: ${reason}`);}
// Usageawait blockWithReason('15551234567', 'Spam messages', 'admin-123');Unblock Users
Restore contact capabilities for previously blocked users.
Unblock Single User
await client.blockUsers.unblock(['15551234567']);
console.log('User unblocked successfully');Unblock Multiple Users
const usersToUnblock = [ '15551234567', '15559876543',];
await client.blockUsers.unblock(usersToUnblock);
console.log(`Unblocked ${usersToUnblock.length} users`);Unblock with Logging
async function unblockWithLog(phoneNumber: string, adminId: string) { // Unblock the user await client.blockUsers.unblock([phoneNumber]);
// Log the unblock action await database.blockRecords.update({ phoneNumber, unblockedAt: new Date(), unblockedBy: adminId, });
console.log(`User ${phoneNumber} unblocked by ${adminId}`);}List Blocked Users
Retrieve all currently blocked users with pagination support.
Get First Page
const blockedUsers = await client.blockUsers.listBlockedUsers({ limit: 20,});
console.log('Blocked users:', blockedUsers.data);console.log('Has more:', blockedUsers.paging?.next);Paginate Through All Blocked Users
async function getAllBlockedUsers(): Promise<string[]> { const allUsers: string[] = []; let after: string | undefined;
do { const response = await client.blockUsers.listBlockedUsers({ limit: 100, after, });
allUsers.push(...response.data.map(u => u.phone_number));
after = response.paging?.cursors?.after; } while (after);
return allUsers;}
// Usageconst allBlocked = await getAllBlockedUsers();console.log(`Total blocked users: ${allBlocked.length}`);List with Filtering
async function findBlockedUser(searchNumber: string) { let after: string | undefined;
do { const response = await client.blockUsers.listBlockedUsers({ limit: 100, after, });
const found = response.data.find( u => u.phone_number === searchNumber );
if (found) { return found; }
after = response.paging?.cursors?.after; } while (after);
return null;}Advanced Use Cases
Automatic Spam Blocking
import { WebhookProcessor } from 'meta-cloud-api/webhook';
const webhook = new WebhookProcessor({ verifyToken: process.env.WEBHOOK_VERIFY_TOKEN!,});
webhook.on('message', async (message, metadata) => { // Check for spam indicators const isSpam = detectSpam(message.text?.body);
if (isSpam) { // Block the user await client.blockUsers.block([message.from]);
console.log(`Blocked spam user: ${message.from}`);
// Log for review await logSpamBlock(message.from, message.text?.body); }});
function detectSpam(text?: string): boolean { if (!text) return false;
const spamKeywords = ['casino', 'lottery', 'prize', 'winner']; const lowerText = text.toLowerCase();
return spamKeywords.some(keyword => lowerText.includes(keyword));}Rate Limit Blocking
interface MessageCounter { [phoneNumber: string]: { count: number; firstMessageAt: Date; };}
const messageCounters: MessageCounter = {};
async function checkRateLimit(phoneNumber: string) { const now = new Date(); const counter = messageCounters[phoneNumber];
if (!counter) { messageCounters[phoneNumber] = { count: 1, firstMessageAt: now, }; return false; // Not rate limited }
// Reset if outside time window (e.g., 1 minute) const timeDiff = now.getTime() - counter.firstMessageAt.getTime(); if (timeDiff > 60000) { messageCounters[phoneNumber] = { count: 1, firstMessageAt: now, }; return false; }
// Increment counter counter.count++;
// Block if exceeds threshold (e.g., 10 messages per minute) if (counter.count > 10) { await client.blockUsers.block([phoneNumber]); console.log(`Rate limit exceeded: ${phoneNumber}`); return true; }
return false;}Temporary Block System
interface TemporaryBlock { phoneNumber: string; blockedUntil: Date;}
const tempBlocks = new Map<string, TemporaryBlock>();
async function temporaryBlock( phoneNumber: string, durationMinutes: number) { // Block the user await client.blockUsers.block([phoneNumber]);
// Schedule unblock const blockedUntil = new Date(Date.now() + durationMinutes * 60000); tempBlocks.set(phoneNumber, { phoneNumber, blockedUntil });
// Set timeout for automatic unblock setTimeout(async () => { await client.blockUsers.unblock([phoneNumber]); tempBlocks.delete(phoneNumber); console.log(`Temporary block expired: ${phoneNumber}`); }, durationMinutes * 60000);
console.log(`Temporarily blocked ${phoneNumber} for ${durationMinutes} minutes`);}
// Usage: 30-minute timeoutawait temporaryBlock('15551234567', 30);Block Management Dashboard
interface BlockSummary { totalBlocked: number; blockedToday: number; recentBlocks: Array<{ phoneNumber: string; blockedAt: Date; reason: string; }>;}
async function getBlockSummary(): Promise<BlockSummary> { // Get all blocked users const allBlocked = await getAllBlockedUsers();
// Get block records from database const records = await database.blockRecords.find({ blockedAt: { $exists: true }, });
// Calculate today's blocks const today = new Date(); today.setHours(0, 0, 0, 0);
const blockedToday = records.filter( r => r.blockedAt >= today ).length;
// Get recent blocks const recentBlocks = records .sort((a, b) => b.blockedAt.getTime() - a.blockedAt.getTime()) .slice(0, 10);
return { totalBlocked: allBlocked.length, blockedToday, recentBlocks, };}Response Formats
Block Response
{ success: true}Unblock Response
{ success: true}List Blocked Users Response
{ data: [ { phone_number: '15551234567', blocked_at: '2024-01-15T10:30:00Z' }, { phone_number: '15559876543', blocked_at: '2024-01-14T15:45:00Z' } ], paging: { cursors: { before: 'CURSOR_STRING', after: 'CURSOR_STRING' }, next: 'https://graph.facebook.com/...' }}Error Handling
try { await client.blockUsers.block(['15551234567']);} catch (error) { if (error.response) { const { code, message } = error.response.data.error;
switch (code) { case 131026: console.error('Cannot block: user has not messaged in 24 hours'); break; case 100: console.error('Invalid phone number format'); break; default: console.error(`Error ${code}: ${message}`); } }}Best Practices
-
Validate Before Blocking: Ensure proper phone number format
function validateBeforeBlock(phoneNumbers: string[]): string[] {return phoneNumbers.filter(num => /^\d{1,15}$/.test(num));}const validNumbers = validateBeforeBlock(['15551234567', 'invalid']);await client.blockUsers.block(validNumbers); -
Log Block Actions: Maintain audit trail
async function blockWithAudit(phoneNumber: string, reason: string) {await client.blockUsers.block([phoneNumber]);await auditLog.record({action: 'block_user',phoneNumber,reason,timestamp: new Date(),});} -
Provide Unblock Mechanism: Allow reversing mistakes
// Admin interface for unblockingapp.post('/admin/unblock', async (req, res) => {const { phoneNumber, adminId } = req.body;await client.blockUsers.unblock([phoneNumber]);await auditLog.record({action: 'unblock_user',phoneNumber,adminId,timestamp: new Date(),});res.json({ success: true });}); -
Handle 24-Hour Limitation: Check timing before blocking
async function canBlockUser(phoneNumber: string): Promise<boolean> {// Check if user messaged within 24 hoursconst lastMessage = await database.messages.findOne({from: phoneNumber,timestamp: { $gte: new Date(Date.now() - 24 * 60 * 60 * 1000) },});return !!lastMessage;}if (await canBlockUser('15551234567')) {await client.blockUsers.block(['15551234567']);} else {console.log('Cannot block: 24-hour window expired');} -
Batch Operations: Process multiple users efficiently
// Instead of blocking one by onefor (const number of numbers) {await client.blockUsers.block([number]); // ❌ Inefficient}// Block all at onceawait client.blockUsers.block(numbers); // ✅ Efficient -
Regular Cleanup: Review blocked users periodically
async function reviewBlockedUsers() {const allBlocked = await getAllBlockedUsers();for (const phoneNumber of allBlocked) {const record = await database.blockRecords.findOne({ phoneNumber });// Unblock if blocked for more than 30 daysif (record && isOlderThan(record.blockedAt, 30)) {await client.blockUsers.unblock([phoneNumber]);console.log(`Auto-unblocked: ${phoneNumber}`);}}}
Phone Number Format
Use E.164 format without the + symbol:
// ✅ Correct format'15551234567' // US number'442071234567' // UK number'919876543210' // India number
// ❌ Incorrect format'+15551234567' // Don't include +'1-555-123-4567' // Don't use hyphens'(555) 123-4567' // Don't use formattingRelated Documentation
- Messages API - Handle incoming messages
- Webhooks - Receive message notifications
- Phone Numbers API - Manage phone numbers
- Moderation Guide - Content moderation strategies
Source Code
View the source code on GitHub: BlockUsersApi.ts