JSPM

whatshub-client

1.2.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 2
  • Score
    100M100P100Q61713F
  • License MIT

Official Node.js client library for WhatsHub - Universal WhatsApp Gateway API with SSE and Webhook support

Package Exports

  • whatshub-client
  • whatshub-client/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (whatshub-client) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

whatshub-client

Official Node.js client library for WhatsHub - Universal WhatsApp Gateway API

npm version License: MIT

Features

Easy to use - Simple, intuitive API ✅ TypeScript support - Full type definitions included ✅ Two delivery modes - SSE (persistent servers) or Webhooks (Firebase Functions, serverless) ✅ Real-time messages - Built-in SSE (Server-Sent Events) handling ✅ Webhook support - Perfect for Firebase Functions, AWS Lambda, serverless ✅ Auto-reconnect - Automatic event stream reconnection ✅ Event-driven - EventEmitter-based for reactive programming ✅ Media support - Send images, videos, audio, documents ✅ Auto image optimization - Images over 1MB automatically compressed ✅ Group messaging - Get and message WhatsApp groups ✅ Promise-based - Modern async/await API ✅ HMAC security - Built-in webhook signature verification

Installation

npm install whatshub-client

Quick Start

const WhatsHubClient = require('@phiresky/whatshub-client');

// Create client
const client = new WhatsHubClient({
  hubUrl: 'https://uat.phiresky.com/api/whatsapp-hub',
  apiKey: 'wh_live_your_api_key_here',
  sessionId: 'my-company-support'
});

// Create session and connect
await client.createSession();

// Listen for QR code
client.on('qr', (qrCode) => {
  console.log('Scan this QR code with WhatsApp:', qrCode);
});

// Listen for connection
client.on('ready', (data) => {
  console.log('WhatsApp connected!', data.phoneNumber);
});

// Listen for messages
client.on('message', (message) => {
  console.log('New message from:', message.chatId);
  console.log('Text:', message.text);
});

// Connect to real-time stream
client.connectSSE();

// Send a message
await client.sendMessage('+27763724011', 'Hello from WhatsHub!');

Configuration

Client Options

const client = new WhatsHubClient({
  hubUrl: 'https://uat.phiresky.com/api/whatsapp-hub',  // Required
  apiKey: 'wh_live_xxxxx',                               // Required
  sessionId: 'my-session',                               // Optional
  autoConnect: false,                                     // Optional
  debug: false,                                           // Optional
  webhookUrl: 'https://your-app.com/webhook',           // Optional (for Firebase Functions)
  webhookSecret: 'your-secret-123'                       // Optional (for webhook verification)
});
Option Type Required Description
hubUrl string ✅ Yes WhatsHub server URL
apiKey string ✅ Yes Your WhatsHub API key
sessionId string ❌ No Session ID (auto-generated if not provided)
autoConnect boolean ❌ No Auto-connect SSE on init (default: false)
debug boolean ❌ No Enable debug logging (default: false)
webhookUrl string ❌ No Webhook URL for message delivery (Firebase Functions, serverless)
webhookSecret string ❌ No Secret for HMAC signature verification

API Reference

Sessions

createSession(options)

Create a new WhatsApp session

await client.createSession({
  sessionId: 'my-session',           // Optional
  syncContacts: ['+27763724011'],    // Optional
  syncHistory: false                 // Optional (default: false)
});

Returns: Promise<{sessionId: string}>

getQRCode(sessionId)

Get QR code for WhatsApp authentication

const { qrCode } = await client.getQRCode();
// qrCode is a data URL: "data:image/png;base64,..."

Returns: Promise<{qrCode: string}>

getStatus(sessionId)

Get session connection status

const status = await client.getStatus();
console.log(status.connected);      // true/false
console.log(status.phoneNumber);    // "+27815665778"

Returns: Promise<SessionStatus>

getUserStatus()

Get overall user status (all sessions)

const status = await client.getUserStatus();
console.log(status.hasActiveConnection);  // true/false
console.log(status.connectedSessions);    // 2
console.log(status.sessions);             // [...]

Returns: Promise<UserStatus>

deleteSession(sessionId)

Delete session (logout from WhatsApp)

await client.deleteSession();

Returns: Promise<void>

Messaging

sendMessage(to, message, sessionId)

Send a text message

const result = await client.sendMessage('+27763724011', 'Hello!');
console.log(result.messageId);

Parameters:

  • to (string): Phone number (+27763724011) or group ID
  • message (string): Text message content
  • sessionId (string, optional): Session ID

Returns: Promise<{success: boolean, messageId: string}>

sendMedia(to, media, caption, sessionId)

Send media message (image, video, audio, document)

// From URL
await client.sendMedia('+27763724011', {
  url: 'https://example.com/image.jpg',
  mimetype: 'image/jpeg',
  filename: 'photo.jpg'
}, 'Check this out!');

// From Base64
await client.sendMedia('+27763724011', {
  base64: 'iVBORw0KGgoAAAANS...',
  mimetype: 'image/png',
  filename: 'screenshot.png'
}, 'Screenshot attached');

Parameters:

  • to (string): Phone number or group ID
  • media (object): Media object with url or base64, mimetype, filename
  • caption (string, optional): Media caption
  • sessionId (string, optional): Session ID

Returns: Promise<{success: boolean, messageId: string}>

getMessages(options, sessionId)

Get message history

const messages = await client.getMessages({
  contact: '+27763724011',  // Optional: filter by contact
  from: '2025-11-01',       // Optional: start date
  to: '2025-11-03',         // Optional: end date
  limit: 100                // Optional: max messages (default: 100)
});

Returns: Promise<Message[]>

Groups

getGroups(sessionId)

Get list of WhatsApp groups

const groups = await client.getGroups();

groups.forEach(group => {
  console.log(group.id);          // "120363422849127323@g.us"
  console.log(group.subject);     // "Family Group"
  console.log(group.participants); // 15
});

Returns: Promise<WhatsAppGroup[]>

Real-Time Events (SSE)

connectSSE(sessionId)

Connect to Server-Sent Events stream for real-time updates

client.connectSSE();

disconnectSSE()

Disconnect from SSE stream

client.disconnectSSE();

Events

The client extends EventEmitter and emits the following events:

Connection Events

qr

QR code available for scanning

client.on('qr', (qrCode, data) => {
  console.log('QR Code:', qrCode);  // data URL
});

ready / connected

WhatsApp connected and authenticated

client.on('ready', (data) => {
  console.log('Connected!', data.phoneNumber);
});

disconnected

WhatsApp disconnected

client.on('disconnected', (data) => {
  console.log('Disconnected:', data.reason);
  console.log('Will reconnect:', data.shouldReconnect);
});

conflict

Multiple devices connected (action required)

client.on('conflict', (data) => {
  console.error('Conflict detected:', data.reason);
  // Log out of other WhatsApp Web/Desktop sessions
});

Message Events

message

New incoming message

client.on('message', (message) => {
  console.log('From:', message.chatId);
  console.log('Text:', message.text);
  console.log('Has media:', message.hasMedia);

  // Auto-reply example
  if (message.text.toLowerCase().includes('help')) {
    client.sendMessage(message.chatId, 'How can I help you?');
  }
});

message-sent

Message successfully sent

client.on('message-sent', (data) => {
  console.log('Message sent to:', data.to);
  console.log('Message ID:', data.messageId);
});

Other Events

heartbeat

Keep-alive ping (every 30 seconds)

client.on('heartbeat', (data) => {
  console.log('Heartbeat:', data.timestamp);
});

error

Error occurred

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

Complete Examples

Example 1: Basic Bot

const WhatsHubClient = require('@phiresky/whatshub-client');

const client = new WhatsHubClient({
  hubUrl: 'https://uat.phiresky.com/api/whatsapp-hub',
  apiKey: process.env.WHATSHUB_API_KEY,
  sessionId: 'support-bot',
  debug: true
});

async function main() {
  // Create session
  await client.createSession();

  // Handle QR code
  client.on('qr', (qrCode) => {
    console.log('Please scan this QR code with WhatsApp');
    // Display QR code or save to file
  });

  // Handle connection
  client.on('ready', async (data) => {
    console.log('✅ WhatsApp connected!', data.phoneNumber);

    // Send startup notification
    await client.sendMessage('+27763724011', 'Bot is now online! 🤖');
  });

  // Handle incoming messages
  client.on('message', async (message) => {
    // Ignore messages from self
    if (message.fromMe) return;

    console.log(`Message from ${message.chatId}: ${message.text}`);

    // Simple command handling
    if (message.text === '/help') {
      await client.sendMessage(message.chatId,
        'Available commands:\n/help - Show this message\n/status - Check bot status');
    }
    else if (message.text === '/status') {
      const status = await client.getUserStatus();
      await client.sendMessage(message.chatId,
        `Bot Status:\nConnected: ${status.hasActiveConnection}\nSessions: ${status.totalSessions}`);
    }
    else {
      await client.sendMessage(message.chatId,
        'Thanks for your message! Type /help for available commands.');
    }
  });

  // Handle disconnection
  client.on('disconnected', (data) => {
    console.log('Disconnected:', data.reason);
    if (data.shouldReconnect) {
      console.log('Will attempt to reconnect...');
    }
  });

  // Connect to real-time stream
  client.connectSSE();
}

main().catch(console.error);

Example 2: Send Bulk Messages

const WhatsHubClient = require('@phiresky/whatshub-client');

const client = new WhatsHubClient({
  hubUrl: 'https://uat.phiresky.com/api/whatsapp-hub',
  apiKey: process.env.WHATSHUB_API_KEY,
  sessionId: 'bulk-sender'
});

async function sendBulkMessages() {
  // Wait for connection
  await client.createSession();

  // Get status to ensure connected
  const status = await client.getStatus();
  if (!status.connected) {
    console.log('Not connected. Please scan QR code first.');
    return;
  }

  const contacts = [
    '+27763724011',
    '+27815665778',
    // ... more contacts
  ];

  const message = 'Hello! This is a bulk message from our system.';

  for (const contact of contacts) {
    try {
      await client.sendMessage(contact, message);
      console.log(`✅ Sent to ${contact}`);

      // Rate limiting: ~40-60 messages/minute
      await new Promise(resolve => setTimeout(resolve, 1500));
    } catch (error) {
      console.error(`❌ Failed to send to ${contact}:`, error.message);
    }
  }

  console.log('Bulk send complete!');
}

sendBulkMessages().catch(console.error);

Example 3: Send Media

const WhatsHubClient = require('@phiresky/whatshub-client');
const fs = require('fs');

const client = new WhatsHubClient({
  hubUrl: 'https://uat.phiresky.com/api/whatsapp-hub',
  apiKey: process.env.WHATSHUB_API_KEY,
  sessionId: 'media-sender'
});

async function sendImage() {
  // From URL
  await client.sendMedia('+27763724011', {
    url: 'https://example.com/promo.jpg',
    mimetype: 'image/jpeg',
    filename: 'promo.jpg'
  }, '🎉 Special offer just for you!');

  // From local file (base64)
  const imageBuffer = fs.readFileSync('./image.png');
  const base64Image = imageBuffer.toString('base64');

  await client.sendMedia('+27763724011', {
    base64: base64Image,
    mimetype: 'image/png',
    filename: 'image.png'
  }, 'Check out this screenshot!');
}

sendImage().catch(console.error);

Example 4: Group Messaging

const WhatsHubClient = require('@phiresky/whatshub-client');

const client = new WhatsHubClient({
  hubUrl: 'https://uat.phiresky.com/api/whatsapp-hub',
  apiKey: process.env.WHATSHUB_API_KEY,
  sessionId: 'group-bot'
});

async function sendToGroup() {
  // Get all groups
  const groups = await client.getGroups();

  console.log(`Found ${groups.length} groups`);

  // Find specific group
  const targetGroup = groups.find(g =>
    g.subject.toLowerCase().includes('team')
  );

  if (targetGroup) {
    await client.sendMessage(targetGroup.id,
      '📢 Team announcement: Meeting at 3 PM today!');
    console.log(`Message sent to group: ${targetGroup.subject}`);
  }
}

sendToGroup().catch(console.error);

Webhook Integration (Firebase Functions, Serverless)

For stateless environments like Firebase Functions or AWS Lambda, use webhook mode:

Setup with Webhooks

const functions = require('firebase-functions');
const WhatsHubClient = require('whatshub-client');

// Webhook endpoint - receives messages from WhatsHub
exports.whatsappWebhook = functions.https.onRequest(async (req, res) => {
  if (req.method !== 'POST') {
    return res.status(405).send('Method Not Allowed');
  }

  // 1. Verify HMAC signature (CRITICAL!)
  const signature = req.headers['x-whatshub-signature'];
  const secret = functions.config().whatsapp.webhook_secret;

  try {
    const isValid = WhatsHubClient.verifyWebhookSignature(
      req.body,
      signature,
      secret
    );

    if (!isValid) {
      return res.status(401).send('Unauthorized');
    }
  } catch (error) {
    return res.status(400).send('Invalid signature');
  }

  // 2. Parse message
  const message = WhatsHubClient.parseWebhookPayload(req.body);

  console.log('Received:', message.text);

  // 3. Process message (your logic here)
  // ...

  // 4. Respond quickly (5s timeout)
  res.status(200).send('OK');
});

// Setup function - call once to create session
exports.setupWhatsApp = functions.https.onRequest(async (req, res) => {
  const client = new WhatsHubClient({
    hubUrl: 'https://uat.phiresky.com/api/whatsapp-hub',
    apiKey: functions.config().whatsapp.api_key
  });

  const webhookUrl = `https://us-central1-${process.env.GCLOUD_PROJECT}.cloudfunctions.net/whatsappWebhook`;

  await client.createSession({
    sessionId: 'my-session',
    webhookUrl: webhookUrl,
    webhookSecret: functions.config().whatsapp.webhook_secret
  });

  const { qrCode } = await client.getQRCode('my-session');

  res.json({ message: 'Scan QR code', qrCode });
});

Deploy to Firebase

# Set config
firebase functions:config:set \
  whatsapp.api_key="wh_live_your_key" \
  whatsapp.webhook_secret="your-secret"

# Deploy
firebase deploy --only functions

# Setup (one-time)
curl https://us-central1-your-project.cloudfunctions.net/setupWhatsApp

Static Utility Methods

The client provides static methods for webhook handling:

WhatsHubClient.verifyWebhookSignature(body, signature, secret)

Verifies HMAC-SHA256 signature from WhatsHub webhooks:

const isValid = WhatsHubClient.verifyWebhookSignature(
  req.body,                            // Request body (object or string)
  req.headers['x-whatshub-signature'], // Signature header
  process.env.WEBHOOK_SECRET           // Your secret
);

if (!isValid) {
  throw new Error('Invalid signature');
}

WhatsHubClient.parseWebhookPayload(body)

Parses and validates webhook payload:

const message = WhatsHubClient.parseWebhookPayload(req.body);

console.log(message.chatId);    // "27763724011@s.whatsapp.net"
console.log(message.text);      // "Hello!"
console.log(message.timestamp); // ISO date

TypeScript Usage

import WhatsHubClient, {
  WhatsHubClientOptions,
  MessageEvent
} from '@phiresky/whatshub-client';

const options: WhatsHubClientOptions = {
  hubUrl: 'https://uat.phiresky.com/api/whatsapp-hub',
  apiKey: process.env.WHATSHUB_API_KEY!,
  sessionId: 'my-session',
  debug: true
};

const client = new WhatsHubClient(options);

client.on('message', (message: MessageEvent) => {
  console.log('Message:', message.text);
});

await client.createSession();
client.connectSSE();

Error Handling

const client = new WhatsHubClient({
  hubUrl: 'https://uat.phiresky.com/api/whatsapp-hub',
  apiKey: process.env.WHATSHUB_API_KEY,
  sessionId: 'my-session'
});

// Handle errors from API calls
try {
  await client.sendMessage('+27763724011', 'Hello!');
} catch (error) {
  console.error('Failed to send message:', error.message);
}

// Handle SSE errors
client.on('error', (error) => {
  console.error('SSE error:', error);

  // Implement retry logic
  setTimeout(() => {
    console.log('Reconnecting...');
    client.connectSSE();
  }, 5000);
});

// Handle conflicts
client.on('conflict', (data) => {
  console.error('Multiple devices connected!');
  console.error('Please log out of other WhatsApp Web/Desktop sessions');
  // Notify admin or take corrective action
});

Best Practices

1. Use Environment Variables

const client = new WhatsHubClient({
  hubUrl: process.env.WHATSHUB_URL,
  apiKey: process.env.WHATSHUB_API_KEY,
  sessionId: process.env.WHATSHUB_SESSION_ID
});

2. Respect Rate Limits

// WhatsApp rate limit: ~40-60 messages/minute
async function sendWithRateLimit(contacts, message) {
  for (const contact of contacts) {
    await client.sendMessage(contact, message);
    await new Promise(resolve => setTimeout(resolve, 1500)); // 1.5s delay
  }
}

3. Handle Disconnections

client.on('disconnected', (data) => {
  if (data.shouldReconnect) {
    // Implement exponential backoff
    setTimeout(() => client.connectSSE(), 5000);
  } else {
    // Permanent disconnect - take action
    console.error('Permanent disconnect - manual intervention required');
  }
});

4. Clean Up

process.on('SIGINT', () => {
  console.log('Shutting down...');
  client.destroy();
  process.exit(0);
});

Troubleshooting

QR Code Not Appearing

// Ensure session is created first
await client.createSession();

// Then get QR code
const { qrCode } = await client.getQRCode();

Messages Not Being Received

// Make sure SSE is connected
client.connectSSE();

// Check connection status
const status = await client.getStatus();
console.log('Connected:', status.connected);

Session Keeps Disconnecting

// Check for conflicts
client.on('conflict', (data) => {
  console.error('Multiple devices connected!');
  // Log out of other WhatsApp Web/Desktop sessions
});

API Documentation

For complete API documentation, see:

Support

License

MIT © Phiresky

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details.

Changelog

See CHANGELOG.md for release history.


Made with ❤️ by Phiresky