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
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-clientQuick 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 IDmessage(string): Text message contentsessionId(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 IDmedia(object): Media object withurlorbase64,mimetype,filenamecaption(string, optional): Media captionsessionId(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/setupWhatsAppStatic 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 dateTypeScript 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
- Issues: GitHub Issues
- Email: support@phiresky.com
- Documentation: Full API Docs
License
MIT © Phiresky
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
Changelog
See CHANGELOG.md for release history.
Made with ❤️ by Phiresky