WhatsApp Flow Server
2.4K
Production-ready Node.js server for WhatsApp Flows with automated CI/CD, multi-arch Docker support, and DDD architecture
Featuresβ β’ Quick Startβ β’ Documentationβ β’ Architectureβ β’ Contributingβ
WhatsApp Flow Server is a robust, production-ready TypeScript server that implements the WhatsApp Flows APIβ using Domain-Driven Design (DDD) principles. It provides a complete solution for handling WhatsApp Flow interactions with built-in encryption, webhook processing, and comprehensive CI/CD automation.
WhatsApp Flows enable rich, interactive experiences within WhatsApp, but implementing them requires:
This server solves all these challenges with:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β WhatsApp Platform β
ββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ¬ββββββββββββββ
β β
β Encrypted Flow Data β Webhook Events
β (RSA-2048 + AES-128-GCM) β (nfm_reply)
βΌ βΌ
βββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββ
β Flow Endpoint (Data API) β β Webhook Endpoint β
β POST /flows/endpoint/:id β β POST /webhooks/whatsappβ
β β β β
β - Decrypt request β β - Validate signature β
β - Process action β β - Parse response_json β
β - Return encrypted data β β - Forward to callback β
β - < 3s response time β β - Store in database β
ββββββββββββββββ¬βββββββββββββββ ββββββββββββ¬ββββββββββββββββ
β β
β β
βΌ βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Application Layer β
β β
β ββββββββββββββββββββββββ βββββββββββββββββββββββββββ β
β β HandleFlowRequest β β ProcessWebhook β β
β β UseCase β β UseCase β β
β ββββββββββββ¬ββββββββββββ βββββββββββββ¬ββββββββββββββ β
β β β β
β βΌ βΌ β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Domain Layer (Business Logic) β β
β β β β
β β β’ FlowEngine - Navigation and data exchange β β
β β β’ Flow - Immutable Flow templates β β
β β β’ FlowSession - User session tracking β β
β β β’ FlowResponse - Completed Flow data β β
β β β’ EncryptionService - RSA/AES with IV flip β β
β ββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ β
β β β
βββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Infrastructure Layer β
β β
β ββββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββ β
β β PostgreSQL β β Express HTTP β β Axios HTTP β β
β β Repositories β β Server β β Client β β
β ββββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββ β
β β
β Database Tables: β
β β’ flows - Flow JSON templates β
β β’ flow_sessions - Active/completed sessions β
β β’ flow_responses - Completed Flow data β
β β’ webhook_events - Webhook audit trail β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
User WhatsApp Flow Server Database Your System
β β β β β
β Click Flow Button β β β β
ββββββββββββββββββββ>β β β β
β β β β β
β β POST /flows/endpoint (INIT) β β
β ββββββββββββββββββββ>β β β
β β β Create Session β β
β β βββββββββββββββββ>β β
β β β Return INIT β β
β β<ββββββββββββββββββββ€ β β
β β β β β
β Display Screen 1 β β β β
β<ββββββββββββββββββββ€ β β β
β β β β β
β Fill & Submit β β β β
ββββββββββββββββββββ>β β β β
β β POST /flows/endpoint (data_exchange) β β
β ββββββββββββββββββββ>β β β
β β β Update Session β β
β β βββββββββββββββββ>β β
β β β Return Screen 2 β β
β β<ββββββββββββββββββββ€ β β
β β β β β
β Display Screen 2 β β β β
β<ββββββββββββββββββββ€ β β β
β β β β β
β Complete Flow β β β β
ββββββββββββββββββββ>β β β β
β β POST /flows/endpoint (complete) β β
β ββββββββββββββββββββ>β β β
β β β Mark Complete β β
β β βββββββββββββββββ>β β
β β β β β
β β POST /webhooks/whatsapp (nfm_reply) β β
β ββββββββββββββββββββ>β β β
β β β Store Response β β
β β βββββββββββββββββ>β β
β β β Forward Data β β
β β βββββββββββββββββββββββββββββββββ>β
β β β β β
β "Thank you!" β β β β
β<ββββββββββββββββββββ€ β β β
WhatsApp Request Server Response
β β
β Encrypted with: β Encrypted with:
β β’ AES key encrypted by RSA β β’ FLIPPED IV β οΈ
β β’ Normal IV β β’ Same AES key
β β
βΌ βΌ
ββββββββββββββββββ ββββββββββββββββββ
β Decrypt AES Keyβ β Flip IV Buffer β
β with RSA β β (reverse bytes)β
βββββββββ¬βββββββββ ββββββββββ¬ββββββββ
β β
βΌ βΌ
ββββββββββββββββββ ββββββββββββββββββ
β Decrypt Payloadβ β Encrypt Payloadβ
β with AES β β with AES β
β (normal IV) β β (flipped IV) β
βββββββββ¬βββββββββ ββββββββββ¬ββββββββ
β β
βΌ βΌ
Flow Data Encrypted Response
# 1. Clone the repository
git clone https://github.com/guilhermejansen/whatsapp-flows-server.git
cd whatsapp-flows-server
# 2. Configure environment
cp .env.docker.example .env
nano .env # Edit with your credentials
# 3. Start services
docker-compose up -d
# 4. Generate encryption keys
docker-compose exec app npm run generate-keys
# Copy output to .env
# 5. Restart application
docker-compose restart app
# 6. Register public key with Meta
docker-compose exec app npm run register-key
# 7. Verify health
curl http://localhost:3000/health
Your server is now running! π
Configure WhatsApp Manager:
https://your-domain.com/flows/endpoint/csat-feedbackhttps://your-domain.com/webhooks/whatsapp# 1. Clone and install
git clone https://github.com/guilhermejansen/whatsapp-flows-server.git
cd whatsapp-flows-server
npm install
# 2. Setup PostgreSQL
createdb whatsapp_flows
npm run migrate
# 3. Generate keys
npm run generate-keys
# Copy output to .env
# 4. Configure environment
cp .env.example .env
nano .env # Edit with your credentials
# 5. Register public key
npm run register-key
# 6. Start development server
npm run dev
Pre-built images available for AMD64 (Intel/AMD) and ARM64 (Apple Silicon, AWS Graviton):
# Pull latest version
docker pull setupautomatizado/whatsapp-flows-server:latest
# Or specific version
docker pull setupautomatizado/whatsapp-flows-server:1.0.0
# Create directory
mkdir -p ~/whatsapp-flows-server-production
cd ~/whatsapp-flows-server-production
# Download compose file
curl -O https://raw.githubusercontent.com/guilhermejansen/whatsapp-flows-server/main/docker-compose.yml
# Configure environment
curl -O https://raw.githubusercontent.com/guilhermejansen/whatsapp-flows-server/main/.env.docker.example
cp .env.docker.example .env
nano .env
# Install Nginx + Certbot
sudo apt update
sudo apt install nginx certbot python3-certbot-nginx -y
# Configure Nginx
sudo nano /etc/nginx/sites-available/whatsapp-flows-server
Nginx Configuration:
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WhatsApp requires < 3s response
proxy_connect_timeout 2s;
proxy_send_timeout 2s;
proxy_read_timeout 2s;
}
}
# Enable site
sudo ln -s /etc/nginx/sites-available/whatsapp-flows-server /etc/nginx/sites-enabled/
sudo nginx -t
# Get SSL certificate
sudo certbot --nginx -d your-domain.com
# Restart Nginx
sudo systemctl restart nginx
# Start services
docker-compose up -d
# Generate keys
docker-compose exec app npm run generate-keys
# Add keys to .env
# Restart
docker-compose restart app
# Register public key
docker-compose exec app npm run register-key
# Verify
curl https://your-domain.com/health
# View logs
docker-compose logs -f app
# Shell access
docker-compose exec app sh
# Database access
docker-compose exec postgres psql -U whatsapp_flow -d whatsapp_flows
# Run migrations manually
docker-compose exec app npm run migrate
# Backup database
docker-compose exec postgres pg_dump -U whatsapp_flow whatsapp_flows > backup.sql
# Stop services
docker-compose down
| Variable | Description | Required | Example |
|---|---|---|---|
NODE_ENV | Environment mode | β | production |
PORT | Server port | β | 3000 |
DATABASE_URL | PostgreSQL connection string | β | postgresql://user:pass@localhost:5432/db |
PRIVATE_KEY | RSA private key (PEM format) | β | -----BEGIN RSA PRIVATE KEY-----\n... |
PUBLIC_KEY | RSA public key (PEM format) | β | -----BEGIN PUBLIC KEY-----\n... |
META_APP_SECRET | Meta app secret | β | your_app_secret |
META_VERIFY_TOKEN | Webhook verify token | β | your_verify_token |
META_ACCESS_TOKEN | WhatsApp API access token | β | EAAB... |
CALLBACK_WEBHOOK_URL | Your callback URL for completed flows | β | https://yourapi.com/webhook |
DEFAULT_FLOW_NAME | Default flow when not specified | β οΈ | csat-feedback |
FLOW_ENDPOINT_TIMEOUT | Max response time (< 3000ms) | β οΈ | 2500 |
CORS_ORIGINS | Allowed CORS origins | β οΈ | https://app.com |
API_TOKEN | API authentication token | β οΈ | Generated with openssl rand -hex 32 |
Legend: β Required | β οΈ Recommended
# Generate RSA-2048 key pair
npm run generate-keys
# Validate keys
npm run validate-keys
# Register public key with Meta
npm run register-key
This server implements WhatsApp's mandatory IV flip pattern for encryption:
// Decryption (incoming from WhatsApp) - Normal IV
const iv = Buffer.from(initialVector, 'base64');
const decipher = crypto.createDecipheriv('aes-128-gcm', aesKey, iv);
// Encryption (outgoing to WhatsApp) - FLIPPED IV β οΈ
const iv = Buffer.from(initialVector, 'base64');
const flippedIV = Buffer.from(iv).reverse(); // Must reverse!
const cipher = crypto.createCipheriv('aes-128-gcm', aesKey, flippedIV);
Critical: If IV is not flipped, WhatsApp returns error 421.
See SECURITY.mdβ for vulnerability reporting.
Endpoint: POST /flows/endpoint/:flowName
Handles encrypted interactions during Flow execution.
Actions:
ping - Health checkINIT - Initialize Flow sessiondata_exchange - Process user input and navigatenavigate - Explicit screen navigationcomplete - Mark Flow as completedHeaders:
Content-Type: application/json
Example Request (INIT):
{
"version": "3.0",
"action": "INIT",
"flow_token": "unique_token_123",
"encrypted_flow_data": "...",
"encrypted_aes_key": "...",
"initial_vector": "..."
}
Response: Encrypted Flow data with next screen
Endpoint: POST /webhooks/whatsapp
Receives nfm_reply events when user completes Flow.
Headers:
Content-Type: application/json
X-Hub-Signature-256: sha256=...
Example Payload:
{
"entry": [{
"changes": [{
"value": {
"messages": [{
"type": "interactive",
"interactive": {
"type": "nfm_reply",
"nfm_reply": {
"response_json": "{\"flow_token\":\"...\",\"data\":...}",
"name": "flow_name"
}
}
}]
}
}]
}]
}
Important: response_json is a string, must be parsed with JSON.parse().
Endpoint: GET /health
Response:
{
"status": "ok",
"timestamp": "2025-01-27T12:00:00.000Z",
"version": "1.0.0",
"uptime": 3600,
"database": "connected"
}
Interactive API docs available at /docs when server is running.
whatsapp-flow/
βββ src/
β βββ domain/ # Business entities and rules
β β βββ flows/ # Flow, FlowSession entities
β β βββ encryption/ # Encryption services
β β βββ webhooks/ # Webhook events
β βββ application/ # Use cases (business logic)
β β βββ dtos/ # Da
Content type
Image
Digest
sha256:b2006710aβ¦
Size
85 MB
Last updated
11 months ago
docker pull setupautomatizado/whatsapp-flows-server