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 🙏

© 2026 – Pkg Stats / Ryan Hefner

easy-connect-official-wpp-rc

v1.0.13

Published

Official WhatsApp Cloud API client for Node.js with Redis webhook distribution. Build scalable WhatsApp integrations with event listeners and distributed message handling.

Readme

easy-connect-official-wpp-rc

Official WhatsApp Cloud API client for Node.js with Redis webhook distribution. Build scalable, event-driven WhatsApp integrations with automatic Redis connection management.

npm version TypeScript Node.js

Features

Official WhatsApp Cloud API v25.0 — Latest WhatsApp Graph API
🚀 Automatic Initialization — Redis connects automatically on first listener
🎧 Event-Driven Architecture — Familiar callback pattern for all events
📦 Distributed Ready — Built-in Redis pub/sub for multiple client instances
📨 Full Message Support — Text, images, videos, audio, documents, location, contacts, reactions, templates
Type-Safe — Full TypeScript support with comprehensive type definitions
🔄 Scalable — Handle webhooks across multiple servers with Redis

Installation

npm install easy-connect-official-wpp-rc

Prerequisites

  • Node.js 18+
  • Redis (optional, but required for webhook distribution)
  • WhatsApp Business Account with Cloud API access
  • Phone Number ID and Access Token from Meta

Quick Start

import { WhatsAppOfficialClient } from 'easy-connect-official-wpp-rc';

// 1. Create client with Redis config (automatic connection)
const client = new WhatsAppOfficialClient('your_phone_number_id', 'your_access_token', {
  host: 'localhost',
  port: 6379,
  db: 0,
});

// 2. Register listeners (✨ Redis connects automatically!)
client.onMessage((message) => {
  console.log(`Message from ${message.from}: ${message.message}`);
});

client.onMessageAck((ack) => {
  console.log(`Message ${ack.messageId} status: ${ack.status}`);
});

// 3. Handle errors and connection status
client.onError((error) => {
  console.error('Error:', error);
});

client.onConnectionStatus((status) => {
  console.log(`Connection status: ${status}`);
});

API Reference

Constructor

new WhatsAppOfficialClient(
  phoneNumberId: string,
  accessToken: string,
  redisConfig?: RedisConfig
)

Parameters:

  • phoneNumberId — Your WhatsApp Business Phone Number ID
  • accessToken — Meta Access Token with WhatsApp permissions
  • redisConfig (optional) — Redis connection configuration

RedisConfig:

interface RedisConfig {
  host?: string; // Default: 'localhost'
  port?: number; // Default: 6379
  db?: number; // Default: 0
  password?: string; // Optional
}

Sending Messages

sendText(identifier: string, message: string): Promise<Response>

Send a text message.

const response = await client.sendText('5511999999999', 'Hello!');
console.log('Message sent:', response.content);

sendTextReply(identifier: string, message: string, options?: any): Promise<Response>

Send a reply to a specific message.

await client.sendTextReply(message.from, 'Thanks!', { content: { id: message.id } });

sendImage(identifier: string, content: string, option?: ImageOption): Promise<Response>

Send an image with optional caption (auto-uploads from URL).

await client.sendImage('5511999999999', 'https://example.com/image.jpg', {
  caption: 'Check this out!',
});

sendVideo(identifier: string, content: string, option?: VideoOption): Promise<Response>

Send a video with optional caption (auto-uploads from URL).

await client.sendVideo('5511999999999', 'https://example.com/video.mp4', {
  caption: 'My video',
});

sendAudio(identifier: string, content: string, option?: AudioOption): Promise<Response>

Send an audio file (auto-uploads from URL).

await client.sendAudio('5511999999999', 'https://example.com/audio.mp3');

sendVoice(identifier: string, content: string, option?: AudioOption): Promise<Response>

Send a voice message (same as sendAudio).

await client.sendVoice('5511999999999', 'https://example.com/voice.ogg');

sendDocument(identifier: string, content: string, option?: FileOption): Promise<Response>

Send a document with optional filename (auto-uploads from URL).

await client.sendDocument('5511999999999', 'https://example.com/document.pdf', {
  filename: 'Report.pdf',
});

sendLocation(identifier: string, latitude: number, longitude: number): Promise<Response>

Send a location.

await client.sendLocation('5511999999999', -23.5505, -46.6333);

sendContact(identifier: string, contactName: string, contactPhone: string, contactPhotoUrl?: string): Promise<Response>

Send a contact card.

await client.sendContact('5511999999999', 'John Doe', '5511988888888');

sendReaction(identifier: string, reaction: string, messageId: string): Promise<Response>

Send a reaction emoji to a message.

await client.sendReaction('5511999999999', '👍', 'message_id');

sendTemplate(identifier: string, templateName: string, language?: string, parameters?: any[]): Promise<Response>

Send a pre-approved template message.

await client.sendTemplate('5511999999999', 'hello_world', 'en_US');

markReadAll(identifier: string): Promise<Response>

Mark a message as read.

await client.markReadAll('message_id');

setPresence(identifier: string, type?: string): Promise<Response>

Set presence status (typing indicator).

await client.setPresence('5511999999999', 'typing');

Event Listeners

onMessage(callback: (message: EventResponse) => void): void

Listen for incoming messages.

client.onMessage((message) => {
  console.log('Type:', message.type);

  if (message.type === 'text') {
    console.log('Text:', message.message);
  } else if (message.type === 'image') {
    console.log('Image ID:', message.media?.id);
  } else if (message.type === 'location') {
    console.log('Location:', message.location);
  }
});

onMessageAck(callback: (ack: MessageStatusEvent) => void): void

Listen for message acknowledgments.

client.onMessageAck((ack) => {
  console.log(`Message ${ack.messageId}: ${ack.status}`);
});

onMessageStatus(callback: (status: any) => void): void

Listen for status updates.

client.onMessageStatus((status) => {
  console.log('Status update:', status);
});

onConnectionStatus(callback: (status: string) => void): void

Listen for connection changes.

client.onConnectionStatus((status) => {
  if (status === 'connected') {
    console.log('Connected to WhatsApp!');
  }
});

onError(callback: (error: any) => void): void

Listen for errors.

client.onError((error) => {
  console.error('Error:', error);
});

Media Management

downloadMedia(mediaId: string): Promise<Response>

Download media from WhatsApp (returns buffer).

const response = await client.downloadMedia(message.media.id);
const buffer = response.content; // Image/video/audio buffer

getMediaUrl(mediaId: string): Promise<Response>

Get download URL for media.

const response = await client.getMediaUrl(message.media.id);
const mediaUrl = response.content.url;

Profile Management

getProfile(): Promise<Response>

Get profile information.

const profile = await client.getProfile();

updateProfile(profileName: string, aboutText?: string): Promise<Response>

Update profile name and about text.

await client.updateProfile('My Business', 'Welcome!');

getPicture(identifier: string): Promise<Response>

Get profile picture URL.

const response = await client.getPicture('5511999999999');
const picUrl = response.content;

updateProfilePicture(identifier: string, content: string): Promise<Response>

Update profile picture from URL.

await client.updateProfilePicture('5511999999999', 'https://example.com/profile.jpg');

onWhatsApp(identifier: string): Promise<Response>

Check if a phone number is registered on WhatsApp.

const response = await client.onWhatsApp('5511999999999');
if (response.status === 200) {
  console.log('Number is on WhatsApp');
}

Redis Connection

initialize(): Promise<void>

Manually initialize Redis (already automatic).

await client.initialize();

connectToRedis(config?: RedisConfig): Promise<void>

Connect with custom config.

await client.connectToRedis({
  host: 'redis.example.com',
  port: 6380,
  password: 'secret',
});

disconnectFromRedis(): Promise<void>

Disconnect from Redis.

await client.disconnectFromRedis();

isRedisConnected(): boolean

Check connection status.

if (client.isRedisConnected()) {
  console.log('Connected!');
}

Webhook Integration

Setup Webhook Server

import express from 'express';
import redis from 'redis';

const app = express();
const redisClient = redis.createClient();

// Your webhook endpoint
app.post('/webhook', (req, res) => {
  const { entry } = req.body;

  for (const e of entry) {
    for (const change of e.changes) {
      const phoneId = change.value.metadata.phone_number_id;

      // Publish to Redis
      redisClient.publish(`whatsapp:${phoneId}`, JSON.stringify(change.value));
    }
  }

  res.json({ success: true });
});

app.listen(3000);

Distribute Across Servers

// Server A
const client1 = new WhatsAppOfficialClient('phone_id', 'token', {
  host: 'redis.example.com',
});

// Server B
const client2 = new WhatsAppOfficialClient('phone_id', 'token', {
  host: 'redis.example.com',
});

// Both receive events automatically

Complete Example

import { WhatsAppOfficialClient } from 'easy-connect-official-wpp-rc';

async function main() {
  const client = new WhatsAppOfficialClient('your_phone_id', 'your_access_token', {
    host: 'localhost',
    port: 6379,
    db: 0,
  });

  // Handle messages
  client.onMessage(async (message) => {
    if (message.type === 'text') {
      console.log(`📨 ${message.from}: ${message.message}`);

      // Reply
      await client.sendText(message.from, 'Thanks! 👋');
    } else if (message.type === 'image') {
      console.log(`📸 Image received: ${message.media?.id}`);

      // Send back a reaction
      await client.sendReaction(message.from, '👍', message.id);
    }
  });

  // Handle acknowledgments
  client.onMessageAck((ack) => {
    console.log(`✔️ ${ack.status}`);
  });

  // Handle errors
  client.onError((error) => {
    console.error('❌ Error:', error);
  });

  // Connection status
  client.onConnectionStatus((status) => {
    console.log(`🔌 ${status}`);
  });

  // Graceful shutdown
  process.on('SIGINT', async () => {
    console.log('\n👋 Closing...');
    await client.disconnectFromRedis();
    process.exit(0);
  });

  console.log('🚀 Running...');
}

main().catch(console.error);

Error Handling

All methods return a Response object:

const response = await client.sendText('recipient_phone_number_id', 'Hello');

if (response.status === 200) {
  console.log('Success:', response.content);
} else {
  console.error('Error:', response.message);
}

Environment Variables

WHATSAPP_PHONE_ID=your_phone_id
WHATSAPP_ACCESS_TOKEN=your_access_token
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_DB=0
REDIS_PASSWORD=optional

Performance Tips

  1. Reuse instances — One per phone number
  2. Use Redis — For multi-server setups
  3. Fast listeners — Offload heavy work to queues
  4. Monitor health — Use onConnectionStatus
  5. Clean shutdown — Call disconnectFromRedis()

Common Issues

Redis connection timeout

  • Ensure Redis is running
  • Check host/port configuration
  • Verify network connectivity

Channel subscription failed

  • Confirm correct phoneNumberId
  • Check Redis pub/sub is enabled
  • Review logs

Webhook events not received

  • Verify webhook URL is public
  • Check Meta Dashboard configuration
  • Ensure channel name: whatsapp:${phoneId}

Documentation

License

ISC

Author

Send IO

Support