Skip to content

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.

License

Notifications You must be signed in to change notification settings

farinchan/chatery_whatsapp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

45 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ Chatery WhatsApp API

Chatery 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.

Node.js Express.js Baileys Socket.IO License

✨ Features

  • πŸ“± 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

πŸ“– Full Documentation

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.

πŸ“‹ Table of Contents

πŸ›  Installation

Option 1: Standard Installation

# 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

Option 2: Docker Installation

# 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

Docker Commands

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

Docker Volumes

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

βš™ Configuration

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_here

πŸ” API Key Authentication

All WhatsApp API endpoints are protected with API key authentication. Include the X-Api-Key header in your requests.

How to Enable

  1. Set a strong API key in your .env file:

    API_KEY=your_super_secret_key_12345
  2. 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"

Disable Authentication

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

Error Responses

Status Message Description
401 Missing X-Api-Key header API key not provided in request
403 Invalid API key API key doesn't match

Dashboard Integration

When logging into the dashboard, you'll be prompted to enter your API key (optional). This allows the dashboard to make authenticated API calls.

πŸš€ Quick Start

  1. Start the server

    npm start
  2. 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"
  3. Get QR Code - Open in browser or scan

    http://localhost:3000/api/whatsapp/sessions/mysession/qr/image
    

    Note: QR image endpoint also requires API key. Use curl or include header.

  4. 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!"}'

πŸŽ›οΈ Dashboard

Access the admin dashboard at http://localhost:3000/dashboard

πŸ” Authentication

Dashboard requires login with username and password configured in .env file.

Field Default Value
Username admin
Password admin123

✨ Dashboard Features

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

πŸ“Έ Screenshots

Dashboard Screenshot

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

πŸ“š API Documentation

Base URL: http://localhost:3000/api/whatsapp

Sessions

List All Sessions

GET /sessions

Response:

{
  "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

Create/Connect Session

POST /sessions/:sessionId/connect

Body (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"] }
    ]
  }
}

Update Session Config

PATCH /sessions/:sessionId/config

Body:

{
  "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"] }
    ]
  }
}

Add Webhook

POST /sessions/:sessionId/webhooks

Body:

{
  "url": "https://another-server.com/webhook",
  "events": ["message", "connection.update"]
}

Remove Webhook

DELETE /sessions/:sessionId/webhooks

Body:

{
  "url": "https://another-server.com/webhook"
}

Get Session Status

GET /sessions/:sessionId/status

Get QR Code (JSON)

GET /sessions/:sessionId/qr

Get QR Code (Image)

GET /sessions/:sessionId/qr/image

Returns a PNG image that can be displayed directly in browser or scanned.

Delete Session

DELETE /sessions/:sessionId

Messaging

πŸ’‘ Typing Indicator: All messaging endpoints support typingTime parameter (in milliseconds) to simulate typing before sending the message. This makes the bot appear more human-like.

↩️ Reply to Message: All messaging endpoints support replyTo parameter to reply to a specific message. Pass the message ID to quote/reply to that message.

Send Text Message

POST /chats/send-text

Body:

{
  "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

Send Image

POST /chats/send-image

Body:

{
  "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

Send Document

POST /chats/send-document

Body:

{
  "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

Send Audio

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

Send Location

POST /chats/send-location

Body:

{
  "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

Send Contact

POST /chats/send-contact

Body:

{
  "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

Send Poll Message

POST /chats/send-poll

Body:

{
  "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

Send Button Message (DEPRECATED)

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

Send Presence Update

POST /chats/presence

Body:

{
  "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

Check Phone Number

POST /chats/check-number

Body:

{
  "sessionId": "mysession",
  "phone": "628123456789"
}

Get Profile Picture

POST /chats/profile-picture

Body:

{
  "sessionId": "mysession",
  "phone": "628123456789"
}

Bulk Messaging (Background Jobs)

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.

Send Bulk Text Message

POST /chats/send-bulk

Body:

{
  "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"
  }
}

Send Bulk Image

POST /chats/send-bulk-image

Body:

{
  "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)

Send Bulk Document

POST /chats/send-bulk-document

Body:

{
  "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 Bulk Job Status

GET /chats/bulk-status/:jobId

Response:

{
  "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

Get All Bulk Jobs

POST /chats/bulk-jobs

Body:

{
  "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"
    }
  ]
}

Chat History

Get Chats Overview

POST /chats/overview

Body:

{
  "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

Get Contacts

POST /contacts

Body:

{
  "sessionId": "mysession",
  "limit": 100,
  "offset": 0,
  "search": "john"
}

Get Chat Messages

POST /chats/messages

Body:

{
  "sessionId": "mysession",
  "chatId": "628123456789@s.whatsapp.net",
  "limit": 50,
  "cursor": null
}

Get Chat Info

POST /chats/info

Body:

{
  "sessionId": "mysession",
  "chatId": "628123456789@s.whatsapp.net"
}

Mark Chat as Read

POST /chats/mark-read

Mark 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 markedCount is 0, there were no unread messages in the store.


Group Management

Get All Groups

POST /groups

Body:

{
  "sessionId": "mysession"
}

Response:

{
  "success": true,
  "data": {
    "count": 5,
    "groups": [
      {
        "id": "123456789@g.us",
        "subject": "My Group",
        "participantsCount": 25,
        "creation": 1609459200
      }
    ]
  }
}

Create Group

POST /groups/create

Body:

{
  "sessionId": "mysession",
  "name": "My New Group",
  "participants": ["628123456789", "628987654321"]
}

Get Group Metadata

POST /groups/metadata

Body:

{
  "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
  }
}

Add Participants

POST /groups/participants/add

Body:

{
  "sessionId": "mysession",
  "groupId": "123456789@g.us",
  "participants": ["628111222333", "628444555666"]
}

Remove Participants

POST /groups/participants/remove

Body:

{
  "sessionId": "mysession",
  "groupId": "123456789@g.us",
  "participants": ["628111222333"]
}

Promote to Admin

POST /groups/participants/promote

Body:

{
  "sessionId": "mysession",
  "groupId": "123456789@g.us",
  "participants": ["628111222333"]
}

Demote from Admin

POST /groups/participants/demote

Body:

{
  "sessionId": "mysession",
  "groupId": "123456789@g.us",
  "participants": ["628111222333"]
}

Update Group Subject (Name)

POST /groups/subject

Body:

{
  "sessionId": "mysession",
  "groupId": "123456789@g.us",
  "subject": "New Group Name"
}

Update Group Description

POST /groups/description

Body:

{
  "sessionId": "mysession",
  "groupId": "123456789@g.us",
  "description": "This is the new group description"
}

Update Group Settings

POST /groups/settings

Body:

{
  "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

Update Group Picture

POST /groups/picture

Body:

{
  "sessionId": "mysession",
  "groupId": "123456789@g.us",
  "imageUrl": "https://example.com/group-pic.jpg"
}

Leave Group

POST /groups/leave

Body:

{
  "sessionId": "mysession",
  "groupId": "123456789@g.us"
}

Join Group via Invite

POST /groups/join

Body:

{
  "sessionId": "mysession",
  "inviteCode": "https://chat.whatsapp.com/AbCdEfGhIjKlMn"
}

Get Invite Code

POST /groups/invite-code

Body:

{
  "sessionId": "mysession",
  "groupId": "123456789@g.us"
}

Response:

{
  "success": true,
  "data": {
    "groupId": "123456789@g.us",
    "inviteCode": "AbCdEfGhIjKlMn",
    "inviteLink": "https://chat.whatsapp.com/AbCdEfGhIjKlMn"
  }
}

Revoke Invite Code

POST /groups/revoke-invite

Body:

{
  "sessionId": "mysession",
  "groupId": "123456789@g.us"
}

πŸ”Œ WebSocket Events

Connect to WebSocket server at ws://localhost:3000

Connection

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');

Events

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 }

Example: Listen for Messages

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})`);
  }
});

WebSocket Test Page

Open http://localhost:3000/ws-test in your browser for an interactive WebSocket testing interface.


πŸͺ Webhooks

You can configure multiple webhook URLs to receive events from your WhatsApp session. Each webhook can subscribe to specific events.

Setup Multiple Webhooks

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"] }
    ]
  }'

Webhook Payload

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"
}

Webhook Headers

Header Value
Content-Type application/json
X-Webhook-Source chatery-whatsapp-api
X-Session-Id Session ID
X-Webhook-Event Event name

Available Webhook Events

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.

WebSocket Stats

GET /api/websocket/stats

Response:

{
  "success": true,
  "data": {
    "totalConnections": 5,
    "sessionRooms": {
      "mysession": 2,
      "othersession": 1
    }
  }
}

πŸ“ Project Structure

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

πŸ“ Examples

Node.js Client

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;
}

Python Client

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()

🀝 Contributing

  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.


β˜• Support & Donate

If you find this project helpful, consider supporting the development:

Saweria PayPal

GitHub Stars GitHub Forks

Your support helps me maintain and improve this project! ❀️


πŸ‘¨β€πŸ’» Author

Fajri Rinaldi Chan (Farin Chan)

GitHub LinkedIn Instagram


πŸ”— Quick Links

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

⚠️ Disclaimer

This project is not affiliated with WhatsApp or Meta. Use at your own risk. Make sure to comply with WhatsApp's Terms of Service.

About

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.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

No packages published