Production-ready, self-hosted WhatsApp Web API with Admin UI, durable queues, and automation hooks
Watson WA API is a self-hosted WhatsApp integration platform built on WhatsApp Web using Baileys.
It provides a secure API, Admin UI, Pairing UI, durable outbound queues, and optional n8n automation forwarding.
Designed for single-server production deployments, with safety-first throttling and persistent message delivery.
- Features
- Architecture
- Screens & UIs
- Repository Structure
- Security Model
- Requirements
- Quick Start
- Environment Variables
- API Overview
- Aliases
- Durable Queue
- n8n Automations
- Re-Pairing WhatsApp
- Backups
- Security Notes
- Production Checklist
- License
- WhatsApp Web connection via Baileys
- QR-based Pairing UI
- Web Admin UI
- Integration-friendly REST API
- Durable outbound queue using Redis + BullMQ
- Strong built-in throttling to reduce ban risk
- Signed media URLs for secure previews
- Contact & group alias management
- Chat history browsing
- Optional n8n webhook forwarding
- Docker + nginx deployment ready
Internet
│
▼
nginx (TLS + Basic Auth)
│
▼
wa-api (Node.js / Express / Baileys)
│
├── Redis → durable outbound queue
├── auth/ → WhatsApp session
├── data/ → contacts, messages, automations
└── uploads/ → media files
- QR code login
- One-time device linking
- Session persisted to disk
- Send messages
- Manage contacts & groups
- Configure automations
- View chat history
Tip: Protect both with nginx Basic Auth in production.
wa-api/
├─ server.js
├─ package.json
├─ Dockerfile
├─ docker-compose.yml
├─ .env.example
├─ ui/
│ ├─ admin/
│ └─ pairing/
├─ nginx/
│ ├─ conf.d/
│ └─ auth/
└─ README.md
| Area | Protection |
|---|---|
| Pairing UI | nginx Basic Auth |
| Admin UI/API | x-admin-key |
| Integration API | x-api-key |
| Media Files | Signed URLs |
| Redis | Internal only |
- Docker
- Docker Compose
- Server with outbound internet access
- WhatsApp account (phone required)
git clone https://github.com/Naude555/watson.git
cd wa-apicp .env.example .envEdit:
WA_API_KEY=change_me
WA_ADMIN_KEY=change_me
MEDIA_SIGNING_SECRET=long_random_value
NODE_ENV=productionmkdir -p nginx/auth
docker run --rm -it -v "$PWD/nginx/auth:/auth" httpd:2.4-alpine sh -lc "apk add --no-cache apache2-utils && htpasswd -c /auth/.htpasswd admin"docker compose up -d --buildOpen:
http://<server>/pairing/ui
Scan QR in WhatsApp → Linked Devices.
| Variable | Description |
|---|---|
| PORT | Internal port (default 3000) |
| NODE_ENV | production |
| Variable | Description |
|---|---|
| WA_API_KEY | Integration API key |
| WA_ADMIN_KEY | Admin API/UI key |
| MEDIA_SIGNING_SECRET | Media URL signing |
| Variable | Description |
|---|---|
| REDIS_URL | Redis connection string |
| WA_QUEUE_NAME | Queue name |
WA_BASE_DELAY_MS=1200
WA_JITTER_MS=800
WA_PER_JID_GAP_MS=3000
WA_MAX_RETRIES=5
WA_RETRY_BACKOFF_MS=2000GET /health
x-api-key: <key>POST /send{
"to": "2782xxxxxxx",
"message": "Hello"
}Multipart:
- to
- image
- caption (optional)
{
"to": "2782xxxxxxx",
"imageUrl": "https://...",
"caption": "Hello"
}- Multipart or URL mode
Raw WhatsApp IDs are unreadable:
1203xxx@g.us
2782xxx@s.whatsapp.net
Aliases let you use human names instead.
Managed in Admin UI → Contacts / Groups.
Outbound messages are stored in Redis via BullMQ.
Benefits:
- Survives restarts
- Persistent retries
- No message loss
- Per-recipient throttling
Concurrency = 1 for account safety.
Enable:
N8N_WEBHOOK_URL=https://...
N8N_SHARED_SECRET=secretForwarded when rules allow.
Header:
x-watson-secret: <secret>
docker compose down
rm -rf ./auth/*
docker compose up -dRe-scan QR.
Back up:
- auth/
- data/
- uploads/
- Never expose Redis publicly
- Never commit
.envorauth/ - Rotate keys if leaked
- Use HTTPS
- Enable Basic Auth
- Secrets configured
- Redis volume enabled
- TLS enabled
- Basic Auth enabled
- Throttling configured
- Health endpoint OK
- WhatsApp paired
- Backups configured
MIT
This system is intentionally conservative:
- Human-like send rates
- Single-threaded queue
- Durability over speed
That’s how WhatsApp accounts survive in production.