A powerful WhatsApp API backend built with Express.js and Baileys library. Supports multi-session management, real-time WebSocket events, group management, and media handling.
- π± Multi-Session Support - Manage multiple WhatsApp accounts simultaneously
- π Real-time WebSocket - Get instant notifications for messages, status updates, and more
- π₯ Group Management - Create, manage, and control WhatsApp groups
- π¨ Send Messages - Text, images, documents, locations, contacts, and more
- β©οΈ Reply to Messages - Reply/quote specific messages with replyTo parameter
- π Poll Messages - Send interactive polls with single or multiple choice
- π€ Bulk Messaging - Send messages to multiple recipients with background processing
- π₯ Auto-Save Media - Automatically save incoming media to server
- πΎ Persistent Store - Message history with optimized caching
- π Session Persistence - Sessions survive server restarts
- ποΈ Admin Dashboard - Web-based dashboard with real-time monitoring and API tester
- π Swagger UI - Interactive API documentation at root URL
For complete and detailed documentation, please visit:
| π Documentation | Link |
|---|---|
| Primary Docs | https://docs.chatery.app |
| Mirror Docs | https://chatery-whatsapp-documentation.appwrite.network |
π The documentation includes complete API reference, examples, troubleshooting guides, and more.
- Full Documentation
- Installation
- Configuration
- API Key Authentication
- Quick Start
- Dashboard
- API Documentation
- WebSocket Events
- Examples
# Clone the repository
git clone https://github.com/farinchan/chatery_whatsapp.git
cd chatery_whatsapp
# Install dependencies
npm install
# Create environment file
cp .env.example .env
# Start the server
npm start
# Or development mode with auto-reload
npm run dev# Clone the repository
git clone https://github.com/farinchan/chatery_whatsapp.git
cd chatery_whatsapp
# Create environment file
cp .env.example .env
# Build and run with Docker Compose
docker-compose up -d
# View logs
docker-compose logs -f
# Stop the container
docker-compose down| Command | Description |
|---|---|
docker-compose up -d |
Start container in background |
docker-compose down |
Stop and remove container |
docker-compose logs -f |
View live logs |
docker-compose restart |
Restart container |
docker-compose build --no-cache |
Rebuild image |
The following data is persisted across container restarts:
| Volume | Path | Description |
|---|---|---|
chatery_sessions |
/app/sessions |
WhatsApp session data |
chatery_media |
/app/public/media |
Received media files |
chatery_store |
/app/store |
Message history store |
Create a .env file in the root directory:
PORT=3000
CORS_ORIGIN=*
# Dashboard Authentication
DASHBOARD_USERNAME=admin
DASHBOARD_PASSWORD=securepassword123
# API Key Authentication (optional - leave empty or 'your_api_key_here' to disable)
API_KEY=your_secret_api_key_hereAll WhatsApp API endpoints are protected with API key authentication. Include the X-Api-Key header in your requests.
-
Set a strong API key in your
.envfile:API_KEY=your_super_secret_key_12345
-
Include the header in all API requests:
curl -X GET http://localhost:3000/api/whatsapp/sessions \ -H "X-Api-Key: your_super_secret_key_12345"
To disable API key authentication, leave API_KEY empty or set it to your_api_key_here in .env:
API_KEY=
# or
API_KEY=your_api_key_here| Status | Message | Description |
|---|---|---|
| 401 | Missing X-Api-Key header | API key not provided in request |
| 403 | Invalid API key | API key doesn't match |
When logging into the dashboard, you'll be prompted to enter your API key (optional). This allows the dashboard to make authenticated API calls.
-
Start the server
npm start
-
Create a session
curl -X POST http://localhost:3000/api/whatsapp/sessions/mysession/connect \ -H "X-Api-Key: your_api_key" \ -H "Content-Type: application/json"
-
Get QR Code - Open in browser or scan
http://localhost:3000/api/whatsapp/sessions/mysession/qr/imageNote: QR image endpoint also requires API key. Use curl or include header.
-
Send a message
curl -X POST http://localhost:3000/api/whatsapp/chats/send-text \ -H "X-Api-Key: your_api_key" \ -H "Content-Type: application/json" \ -d '{"sessionId": "mysession", "chatId": "628123456789", "message": "Hello!"}'
Access the admin dashboard at http://localhost:3000/dashboard
Dashboard requires login with username and password configured in .env file.
| Field | Default Value |
|---|---|
| Username | admin |
| Password | admin123 |
| Feature | Description |
|---|---|
| π Real-time Stats | Monitor total sessions, connected/disconnected status, and WebSocket clients |
| π± Session Management | Create, connect, reconnect, and delete WhatsApp sessions |
| π· QR Code Scanner | Scan QR codes directly from the dashboard |
| π‘ Live Events | Real-time WebSocket event viewer with filtering |
| π¬ Quick Send | Send messages quickly to any number |
| π§ͺ API Tester | Test all 40+ API endpoints with pre-filled templates |
| π€ Bulk Messaging | Send messages to multiple recipients with job tracking |
| π Webhook Manager | Add, remove, and configure webhooks per session |
| πͺ Logout | Secure logout button in header |
The dashboard provides a modern dark-themed interface:
- Session Cards - View all sessions with status indicators
- QR Modal - Full-screen QR code for easy scanning
- Event Log - Live scrolling event feed with timestamps
- API Tester - Dropdown with all endpoints and auto-generated request bodies
Base URL: http://localhost:3000/api/whatsapp
GET /sessionsResponse:
{
"success": true,
"message": "Sessions retrieved",
"data": [
{
"sessionId": "mysession",
"status": "connected",
"isConnected": true,
"phoneNumber": "628123456789",
"name": "John Doe",
"webhooks": [
{
"url": "https://your-server.com/webhook",
"events": ["message", "message_ack"]
}
],
"metadata": {
"userId": "user123",
"plan": "premium"
}
}
]
}| Field | Type | Description |
|---|---|---|
sessionId |
string | Unique session identifier |
status |
string | Current status: disconnected, connecting, qr_ready, connected |
isConnected |
boolean | Whether session is currently connected |
phoneNumber |
string | Connected WhatsApp phone number |
name |
string | WhatsApp profile name |
webhooks |
array | Configured webhooks for this session |
metadata |
object | Custom metadata associated with this session |
POST /sessions/:sessionId/connectBody (Optional):
{
"metadata": {
"userId": "user123",
"plan": "premium",
"customField": "any value"
},
"webhooks": [
{ "url": "https://your-server.com/webhook", "events": ["all"] },
{ "url": "https://backup-server.com/webhook", "events": ["message"] }
]
}| Parameter | Type | Description |
|---|---|---|
metadata |
object | Optional. Custom metadata to store with session |
webhooks |
array | Optional. Array of webhook configs [{ url, events }] |
Response:
{
"success": true,
"message": "Session created",
"data": {
"sessionId": "mysession",
"status": "qr_ready",
"qrCode": "data:image/png;base64,...",
"metadata": { "userId": "user123" },
"webhooks": [
{ "url": "https://your-server.com/webhook", "events": ["all"] }
]
}
}PATCH /sessions/:sessionId/configBody:
{
"metadata": { "newField": "value" },
"webhooks": [
{ "url": "https://new-webhook.com/endpoint", "events": ["message", "connection.update"] }
]
}Response:
{
"success": true,
"message": "Session config updated",
"data": {
"sessionId": "mysession",
"metadata": { "userId": "user123", "newField": "value" },
"webhooks": [
{ "url": "https://new-webhook.com/endpoint", "events": ["message", "connection.update"] }
]
}
}POST /sessions/:sessionId/webhooksBody:
{
"url": "https://another-server.com/webhook",
"events": ["message", "connection.update"]
}DELETE /sessions/:sessionId/webhooksBody:
{
"url": "https://another-server.com/webhook"
}GET /sessions/:sessionId/statusGET /sessions/:sessionId/qrGET /sessions/:sessionId/qr/imageReturns a PNG image that can be displayed directly in browser or scanned.
DELETE /sessions/:sessionIdπ‘ Typing Indicator: All messaging endpoints support
typingTimeparameter (in milliseconds) to simulate typing before sending the message. This makes the bot appear more human-like.β©οΈ Reply to Message: All messaging endpoints support
replyToparameter to reply to a specific message. Pass the message ID to quote/reply to that message.
POST /chats/send-textBody:
{
"sessionId": "mysession",
"chatId": "628123456789",
"message": "Hello, World!",
"typingTime": 2000,
"replyTo": "3EB0B430A2B52B67D0"
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
chatId |
string | Required. Phone number (628xxx) or group ID (xxx@g.us) |
message |
string | Required. Text message to send |
typingTime |
number | Optional. Typing duration in ms before sending (default: 0) |
replyTo |
string | Optional. Message ID to reply to |
POST /chats/send-imageBody:
{
"sessionId": "mysession",
"chatId": "628123456789",
"imageUrl": "https://example.com/image.jpg",
"caption": "Check this out!",
"typingTime": 1500,
"replyTo": null
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
chatId |
string | Required. Phone number or group ID |
imageUrl |
string | Required. Direct URL to image file |
caption |
string | Optional. Image caption |
typingTime |
number | Optional. Typing duration in ms (default: 0) |
replyTo |
string | Optional. Message ID to reply to |
POST /chats/send-documentBody:
{
"sessionId": "mysession",
"chatId": "628123456789",
"documentUrl": "https://example.com/document.pdf",
"filename": "document.pdf",
"mimetype": "application/pdf",
"caption": "Here is the document you requested",
"typingTime": 1000,
"replyTo": null
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
chatId |
string | Required. Phone number or group ID |
documentUrl |
string | Required. Direct URL to document |
filename |
string | Required. Filename to display |
mimetype |
string | Optional. MIME type (default: application/pdf) |
caption |
string | Optional. Caption text for the document |
typingTime |
number | Optional. Typing duration in ms (default: 0) |
replyTo |
string | Optional. Message ID to reply to |
POST /chats/send-audio
β οΈ Important: Audio must be in OGG format (.ogg). WhatsApp only supports OGG audio files with Opus codec.Convert audio using FFmpeg:
ffmpeg -i input.mp3 -c:a libopus output.ogg
Body:
{
"sessionId": "mysession",
"chatId": "628123456789",
"audioUrl": "https://example.com/audio.ogg",
"ptt": true,
"typingTime": 1000,
"replyTo": null
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
chatId |
string | Required. Phone number or group ID |
audioUrl |
string | Required. Direct URL to OGG audio file (.ogg format only) |
ptt |
boolean | Optional. Push to talk mode - true = voice note, false = audio file (default: false) |
typingTime |
number | Optional. Recording simulation in ms (default: 0) |
replyTo |
string | Optional. Message ID to reply to |
POST /chats/send-locationBody:
{
"sessionId": "mysession",
"chatId": "628123456789",
"latitude": -6.2088,
"longitude": 106.8456,
"name": "Jakarta, Indonesia",
"typingTime": 1000,
"replyTo": null
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
chatId |
string | Required. Phone number or group ID |
latitude |
number | Required. GPS latitude |
longitude |
number | Required. GPS longitude |
name |
string | Optional. Location name |
typingTime |
number | Optional. Typing duration in ms (default: 0) |
replyTo |
string | Optional. Message ID to reply to |
POST /chats/send-contactBody:
{
"sessionId": "mysession",
"chatId": "628123456789",
"contactName": "John Doe",
"contactPhone": "628987654321",
"typingTime": 500,
"replyTo": null
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
chatId |
string | Required. Phone number or group ID |
contactName |
string | Required. Contact display name |
contactPhone |
string | Required. Contact phone number |
typingTime |
number | Optional. Typing duration in ms (default: 0) |
replyTo |
string | Optional. Message ID to reply to |
POST /chats/send-pollBody:
{
"sessionId": "mysession",
"chatId": "628123456789",
"question": "What is your favorite color?",
"options": ["Red", "Blue", "Green", "Yellow"],
"selectableCount": 1,
"typingTime": 2000,
"replyTo": null
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
chatId |
string | Required. Phone number or group ID |
question |
string | Required. Poll question |
options |
array | Required. Array of options (2-12 items) |
selectableCount |
number | Optional. Number of selectable options (default: 1) |
typingTime |
number | Optional. Typing duration in ms (default: 0) |
replyTo |
string | Optional. Message ID to reply to |
POST /chats/send-button
β οΈ Note: WhatsApp deprecated button messages in 2022. This endpoint now uses Poll as an alternative. For actual interactive buttons, you need WhatsApp Business API (Cloud API).
Body:
{
"sessionId": "mysession",
"chatId": "628123456789",
"text": "Please choose an option:",
"footer": "Powered by Chatery",
"buttons": ["Option 1", "Option 2", "Option 3"],
"typingTime": 2000,
"replyTo": null
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
chatId |
string | Required. Phone number or group ID |
text |
string | Required. Poll question (combined with footer) |
footer |
string | Optional. Additional text |
buttons |
array | Required. Array of options (poll choices) |
typingTime |
number | Optional. Typing duration in ms (default: 0) |
replyTo |
string | Optional. Message ID to reply to |
POST /chats/presenceBody:
{
"sessionId": "mysession",
"chatId": "628123456789",
"presence": "composing"
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
chatId |
string | Required. Phone number or group ID |
presence |
string | Required. composing, recording, paused, available, unavailable |
POST /chats/check-numberBody:
{
"sessionId": "mysession",
"phone": "628123456789"
}POST /chats/profile-pictureBody:
{
"sessionId": "mysession",
"phone": "628123456789"
}Bulk messaging runs in the background and returns immediately with a job ID. You can track progress using the status endpoint.
β‘ Background Processing: All bulk endpoints return immediately with a
jobId. Messages are sent in background to avoid request timeouts. Track progress with the status endpoint.
POST /chats/send-bulkBody:
{
"sessionId": "mysession",
"recipients": ["628123456789", "628987654321", "628111222333"],
"message": "Hello! This is a bulk message.",
"delayBetweenMessages": 1000,
"typingTime": 0
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
recipients |
array | Required. Array of phone numbers (max 100) |
message |
string | Required. Text message to send |
delayBetweenMessages |
number | Optional. Delay between messages in ms (default: 1000) |
typingTime |
number | Optional. Typing indicator duration in ms (default: 0) |
Response:
{
"success": true,
"message": "Bulk message job started. Check status with jobId.",
"data": {
"jobId": "bulk_1704326400000_abc123def",
"total": 3,
"statusUrl": "/api/whatsapp/chats/bulk-status/bulk_1704326400000_abc123def"
}
}POST /chats/send-bulk-imageBody:
{
"sessionId": "mysession",
"recipients": ["628123456789", "628987654321"],
"imageUrl": "https://example.com/image.jpg",
"caption": "Check out this image!",
"delayBetweenMessages": 1000,
"typingTime": 0
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
recipients |
array | Required. Array of phone numbers (max 100) |
imageUrl |
string | Required. Direct URL to image file |
caption |
string | Optional. Image caption |
delayBetweenMessages |
number | Optional. Delay between messages in ms (default: 1000) |
typingTime |
number | Optional. Typing indicator duration in ms (default: 0) |
POST /chats/send-bulk-documentBody:
{
"sessionId": "mysession",
"recipients": ["628123456789", "628987654321"],
"documentUrl": "https://example.com/document.pdf",
"filename": "document.pdf",
"mimetype": "application/pdf",
"delayBetweenMessages": 1000,
"typingTime": 0
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
recipients |
array | Required. Array of phone numbers (max 100) |
documentUrl |
string | Required. Direct URL to document |
filename |
string | Required. Filename to display |
mimetype |
string | Optional. MIME type (default: application/pdf) |
delayBetweenMessages |
number | Optional. Delay between messages in ms (default: 1000) |
typingTime |
number | Optional. Typing indicator duration in ms (default: 0) |
GET /chats/bulk-status/:jobIdResponse:
{
"success": true,
"data": {
"sessionId": "mysession",
"type": "text",
"status": "processing",
"total": 50,
"sent": 25,
"failed": 2,
"progress": 54,
"details": [
{
"recipient": "628123456789",
"status": "sent",
"messageId": "ABC123",
"timestamp": "2026-01-04T10:00:00.000Z"
},
{
"recipient": "628987654321",
"status": "failed",
"error": "Number not registered",
"timestamp": "2026-01-04T10:00:01.000Z"
}
],
"createdAt": "2026-01-04T10:00:00.000Z",
"completedAt": null
}
}| Field | Type | Description |
|---|---|---|
status |
string | processing or completed |
progress |
number | Progress percentage (0-100) |
sent |
number | Successfully sent count |
failed |
number | Failed count |
details |
array | Per-recipient status with timestamps |
POST /chats/bulk-jobsBody:
{
"sessionId": "mysession"
}Response:
{
"success": true,
"data": [
{
"jobId": "bulk_1704326400000_abc123def",
"type": "text",
"status": "completed",
"total": 50,
"sent": 48,
"failed": 2,
"progress": 100,
"createdAt": "2026-01-04T10:00:00.000Z",
"completedAt": "2026-01-04T10:02:30.000Z"
}
]
}POST /chats/overviewBody:
{
"sessionId": "mysession",
"limit": 50,
"offset": 0,
"type": "all"
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
limit |
number | Optional. Max results (default: 50) |
offset |
number | Optional. Pagination offset (default: 0) |
type |
string | Optional. Filter: all, personal, group |
POST /contactsBody:
{
"sessionId": "mysession",
"limit": 100,
"offset": 0,
"search": "john"
}POST /chats/messagesBody:
{
"sessionId": "mysession",
"chatId": "628123456789@s.whatsapp.net",
"limit": 50,
"cursor": null
}POST /chats/infoBody:
{
"sessionId": "mysession",
"chatId": "628123456789@s.whatsapp.net"
}POST /chats/mark-readMark all unread messages in a chat as read. Works for both personal and group chats.
Body:
{
"sessionId": "mysession",
"chatId": "628123456789"
}| Parameter | Type | Description |
|---|---|---|
sessionId |
string | Required. Session ID |
chatId |
string | Required. Phone number or group ID (@s.whatsapp.net or @g.us) |
Response:
{
"success": true,
"message": "Chat marked as read",
"data": {
"chatId": "628123456789@s.whatsapp.net",
"isGroup": false,
"markedCount": 5
}
}| Field | Type | Description |
|---|---|---|
chatId |
string | Chat ID that was marked as read |
isGroup |
boolean | Whether the chat is a group |
markedCount |
number | Number of messages marked as read |
Note: Messages must be received after the server starts to be in the store. If
markedCountis 0, there were no unread messages in the store.
POST /groupsBody:
{
"sessionId": "mysession"
}Response:
{
"success": true,
"data": {
"count": 5,
"groups": [
{
"id": "123456789@g.us",
"subject": "My Group",
"participantsCount": 25,
"creation": 1609459200
}
]
}
}POST /groups/createBody:
{
"sessionId": "mysession",
"name": "My New Group",
"participants": ["628123456789", "628987654321"]
}POST /groups/metadataBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us"
}Response:
{
"success": true,
"data": {
"id": "123456789@g.us",
"subject": "My Group",
"description": "Group description",
"participants": [
{ "id": "628123456789@s.whatsapp.net", "admin": "superadmin" },
{ "id": "628987654321@s.whatsapp.net", "admin": null }
],
"size": 25
}
}POST /groups/participants/addBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us",
"participants": ["628111222333", "628444555666"]
}POST /groups/participants/removeBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us",
"participants": ["628111222333"]
}POST /groups/participants/promoteBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us",
"participants": ["628111222333"]
}POST /groups/participants/demoteBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us",
"participants": ["628111222333"]
}POST /groups/subjectBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us",
"subject": "New Group Name"
}POST /groups/descriptionBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us",
"description": "This is the new group description"
}POST /groups/settingsBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us",
"setting": "announcement"
}| Setting | Description |
|---|---|
announcement |
Only admins can send messages |
not_announcement |
All participants can send messages |
locked |
Only admins can edit group info |
unlocked |
All participants can edit group info |
POST /groups/pictureBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us",
"imageUrl": "https://example.com/group-pic.jpg"
}POST /groups/leaveBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us"
}POST /groups/joinBody:
{
"sessionId": "mysession",
"inviteCode": "https://chat.whatsapp.com/AbCdEfGhIjKlMn"
}POST /groups/invite-codeBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us"
}Response:
{
"success": true,
"data": {
"groupId": "123456789@g.us",
"inviteCode": "AbCdEfGhIjKlMn",
"inviteLink": "https://chat.whatsapp.com/AbCdEfGhIjKlMn"
}
}POST /groups/revoke-inviteBody:
{
"sessionId": "mysession",
"groupId": "123456789@g.us"
}Connect to WebSocket server at ws://localhost:3000
import { io } from 'socket.io-client';
const socket = io('http://localhost:3000');
// Subscribe to a session
socket.emit('subscribe', 'mysession');
// Unsubscribe from a session
socket.emit('unsubscribe', 'mysession');| Event | Description | Payload |
|---|---|---|
qr |
QR code generated | { sessionId, qrCode, timestamp } |
connection.update |
Connection status changed | { sessionId, status, phoneNumber?, name?, timestamp } |
message |
New message received | { sessionId, message, timestamp } |
message.sent |
Message sent confirmation | { sessionId, message, timestamp } |
message.update |
Message status update (read, delivered) | { sessionId, update, timestamp } |
message.reaction |
Message reaction added | { sessionId, reactions, timestamp } |
message.revoke |
Message deleted/revoked | { sessionId, key, participant, timestamp } |
chat.update |
Chat updated | { sessionId, chats, timestamp } |
chat.upsert |
New chat created | { sessionId, chats, timestamp } |
chat.delete |
Chat deleted | { sessionId, chatIds, timestamp } |
contact.update |
Contact updated | { sessionId, contacts, timestamp } |
presence.update |
Typing, online status | { sessionId, presence, timestamp } |
group.participants |
Group members changed | { sessionId, update, timestamp } |
group.update |
Group info changed | { sessionId, update, timestamp } |
call |
Incoming call | { sessionId, call, timestamp } |
labels |
Labels updated (business) | { sessionId, labels, timestamp } |
logged.out |
Session logged out | { sessionId, message, timestamp } |
const socket = io('http://localhost:3000');
socket.on('connect', () => {
console.log('Connected to WebSocket');
socket.emit('subscribe', 'mysession');
});
socket.on('message', (data) => {
console.log('New message:', data.message);
// {
// sessionId: 'mysession',
// message: {
// id: 'ABC123',
// from: '628123456789@s.whatsapp.net',
// text: 'Hello!',
// timestamp: 1234567890,
// ...
// },
// timestamp: '2024-01-15T10:30:00.000Z'
// }
});
socket.on('qr', (data) => {
console.log('Scan QR Code:', data.qrCode);
});
socket.on('connection.update', (data) => {
console.log('Connection status:', data.status);
if (data.status === 'connected') {
console.log(`Connected as ${data.name} (${data.phoneNumber})`);
}
});Open http://localhost:3000/ws-test in your browser for an interactive WebSocket testing interface.
You can configure multiple webhook URLs to receive events from your WhatsApp session. Each webhook can subscribe to specific events.
Set webhooks when creating or updating a session:
# When creating session with multiple webhooks
curl -X POST http://localhost:3000/api/whatsapp/sessions/mysession/connect \
-H "Content-Type: application/json" \
-d '{
"metadata": { "userId": "123" },
"webhooks": [
{ "url": "https://primary-server.com/webhook", "events": ["all"] },
{ "url": "https://analytics.example.com/webhook", "events": ["message"] },
{ "url": "https://backup.example.com/webhook", "events": ["connection.update"] }
]
}'
# Add a webhook to existing session
curl -X POST http://localhost:3000/api/whatsapp/sessions/mysession/webhooks \
-H "Content-Type: application/json" \
-d '{
"url": "https://new-webhook.com/endpoint",
"events": ["message", "connection.update"]
}'
# Remove a webhook
curl -X DELETE http://localhost:3000/api/whatsapp/sessions/mysession/webhooks \
-H "Content-Type: application/json" \
-d '{
"url": "https://new-webhook.com/endpoint"
}'
# Update all webhooks
curl -X PATCH http://localhost:3000/api/whatsapp/sessions/mysession/config \
-H "Content-Type: application/json" \
-d '{
"webhooks": [
{ "url": "https://only-this-one.com/webhook", "events": ["all"] }
]
}'All configured webhook endpoints will receive POST requests with this format:
{
"event": "message",
"sessionId": "mysession",
"metadata": {
"userId": "123",
"customField": "value"
},
"data": {
"id": "ABC123",
"from": "628123456789@s.whatsapp.net",
"text": "Hello!",
"timestamp": 1234567890
},
"timestamp": "2024-01-15T10:30:00.000Z"
}| Header | Value |
|---|---|
Content-Type |
application/json |
X-Webhook-Source |
chatery-whatsapp-api |
X-Session-Id |
Session ID |
X-Webhook-Event |
Event name |
| Event | Description |
|---|---|
connection.update |
Connection status changed (connected, disconnected) |
message |
New message received |
message.sent |
Message sent confirmation |
Set events: ["all"] to receive all events, or specify individual events per webhook.
GET /api/websocket/statsResponse:
{
"success": true,
"data": {
"totalConnections": 5,
"sessionRooms": {
"mysession": 2,
"othersession": 1
}
}
}chatery_backend/
βββ index.js # Application entry point
βββ package.json
βββ .env # Environment variables
βββ README.md # Documentation
βββ public/
β βββ dashboard.html # Admin dashboard
β βββ websocket-test.html # WebSocket test page
β βββ media/ # Auto-saved media files
β βββ {sessionId}/
β βββ {chatId}/
βββ sessions/ # Session authentication data
β βββ {sessionId}/
β βββ creds.json
β βββ store.json
βββ src/
βββ routes/
β βββ whatsapp.js # API routes
βββ services/
βββ websocket/
β βββ WebSocketManager.js
βββ whatsapp/
βββ index.js
βββ WhatsAppManager.js
βββ WhatsAppSession.js
βββ BaileysStore.js
βββ MessageFormatter.js
const axios = require('axios');
const API_URL = 'http://localhost:3000/api/whatsapp';
// Create session
async function createSession(sessionId) {
const response = await axios.post(`${API_URL}/sessions/${sessionId}/connect`);
return response.data;
}
// Send message
async function sendMessage(sessionId, to, message) {
const response = await axios.post(`${API_URL}/chats/send-text`, {
sessionId,
to,
message
});
return response.data;
}
// Get all groups
async function getGroups(sessionId) {
const response = await axios.post(`${API_URL}/groups`, { sessionId });
return response.data;
}import requests
API_URL = 'http://localhost:3000/api/whatsapp'
# Create session
def create_session(session_id):
response = requests.post(f'{API_URL}/sessions/{session_id}/connect')
return response.json()
# Send message
def send_message(session_id, to, message):
response = requests.post(f'{API_URL}/chats/send-text', json={
'sessionId': session_id,
'to': to,
'message': message
})
return response.json()
# Get all groups
def get_groups(session_id):
response = requests.post(f'{API_URL}/groups', json={
'sessionId': session_id
})
return response.json()- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
If you find this project helpful, consider supporting the development:
Your support helps me maintain and improve this project! β€οΈ
Fajri Rinaldi Chan (Farin Chan)
| Resource | URL |
|---|---|
| π Swagger UI (API Docs) | http://localhost:3000 |
| ποΈ Dashboard | http://localhost:3000/dashboard |
| π API Base URL | http://localhost:3000/api/whatsapp |
| π WebSocket Test | http://localhost:3000/ws-test |
| π WebSocket Stats | http://localhost:3000/api/websocket/stats |
| β€οΈ Health Check | http://localhost:3000/api/health |
| π OpenAPI JSON | http://localhost:3000/api-docs.json |
This project is not affiliated with WhatsApp or Meta. Use at your own risk. Make sure to comply with WhatsApp's Terms of Service.
