A production-ready RESTful API implementation of @whiskeysockets/Baileys with multi-device support, database persistence, webhook integration, and automatic history synchronization.
- π Multi-Device Support - Connect multiple WhatsApp accounts simultaneously
- πΎ Database Persistence - Store sessions, chats, contacts, and messages using Prisma ORM (MySQL)
- π History Sync - Automatic synchronization of chat history and messages
- π Cursor Pagination - Efficient pagination for chats and messages
- π Webhook Integration - Real-time event notifications for all WhatsApp events
- π API Authentication - Secure your endpoints with token-based authentication
- π± QR Code & Pairing Code - Flexible authentication methods
- π Production Ready - Built with Express 5, Prisma, and modern Node.js (ESM)
- π§Ή Smart Filtering - Automatically filters out protocol messages from chat history
- Node.js version 18.16.0 or higher
- MySQL database (or compatible database supported by Prisma)
git clone https://github.com/plusemon/baileys-api.git
cd baileys-api
npm installcp .env.example .envEdit .env with your configuration:
# Server Configuration
HOST=127.0.0.1
PORT=8000
# WhatsApp Connection
MAX_RETRIES=-1 # -1 for infinite retries
RECONNECT_INTERVAL=5000 # Milliseconds between reconnection attempts
# Authentication
AUTHENTICATION_GLOBAL_AUTH_TOKEN= # Leave empty to disable, or set a secure token
# Webhook Configuration
APP_WEBHOOK_URL= # Your webhook endpoint URL
APP_WEBHOOK_ALLOWED_EVENTS=MESSAGES_UPSERT,MESSAGES_DELETE,MESSAGES_UPDATE
APP_WEBHOOK_FILE_IN_BASE64=false # Set to true to receive media files as base64
# Database Configuration
STORE_TYPE=database # "database" or "file"
DATABASE_URL=mysql://root:password@localhost:3306/whatsapp_web_apinpx prisma migrate deploy
npx prisma generate# Development mode with auto-reload
npm run dev
# Production mode
npm startThe API will be available at http://localhost:8000.
If AUTHENTICATION_GLOBAL_AUTH_TOKEN is set in your .env, include it in requests:
curl -H "Authorization: Bearer YOUR_TOKEN_HERE" \
http://localhost:8000/sessions/listPOST /sessions/add
Content-Type: application/json
{
"id": "my-session"
}Response:
{
"success": true,
"message": "QR code received, please scan the QR code.",
"data": {
"qrcode": "data:image/png;base64,..."
}
}POST /sessions/add
Content-Type: application/json
{
"id": "my-session",
"typeAuth": "code",
"phoneNumber": "1234567890"
}GET /sessions/status/:idResponse:
{
"success": true,
"data": {
"status": "authenticated"
}
}GET /sessions/listDELETE /sessions/delete/:idGET /chats?id=my-session&limit=20&cursor=12Parameters:
id(required): Session IDlimit(optional, default: 20): Number of chats per pagecursor(optional): Cursor from previous response for next page
Response:
{
"success": true,
"data": {
"chats": [
{
"id": "1234567890@s.whatsapp.net",
"name": "John Doe",
"unreadCount": 5,
"conversationTimestamp": 1732534567,
"lastUpdated": 1732534567890
}
],
"nextCursor": "25",
"hasMore": true
}
}GET /chats/:jid?id=my-session&limit=25&cursorId=ABC123&cursorFromMe=falseParameters:
id(required): Session IDlimit(optional, default: 25): Number of messages per pagecursorId(optional): Message ID from previous responsecursorFromMe(optional): Whether cursor message was sent by you
Response:
{
"success": true,
"data": {
"messages": [
{
"key": {
"remoteJid": "1234567890@s.whatsapp.net",
"id": "ABC123",
"fromMe": false
},
"message": {
"conversation": "Hello!"
},
"messageTimestamp": 1732534567,
"pushName": "John Doe"
}
],
"nextCursor": {
"id": "XYZ789",
"fromMe": true
},
"hasMore": true
}
}POST /chats/send?id=my-session
Content-Type: application/json
{
"receiver": "1234567890",
"message": {
"text": "Hello from API!"
}
}POST /chats/send?id=my-session
Content-Type: application/json
{
"receiver": "1234567890",
"message": {
"image": {
"url": "https://example.com/image.jpg",
"caption": "Check this out!"
}
}
}Supported media types: image, video, audio, document, sticker
POST /chats/send-bulk?id=my-session
Content-Type: application/json
[
{
"receiver": "1234567890",
"message": { "text": "Hello!" },
"delay": 1000
},
{
"receiver": "0987654321",
"message": { "text": "Hi there!" },
"delay": 2000
}
]POST /chats/read?id=my-session
Content-Type: application/json
{
"keys": [
{
"remoteJid": "1234567890@s.whatsapp.net",
"id": "MESSAGE_ID",
"fromMe": false
}
]
}Mark all messages in a conversation as read and reset the unread count:
POST /chats/mark-as-read?id=my-session
Content-Type: application/json
{
"jid": "1234567890@s.whatsapp.net"
}Response:
{
"success": true,
"message": "The conversation has been successfully marked as read.",
"data": {
"markedCount": 15
}
}POST /chats/send-presence?id=my-session
Content-Type: application/json
{
"receiver": "1234567890",
"presence": "composing"
}Presence types: composing, recording, available, unavailable
GET /groups?id=my-sessionPOST /groups/create?id=my-session
Content-Type: application/json
{
"subject": "My Group",
"participants": ["1234567890", "0987654321"]
}POST /groups/update-participants?id=my-session
Content-Type: application/json
{
"groupId": "123456789-1234567890@g.us",
"participants": ["1234567890"],
"action": "add"
}Actions: add, remove, promote, demote
POST /groups/update-subject?id=my-session
Content-Type: application/json
{
"groupId": "123456789-1234567890@g.us",
"subject": "New Group Name"
}POST /groups/invite-code?id=my-session
Content-Type: application/json
{
"groupId": "123456789-1234567890@g.us"
}Configure webhook URL in .env:
APP_WEBHOOK_URL=https://your-webhook-endpoint.com/webhook
APP_WEBHOOK_ALLOWED_EVENTS=ALL| Event | Description |
|---|---|
QRCODE_UPDATED |
QR code generated/updated |
CONNECTION_UPDATE |
Connection status changed |
MESSAGES_UPSERT |
New message received |
MESSAGES_UPDATE |
Message updated (status, edit) |
MESSAGES_DELETE |
Message deleted |
MESSAGING_HISTORY_SET |
Chat history synced |
CHATS_SET |
Initial chats loaded |
CHATS_UPSERT |
New chat created |
CHATS_UPDATE |
Chat updated |
CONTACTS_SET |
Initial contacts loaded |
CONTACTS_UPSERT |
Contact added/updated |
GROUPS_UPSERT |
Group created |
GROUPS_UPDATE |
Group info updated |
GROUP_PARTICIPANTS_UPDATE |
Participant added/removed/promoted/demoted |
PRESENCE_UPDATE |
User online/typing status |
{
"instance": "my-session",
"type": "MESSAGES_UPSERT",
"data": {
// Event-specific data
}
}Stores WhatsApp authentication data (credentials, encryption keys, pre-keys, session keys).
Note: 800+ records per session is normal! Each record stores different encryption keys required by the Signal Protocol.
Stores chat/conversation metadata.
Stores message history with automatic filtering of protocol messages.
Stores contact information.
# Run migrations
npx prisma migrate deploy
# Generate Prisma Client
npx prisma generate
# View database in Prisma Studio
npx prisma studio
# Reset database (WARNING: Deletes all data)
npx prisma migrate resetbaileys-api/
βββ controllers/ # API route controllers
β βββ sessionsController.js
β βββ chatsController.js
β βββ getMessages.js
β βββ groupsController.js
βββ middlewares/ # Express middlewares
β βββ authenticationValidator.js
β βββ requestValidator.js
β βββ sessionValidator.js
βββ routes/ # API route definitions
β βββ sessionsRoute.js
β βββ chatsRoute.js
β βββ groupsRoute.js
βββ store/ # Data persistence layer
β βββ database-store.js # Database storage implementation
β βββ database-auth-state.js # Auth state management
β βββ memory-store.js # In-memory storage
βββ utils/ # Utility functions
β βββ prisma.js
β βββ logger.js
β βββ functions.js
βββ prisma/ # Database schema and migrations
β βββ schema.prisma
β βββ migrations/
βββ app.js # Express app setup
βββ whatsapp.js # Baileys integration & event handlers
βββ routes.js # Route registration
# Lint code
npm run lint
# Fix linting issues
npm run lint:fix
# Format code
npm run format
# Check formatting
npm run format:checkWhen you connect a new session, WhatsApp automatically syncs your chat history through HISTORY_SYNC_NOTIFICATION messages. The API:
- Receives encrypted history sync notifications
- Downloads and decrypts the history
- Fires
messaging-history.setevent with chats, contacts, and messages - Stores everything in the database
- Filters out protocol messages automatically
Both chats and messages use cursor-based pagination for efficiency:
Chats: Uses pkId (primary key) as cursor
Messages: Uses {id, fromMe} composite cursor
Benefits:
- β Consistent results even with new data
- β Better performance than offset pagination
- β Works well with real-time updates
The API automatically filters out these system messages:
HISTORY_SYNC_NOTIFICATIONAPP_STATE_SYNC_KEY_SHAREINITIAL_SECURITY_NOTIFICATION_SETTING_SYNCAPP_STATE_FATAL_EXCEPTION_NOTIFICATION
Only real chat messages are stored and returned.
- Session Recovery: Sessions are automatically recovered on server restart
- Multi-Device: Each session supports WhatsApp multi-device protocol
- Rate Limiting: Implement rate limiting in production to avoid WhatsApp bans
- Message Validation: Always validate message content before sending
- Error Handling: The API provides detailed error messages
- Auto-Reconnect: Automatic reconnection with configurable retry logic
This project is intended for educational and legitimate business purposes only.
DO NOT use for:
- β Spamming
- β Unsolicited marketing
- β Any activities prohibited by WhatsApp's Terms of Service
The authors are not responsible for misuse of this software. Use at your own risk.
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is open source and available under the MIT License.
- @whiskeysockets/Baileys - The amazing WhatsApp Web API library
- Prisma - Next-generation ORM
- All contributors and users of this project
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with β€οΈ for the WhatsApp API community