npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

whatsapp-client-sdk

v1.6.0

Published

TypeScript SDK for WhatsApp Business API - Simplify messaging integration

Readme

WhatsApp SDK

npm version TypeScript License: MIT Website

A powerful, easy-to-use TypeScript/JavaScript SDK for the WhatsApp Business API. Simplify your WhatsApp Business integration with a clean, intuitive API.

🌐 Visit wazap.dev for interactive documentation, live examples, and advanced tutorials.

✨ Features

  • 🚀 Easy to use - Simple, intuitive API design
  • 📝 Full TypeScript support - Complete type definitions included
  • 🔄 All message types - Text, images, videos, documents, interactive messages, templates, contacts, stickers
  • 📢 Broadcast messaging - Send bulk notifications with intelligent rate limiting and progress tracking
  • 💬 Typing indicators & read receipts - Enhanced user experience with real-time status updates
  • 🎣 Framework-agnostic webhooks - Zero boilerplate webhook handling that works with any framework
  • ❤️ Incoming reactions & replies - Full support for receiving and handling user reactions and message replies
  • 📊 Message status tracking - Track delivery status (sent, delivered, read, failed) with detailed error handling
  • 📁 Media management - Upload, download, and manage media files
  • 🛡️ Error handling - Comprehensive error types and handling
  • Modern - Built with latest TypeScript and modern JavaScript features
  • 🔒 Secure - Input validation and security best practices
  • 📖 Well documented - Comprehensive documentation and practical examples
  • 🌐 Production ready - Built-in retry logic, rate limiting, and enterprise features

📦 Installation

npm install whatsapp-client-sdk
yarn add whatsapp-client-sdk
pnpm add whatsapp-client-sdk

🚀 Quick Start

1. Initialize the Client

import { WhatsAppClient } from 'whatsapp-client-sdk';

const client = new WhatsAppClient({
  accessToken: 'your-access-token',        // Required: Get from Meta Developer Console
  phoneNumberId: 'your-phone-number-id',   // Required: Your WhatsApp Business phone number ID
  webhookVerifyToken: 'your-verify-token'  // Required: For receiving messages
});

2. Send Your First Message

// Send a simple text message
await client.sendText('+1234567890', 'Hello from WhatsApp Business SDK! 🚀');
console.log('Message sent successfully!');

3. Setup Webhook to Receive Messages

import express from 'express';

const app = express();
app.use(express.json());

// Create webhook processor (handles verification & message parsing automatically)
const webhookProcessor = client.createWebhookProcessor({
  onTextMessage: async (message) => {
    console.log(`Received: ${message.text} from ${message.from}`);
    
    // Auto-reply
    if (message.text.toLowerCase().includes('hello')) {
      await client.sendText(message.from, 'Hi! How can I help you?');
    }
  }
});

// Single endpoint handles both webhook verification and incoming messages
app.all('/webhook', async (req, res) => {
  const result = await webhookProcessor.processWebhook(req.body, req.query);
  res.status(result.status).send(result.response);
});

app.listen(3000, () => console.log('Webhook ready on port 3000'));

🔧 Environment Setup

For production apps, use environment variables. Create a .env file:

WHATSAPP_ACCESS_TOKEN=your_access_token_here
WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id_here
WHATSAPP_WEBHOOK_TOKEN=your_webhook_verify_token_here
WHATSAPP_BUSINESS_ID=your_business_id_here

Now update your client initialization from the Quick Start to use these variables:

const client = new WhatsAppClient({
-  accessToken: 'your-access-token',
-  phoneNumberId: 'your-phone-number-id', 
-  webhookVerifyToken: 'your-verify-token'
+  accessToken: process.env.WHATSAPP_ACCESS_TOKEN!,
+  phoneNumberId: process.env.WHATSAPP_PHONE_NUMBER_ID!,
+  webhookVerifyToken: process.env.WHATSAPP_WEBHOOK_TOKEN!,
+  businessId: process.env.WHATSAPP_BUSINESS_ID, // Optional
+  timeout: 30000,                              // Optional: Request timeout
+  apiVersion: 'v23.0'                          // Optional: API version
});

Test your connection:

const isConnected = await client.testConnection();
console.log('WhatsApp API connected:', isConnected);

📱 Sending Messages

Now you can start sending different types of messages:

Text Messages

// Simple text
await client.sendText('+1234567890', 'Hello World!');

// With URL preview
await client.sendText('+1234567890', 'Check out https://example.com', {
  previewUrl: true
});

// Reply to a message
await client.sendText('+1234567890', 'This is a reply', {
  replyToMessageId: 'message-id-to-reply-to'
});

Media Messages

// Send image
await client.sendImage('+1234567890', {
  link: 'https://example.com/image.jpg',
  caption: 'Beautiful image!'
});

// Send video
await client.sendVideo('+1234567890', {
  id: 'media-id', // Previously uploaded media ID
  caption: 'Amazing video!'
});

// Send audio
await client.sendAudio('+1234567890', {
  link: 'https://example.com/audio.mp3'
});

// Send document
await client.sendDocument('+1234567890', {
  link: 'https://example.com/document.pdf',
  filename: 'important-document.pdf',
  caption: 'Please review this document'
});

Interactive Messages

// Buttons
await client.sendButtons(
  '+1234567890',
  'What would you like to do?',
  [
    { id: 'view_catalog', title: '📋 View Catalog' },
    { id: 'contact_support', title: '💬 Contact Support' },
    { id: 'track_order', title: '📦 Track Order' }
  ],
  {
    header: { type: 'text', text: 'Main Menu' },
    footer: 'Choose an option to continue'
  }
);

// List Menu
await client.sendList(
  '+1234567890',
  'Browse our categories:',
  'View Categories',
  [
    {
      title: 'Electronics',
      rows: [
        { id: 'phones', title: 'Phones', description: 'Latest smartphones' },
        { id: 'laptops', title: 'Laptops', description: 'High-performance laptops' }
      ]
    },
    {
      title: 'Clothing',
      rows: [
        { id: 'mens', title: 'Men\'s Clothing', description: 'Fashion for men' },
        { id: 'womens', title: 'Women\'s Clothing', description: 'Fashion for women' }
      ]
    }
  ]
);

Template Messages

await client.sendTemplate(
  '+1234567890',
  'hello_world',              // Template name
  'en_US',                    // Language code
  [                           // Optional components
    {
      type: 'header',
      parameters: [
        {
          type: 'text',
          text: 'John Doe'
        }
      ]
    },
    {
      type: 'body',
      parameters: [
        {
          type: 'text',
          text: 'Your order #12345'
        }
      ]
    }
  ]
);

Location Messages

await client.sendLocation('+1234567890', 40.7128, -74.0060, {
  name: 'New York City',
  address: 'New York, NY, USA'
});

Contact Messages

await client.sendContacts('+1234567890', [
  {
    name: {
      formatted_name: 'John Smith',
      first_name: 'John',
      last_name: 'Smith'
    },
    phones: [
      {
        phone: '+1234567890',
        type: 'WORK'
      }
    ],
    emails: [
      {
        email: '[email protected]',
        type: 'WORK'
      }
    ],
    org: {
      company: 'Tech Company',
      department: 'Development',
      title: 'Developer'
    }
  }
]);

Sticker Messages

// Send sticker by media ID
await client.sendSticker('+1234567890', {
  id: 'media-id-of-sticker'
});

// Send sticker by URL
await client.sendSticker('+1234567890', {
  link: 'https://example.com/sticker.webp'
});

💬 Typing Indicators & Read Receipts

Enhance user experience with typing indicators and read receipts:

Typing Indicators

// Show typing indicator
await client.sendTypingIndicator('+1234567890');

// Show typing indicator with custom duration (max 25 seconds)
await client.sendTypingIndicatorWithDuration('+1234567890', 15000);

// Best practice: Show typing before sending response
await client.sendTypingIndicator('+1234567890');
await new Promise(resolve => setTimeout(resolve, 2000)); // Simulate processing
await client.sendText('+1234567890', 'Here is your response!');

Read Receipts

// Mark a message as read
await client.markMessageAsRead('wamid.HBgLMTY1MDM4Nzk0MzkVAgARGBJDQjZCMzlEQUE4OTJCMTE4RTUA');

// In webhook handler - auto-mark messages as read
const webhookProcessor = client.createWebhookProcessor({
  onTextMessage: async (message) => {
    // Mark message as read immediately
    await client.markMessageAsRead(message.id);
    
    // Show typing indicator while processing
    await client.sendTypingIndicator(message.from);
    
    // Process and respond
    const response = await processMessage(message.text);
    await client.sendText(message.from, response);
  }
});

Smart Conversation Flow

async function smartConversation(phoneNumber) {
  // 1. Show typing indicator
  await client.sendTypingIndicator(phoneNumber);
  
  // 2. Simulate processing time
  await new Promise(resolve => setTimeout(resolve, 2000));
  
  // 3. Send response
  await client.sendText(phoneNumber, '¡Hola! ¿Cómo puedo ayudarte?');
  
  // 4. Show typing for follow-up
  await client.sendTypingIndicatorWithDuration(phoneNumber, 5000);
  await new Promise(resolve => setTimeout(resolve, 3000));
  
  // 5. Send detailed information
  await client.sendText(phoneNumber, 'Aquí tienes las opciones disponibles...');
}

😍 Message Reactions

React to messages with emojis to enhance user engagement:

Basic Reactions

// Send reaction to a message
await client.sendReaction('+1234567890', 'wamid.HBgLMTY1MDM4Nzk0MzkVAgARGBJDQjZCMzlEQUE4OTJCMTE4RTUA', '👍');

// Remove a reaction
await client.removeReaction('+1234567890', 'wamid.HBgLMTY1MDM4Nzk0MzkVAgARGBJDQjZCMzlEQUE4OTJCMTE4RTUA');

Convenience Methods

Use predefined methods for common reactions:

// Common reactions
await client.reactWithLike('+1234567890', messageId);
await client.reactWithLove('+1234567890', messageId);
await client.reactWithLaugh('+1234567890', messageId);
await client.reactWithFire('+1234567890', messageId);
await client.reactWithCheck('+1234567890', messageId);

// More reactions available
await client.reactWithWow('+1234567890', messageId);
await client.reactWithSad('+1234567890', messageId);
await client.reactWithAngry('+1234567890', messageId);
await client.reactWithThumbsDown('+1234567890', messageId);
await client.reactWithHeartEyes('+1234567890', messageId);
await client.reactWithClap('+1234567890', messageId);
await client.reactWithCross('+1234567890', messageId);

Using Reaction Constants

import { REACTION_EMOJIS } from 'whatsapp-client-sdk';

// Use predefined emoji constants
await client.sendReaction('+1234567890', messageId, REACTION_EMOJIS.HEART);
await client.sendReaction('+1234567890', messageId, REACTION_EMOJIS.FIRE);
await client.sendReaction('+1234567890', messageId, REACTION_EMOJIS.CLAP);

// Available constants:
// LIKE, LOVE, LAUGH, WOW, SAD, ANGRY, THUMBS_UP, THUMBS_DOWN, 
// HEART, HEART_EYES, FIRE, CLAP, CHECK, CROSS

Receiving Reactions and Replies

Handle incoming reactions and replies from users:

const webhookProcessor = client.createWebhookProcessor({
  // Handle incoming reactions
  onReactionMessage: async (message) => {
    console.log(`User ${message.from} reacted with ${message.reaction.emoji}`);
    console.log(`Original message: ${message.reaction.message_id}`);

    // Thank them for the reaction
    await client.sendText(message.from, `Thanks for the ${message.reaction.emoji}!`);
  },

  // Handle replies (messages with context)
  onReplyMessage: async (message) => {
    console.log(`User replied to message: ${message.context.message_id}`);

    if (message.type === 'text') {
      console.log(`Reply text: ${message.text}`);
    }

    // Acknowledge the reply
    await client.replyToMessage(message.from, message.id, "Got your reply! 📨");
  },

  // Regular text messages (can also be replies)
  onTextMessage: async (message) => {
    if (message.context) {
      console.log('This text message is a reply!');
    }

    // Auto-react based on message content
    if (message.text.toLowerCase().includes('awesome')) {
      await client.reactWithFire(message.from, message.id);
    } else if (message.text.toLowerCase().includes('thanks')) {
      await client.reactWithHeart(message.from, message.id);
    } else {
      await client.reactWithLike(message.from, message.id);
    }
  }
});

Message Status Tracking

Track delivery status of your outgoing messages:

const webhookProcessor = client.createWebhookProcessor({
  // Handle message status updates (sent → delivered → read → failed)
  onMessageStatusUpdate: async (statusUpdate) => {
    console.log(`Message ${statusUpdate.id}: ${statusUpdate.status}`);
    console.log(`Recipient: ${statusUpdate.recipient_id}`);
    console.log(`Timestamp: ${new Date(parseInt(statusUpdate.timestamp) * 1000)}`);

    switch (statusUpdate.status) {
      case MessageStatus.SENT:
        console.log('✅ Message sent successfully');
        break;

      case MessageStatus.DELIVERED:
        console.log('📱 Message delivered to device');
        break;

      case MessageStatus.READ:
        console.log('👀 Message was read by recipient');
        // Maybe send a follow-up or mark as completed
        break;

      case MessageStatus.FAILED:
        console.log('❌ Message failed to send');
        if (statusUpdate.errors) {
          statusUpdate.errors.forEach(error => {
            console.log(`Error ${error.code}: ${error.title}`);

            // Handle specific errors
            if (error.code === 131047) {
              // 24-hour window expired - send template message
              await client.sendTemplate(statusUpdate.recipient_id, 'template_name');
            }
          });
        }
        break;
    }

    // Track pricing info for analytics
    if (statusUpdate.pricing) {
      console.log(`Cost: ${statusUpdate.pricing.category} (${statusUpdate.pricing.billable ? 'billable' : 'free'})`);
    }
  },

  // Regular message handling continues to work
  onTextMessage: async (message) => {
    const response = await client.sendText(message.from, 'Message received!');

    // The response will trigger status updates via webhook
    console.log(`Sent message ${response.messageId} - tracking status...`);
  }
});

Auto-React in Webhooks

const webhookProcessor = client.createWebhookProcessor({
  onTextMessage: async (message) => {
    // Auto-react based on message content
    if (message.text.toLowerCase().includes('awesome')) {
      await client.reactWithFire(message.from, message.id);
    } else if (message.text.toLowerCase().includes('thanks')) {
      await client.reactWithHeart(message.from, message.id);
    } else if (message.text.toLowerCase().includes('funny')) {
      await client.reactWithLaugh(message.from, message.id);
    } else {
      // Default reaction for any text message
      await client.reactWithLike(message.from, message.id);
    }
  }
});

📁 Media Management

// Upload media
const mediaResponse = await client.uploadMedia(fileBuffer, 'image');
console.log('Media ID:', mediaResponse.id);

// Get media info
const mediaInfo = await client.getMediaInfo('media-id');
console.log('Media URL:', mediaInfo.url);

// Download media
const buffer = await client.downloadMedia('media-id');
// Use the buffer as needed

📢 Broadcast Messages (Bulk Notifications)

Send messages to multiple recipients with intelligent rate limiting and progress tracking.

Simple Text Broadcast

const phoneNumbers = ['+1234567890', '+0987654321', '+1122334455'];

const result = await client.sendBroadcastText(
  phoneNumbers,
  'Important announcement for all customers! 🎉',
  {
    onProgress: (progress) => {
      console.log(`Progress: ${progress.sent}/${progress.total} (${progress.percentage.toFixed(1)}%)`);
      console.log(`ETA: ${Math.round(progress.estimatedTimeRemaining / 1000)}s`);
    }
  }
);

console.log(`✅ Sent to ${result.successful} recipients`);
console.log(`❌ Failed: ${result.failed}`);
console.log(`⏱️  Duration: ${(result.duration / 1000).toFixed(2)}s`);

Personalized Template Broadcast

const recipients = [
  {
    phoneNumber: '+1234567890',
    variables: { name: 'John', orderNumber: 'ORD-123' }
  },
  {
    phoneNumber: '+0987654321',
    variables: { name: 'Jane', orderNumber: 'ORD-456' }
  }
];

const result = await client.sendBulkTemplates(
  recipients,
  'order_confirmation',  // Your WhatsApp template name
  'en_US',
  {
    batchSize: 50,        // Messages per batch
    onProgress: (progress) => {
      console.log(`${progress.percentage.toFixed(1)}% complete`);
    },
    onMessageSent: (msgResult) => {
      if (!msgResult.success) {
        console.error(`Failed for ${msgResult.phoneNumber}: ${msgResult.error}`);
      }
    }
  }
);

console.log(`Broadcast complete: ${result.successful}/${result.total} successful`);

Advanced Broadcast Options

const result = await client.sendBroadcastText(
  phoneNumbers,
  'Your message here',
  {
    batchSize: 100,              // Send 100 messages per batch (default: 50)
    delayBetweenBatches: 2000,   // 2 second delay between batches
    stopOnError: false,          // Continue even if some fail (default: false)
    onProgress: (progress) => {
      // Real-time progress updates
      console.log(`Sent: ${progress.sent}, Failed: ${progress.failed}`);
    },
    onMessageSent: (result) => {
      // Individual message result callback
      if (result.success) {
        console.log(`✅ ${result.phoneNumber}: ${result.messageId}`);
      } else {
        console.error(`❌ ${result.phoneNumber}: ${result.error}`);
      }
    }
  }
);

Broadcast Control

// Check if broadcast is running
const isRunning = client.isBroadcastRunning();

// Abort ongoing broadcast
client.abortBroadcast();

Rate Limiting

The SDK automatically handles WhatsApp API rate limits:

  • 80 messages per second maximum
  • 1000 messages per minute (rolling window)
  • Intelligent batching to optimize throughput
  • Automatic delays between batches

See examples/broadcast-messages.js for more examples.

🔌 Advanced Webhook Features

Multiple Message Types Handler

const webhookProcessor = client.createWebhookProcessor({
  // Text messages
  onTextMessage: async (message) => {
    if (message.text.toLowerCase() === 'menu') {
      await client.sendButtons(message.from, 'Choose an option:', [
        { id: 'catalog', title: '📋 View Catalog' },
        { id: 'support', title: '💬 Contact Support' }
      ]);
    }
  },

  // Handle button clicks
  onButtonClick: async (message) => {
    const buttonId = message.interactive.button_id;
    switch (buttonId) {
      case 'catalog':
        await client.sendText(message.from, 'Here\'s our catalog...');
        break;
      case 'support':
        await client.sendText(message.from, 'Connecting you to support...');
        break;
    }
  },

  // Handle media messages (images, videos, documents)
  onImageMessage: async (message) => {
    // Download and process the image
    const buffer = await client.downloadMedia(message.media.id);
    await client.sendText(message.from, 'Thanks for the image!');
  },

  // Error handling
  onError: async (error, message) => {
    console.error('Webhook error:', error.message);
  }
});

Framework Compatibility

Works with any Node.js framework:

// Express.js / Fastify / Next.js / Nest.js / AWS Lambda
app.all('/webhook', async (req, res) => {
  const result = await webhookProcessor.processWebhook(req.body, req.query);
  res.status(result.status).send(result.response);
});

🎯 Advanced Usage

Error Handling

import { 
  WhatsAppApiError, 
  RateLimitError, 
  MessageValidationError 
} from 'whatsapp-client-sdk';

try {
  await client.sendText('+invalid', 'This will fail');
} catch (error) {
  if (error instanceof MessageValidationError) {
    console.log('Validation error:', error.message);
  } else if (error instanceof RateLimitError) {
    console.log('Rate limited, retry after:', error.retryAfter);
  } else if (error instanceof WhatsAppApiError) {
    console.log('WhatsApp API error:', error.details);
  }
}

Custom Configuration

const client = new WhatsAppClient({
  accessToken: process.env.WHATSAPP_ACCESS_TOKEN!,
  phoneNumberId: process.env.WHATSAPP_PHONE_NUMBER_ID!,
  timeout: 60000, // 60 second timeout
});

// Test connection
const isConnected = await client.testConnection();
console.log('Connected:', isConnected);

🎯 Next Steps

Now that you have the basics working, explore these advanced features:

  1. 📱 Send Media: Upload and send images, videos, documents
  2. 🔘 Interactive Messages: Use buttons and lists for better UX
  3. 📞 Business Features: Send contacts, locations, and stickers
  4. 🏗️ Scale Up: Add error handling, logging, and production configs
  5. 🌐 Deploy: Use Next.js, Nest.js, or any framework you prefer

📚 API Reference

WhatsAppClient Methods

| Method | Description | Returns | |--------|-------------|---------| | `sendText(to, text, options?)` | Send text message | `Promise` | | `sendImage(to, image, options?)` | Send image message | `Promise` | | `sendVideo(to, video, options?)` | Send video message | `Promise` | | `sendAudio(to, audio, options?)` | Send audio message | `Promise` | | `sendDocument(to, document, options?)` | Send document message | `Promise` | | `sendButtons(to, text, buttons, options?)` | Send interactive buttons | `Promise` | | `sendList(to, text, buttonText, sections, options?)` | Send interactive list | `Promise` | | `sendTemplate(to, name, language, components?)` | Send template message | `Promise` | | `sendLocation(to, lat, lng, options?)` | Send location message | `Promise` | | `sendContacts(to, contacts, options?)` | Send contact message | `Promise` | | `sendSticker(to, sticker, options?)` | Send sticker message | `Promise` | | `sendTypingIndicator(to)` | Show typing indicator | `Promise` | | `sendTypingIndicatorWithDuration(to, duration?)` | Show typing indicator with custom duration | `Promise` | | `markMessageAsRead(messageId)` | Mark message as read | `Promise` | | `sendReaction(to, messageId, emoji)` | Send reaction to message | `Promise` | | `reactWithLike(to, messageId)` | React with like emoji | `Promise` | | `reactWithLove(to, messageId)` | React with love emoji | `Promise` | | `reactWithLaugh(to, messageId)` | React with laugh emoji | `Promise` | | `reactWithFire(to, messageId)` | React with fire emoji | `Promise` | | `reactWithCheck(to, messageId)` | React with check emoji | `Promise` | | `removeReaction(to, messageId)` | Remove reaction from message | `Promise` | | `sendBroadcast(phoneNumbers, message, options?)` | Send same message to multiple recipients | `Promise` | | `sendBroadcastText(phoneNumbers, text, options?)` | Send text broadcast to multiple recipients | `Promise` | | `sendBulkTemplates(recipients, name, language, options?)` | Send personalized templates to multiple recipients | `Promise` | | `abortBroadcast()` | Abort ongoing broadcast operation | `void` | | `isBroadcastRunning()` | Check if broadcast is currently running | `boolean` | | `uploadMedia(file, type)` | Upload media file | `Promise` | | `downloadMedia(mediaId)` | Download media file | `Promise` | | `getMediaInfo(mediaId)` | Get media information | `Promise` | | `verifyWebhook(mode, token, challenge)` | Verify webhook | `number \| null` | | `parseWebhook(payload)` | Parse webhook payload | `ProcessedIncomingMessage[]` | | `createWebhookProcessor(handlers)` | Create framework-agnostic webhook processor | `WebhookProcessor` | | `testConnection()` | Test API connection | `Promise` |

Webhook Handlers

| Handler | Description | Parameters | |---------|-------------|------------| | `onTextMessage` | Handle incoming text messages | `(message: ProcessedIncomingMessage & { text: string })` | | `onImageMessage` | Handle incoming image messages | `(message: ProcessedIncomingMessage & { media: MediaInfo })` | | `onVideoMessage` | Handle incoming video messages | `(message: ProcessedIncomingMessage & { media: MediaInfo })` | | `onAudioMessage` | Handle incoming audio messages | `(message: ProcessedIncomingMessage & { media: MediaInfo })` | | `onDocumentMessage` | Handle incoming document messages | `(message: ProcessedIncomingMessage & { media: MediaInfo })` | | `onLocationMessage` | Handle incoming location messages | `(message: ProcessedIncomingMessage & { location: LocationInfo })` | | `onStickerMessage` | Handle incoming sticker messages | `(message: ProcessedIncomingMessage & { media: MediaInfo })` | | `onContactMessage` | Handle incoming contact messages | `(message: ProcessedIncomingMessage)` | | `onButtonClick` | Handle button interactions | `(message: ProcessedIncomingMessage & { interactive: InteractiveInfo })` | | `onListSelect` | Handle list selections | `(message: ProcessedIncomingMessage & { interactive: InteractiveInfo })` | | `onReactionMessage` | NEW: Handle incoming reactions | `(message: ProcessedIncomingMessage & { reaction: { message_id: string, emoji: string } })` | | `onReplyMessage` | NEW: Handle reply messages | `(message: ProcessedIncomingMessage & { context: { message_id: string } })` | | `onMessageStatusUpdate` | NEW: Handle message delivery status | `(statusUpdate: MessageStatusUpdate)` | | `onUnknownMessage` | Handle unknown message types | `(message: ProcessedIncomingMessage)` | | `onError` | Handle errors | `(error: Error, message?: ProcessedIncomingMessage)` |

🛠️ Development

# Clone the repository
git clone https://github.com/joseandrescolmenares/whatsapp-sdk.git
# or visit https://www.wazap.dev/ for documentation

# Install dependencies
npm install

# Build the project
npm run build

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Lint code
npm run lint

# Format code
npm run format

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create your feature branch (`git checkout -b feature/amazing-feature`)
  3. Commit your changes (`git commit -m 'Add some amazing feature'`)
  4. Push to the branch (`git push origin feature/amazing-feature`)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

📞 Support


Made with ❤️ for the developer community | Visit wazap.dev