Evolution API Skill
Expert assistance for building WhatsApp integrations and multi-channel messaging automation using Evolution API - an open-source platform for WhatsApp, chatbots, and business communication.
When to Use This Skill
This skill should be used when:
- •Building WhatsApp integrations and chatbots
- •Creating automated messaging systems
- •Integrating WhatsApp with business applications
- •Setting up multi-channel customer service platforms
- •Implementing chatbot flows with Typebot, Chatwoot, or Dify
- •Connecting WhatsApp to CRM systems
- •Building AI-powered conversational applications
- •Setting up webhook-based message handling
- •Implementing event-driven messaging architectures
- •Managing WhatsApp Business API connections
- •Integrating with OpenAI for intelligent responses
- •Setting up message queuing with RabbitMQ, Kafka, or SQS
- •Storing media files in S3 or MinIO
- •Questions about Evolution API configuration and deployment
- •Troubleshooting WhatsApp connection issues
Overview
What is Evolution API?
Evolution API is an open-source WhatsApp integration platform that:
- •Provides RESTful API for WhatsApp messaging
- •Supports both Baileys (free) and Official WhatsApp Business API
- •Integrates with multiple chatbot and automation platforms
- •Offers comprehensive webhook and event system
- •Enables business messaging automation
- •Completely free and self-hosted
Evolution from CodeChat:
"Originally built as a WhatsApp control API using the Baileys library based on CodeChat, the platform has evolved significantly."
Key Features
Messaging Capabilities:
- •Send and receive WhatsApp messages
- •Media support (images, videos, audio, documents)
- •Group management and operations
- •Contact management
- •Message history and search
- •Read receipts and status updates
Integration Ecosystem:
- •Typebot: Visual chatbot builder
- •Chatwoot: Customer service platform
- •Dify: AI agent management
- •OpenAI: AI-powered responses and audio transcription
- •Flowise: Low-code AI workflow builder
- •N8N: Workflow automation
Technical Features:
- •RESTful API with comprehensive endpoints
- •Webhook system for real-time events
- •WebSocket support for live updates
- •Message queue integration (RabbitMQ, Kafka, SQS)
- •Database persistence (PostgreSQL, MySQL)
- •Redis caching for performance
- •S3/MinIO for media storage
- •Docker deployment ready
Installation
Prerequisites
# Node.js 18+ or Docker node --version # v18.0.0 or higher # Database (optional but recommended) # PostgreSQL 12+ or MySQL 8+ # Redis (optional, for caching) # Redis 6+
Installation Methods
Option 1: Docker (Recommended)
# Clone the repository git clone https://github.com/EvolutionAPI/evolution-api.git cd evolution-api # Create environment file cp .env.example .env # Edit environment variables nano .env # Start with Docker Compose docker-compose up -d # Check logs docker-compose logs -f evolution-api
Docker Compose Example:
version: '3.8'
services:
evolution-api:
image: atendai/evolution-api:latest
container_name: evolution-api
ports:
- "8080:8080"
environment:
- SERVER_URL=https://your-domain.com
- DATABASE_ENABLED=true
- DATABASE_PROVIDER=postgresql
- DATABASE_CONNECTION_URI=postgresql://user:pass@postgres:5432/evolution
- AUTHENTICATION_API_KEY=your-secret-key-here
volumes:
- evolution_instances:/evolution/instances
restart: unless-stopped
postgres:
image: postgres:15
container_name: postgres
environment:
- POSTGRES_USER=evolution
- POSTGRES_PASSWORD=your-db-password
- POSTGRES_DB=evolution
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: redis:7
container_name: redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
restart: unless-stopped
volumes:
evolution_instances:
postgres_data:
redis_data:
Option 2: NVM (Node Version Manager)
# Install NVM curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash # Reload shell source ~/.bashrc # Install Node.js 18+ nvm install 18 nvm use 18 # Clone repository git clone https://github.com/EvolutionAPI/evolution-api.git cd evolution-api # Install dependencies npm install # Copy environment file cp .env.example .env # Edit configuration nano .env # Build npm run build # Start production npm run start:prod # Or development mode npm run start:dev
Option 3: PM2 (Process Manager)
# After NVM installation above # Install PM2 globally npm install -g pm2 # Start with PM2 pm2 start dist/src/main.js --name evolution-api # Save PM2 configuration pm2 save # Setup auto-restart on boot pm2 startup
Configuration
Essential Environment Variables
# Server Configuration SERVER_TYPE=http # or https SERVER_PORT=8080 SERVER_URL=https://your-domain.com # For webhooks # Authentication AUTHENTICATION_API_KEY=your-secret-api-key-here AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true # Database (Recommended for production) DATABASE_ENABLED=true DATABASE_PROVIDER=postgresql # or mysql DATABASE_CONNECTION_URI=postgresql://user:pass@localhost:5432/evolution?schema=public DATABASE_CONNECTION_CLIENT_NAME=evolution_instance # Data Persistence DATABASE_SAVE_DATA_INSTANCE=true DATABASE_SAVE_DATA_NEW_MESSAGE=true DATABASE_SAVE_MESSAGE_UPDATE=true DATABASE_SAVE_DATA_CONTACTS=true DATABASE_SAVE_DATA_CHATS=true # Redis Cache (Optional but recommended) CACHE_REDIS_ENABLED=true CACHE_REDIS_URI=redis://localhost:6379/6 CACHE_REDIS_PREFIX_KEY=evolution # CORS CORS_ORIGIN=* CORS_METHODS=GET,POST,PUT,DELETE CORS_CREDENTIALS=true # Logging LOG_LEVEL=INFO # ERROR, WARN, DEBUG, INFO, LOG, VERBOSE LOG_COLOR=true LOG_BAILEYS=error # fatal, error, warn, info, debug, trace # Instance Management DEL_INSTANCE=false # Auto-delete after X minutes (false = never) # Language LANGUAGE=en # or pt, es, etc.
WhatsApp Configuration
# Session Configuration CONFIG_SESSION_PHONE_CLIENT=Evolution API CONFIG_SESSION_PHONE_NAME=Chrome # QR Code Settings QRCODE_LIMIT=30 # Seconds before regeneration QRCODE_COLOR=#175197 # QR code color # WhatsApp Business API (Official) WA_BUSINESS_TOKEN_WEBHOOK=evolution WA_BUSINESS_URL=https://graph.facebook.com WA_BUSINESS_VERSION=v20.0 WA_BUSINESS_LANGUAGE=en_US
Webhook Configuration
# Global Webhook WEBHOOK_GLOBAL_ENABLED=true WEBHOOK_GLOBAL_URL=https://your-webhook-endpoint.com/webhook WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=true # Event-specific webhooks WEBHOOK_EVENTS_APPLICATION_STARTUP=true WEBHOOK_EVENTS_QRCODE_UPDATED=true WEBHOOK_EVENTS_MESSAGES_SET=true WEBHOOK_EVENTS_MESSAGES_UPSERT=true WEBHOOK_EVENTS_MESSAGES_UPDATE=true WEBHOOK_EVENTS_MESSAGES_DELETE=true WEBHOOK_EVENTS_SEND_MESSAGE=true WEBHOOK_EVENTS_CONTACTS_SET=true WEBHOOK_EVENTS_CONTACTS_UPSERT=true WEBHOOK_EVENTS_CONTACTS_UPDATE=true WEBHOOK_EVENTS_PRESENCE_UPDATE=true WEBHOOK_EVENTS_CHATS_SET=true WEBHOOK_EVENTS_CHATS_UPSERT=true WEBHOOK_EVENTS_CHATS_UPDATE=true WEBHOOK_EVENTS_CHATS_DELETE=true WEBHOOK_EVENTS_GROUPS_UPSERT=true WEBHOOK_EVENTS_GROUPS_UPDATE=true WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE=true WEBHOOK_EVENTS_CONNECTION_UPDATE=true WEBHOOK_EVENTS_CALL=true WEBHOOK_EVENTS_TYPEBOT_START=true WEBHOOK_EVENTS_TYPEBOT_CHANGE_STATUS=true WEBHOOK_EVENTS_ERRORS=true WEBHOOK_EVENTS_ERRORS_WEBHOOK=true
Integration Configurations
Typebot:
TYPEBOT_API_VERSION=latest # or specific version
Chatwoot:
CHATWOOT_ENABLED=true CHATWOOT_MESSAGE_READ=true CHATWOOT_MESSAGE_DELETE=true CHATWOOT_IMPORT_DATABASE_CONNECTION_URI=postgresql://... CHATWOOT_IMPORT_PLACEHOLDER_MEDIA_MESSAGE=true
OpenAI:
OPENAI_ENABLED=true
Dify:
DIFY_ENABLED=true
RabbitMQ:
RABBITMQ_ENABLED=true RABBITMQ_URI=amqp://user:pass@localhost:5672 RABBITMQ_EXCHANGE_NAME=evolution_exchange RABBITMQ_GLOBAL_ENABLED=true
AWS SQS:
SQS_ENABLED=true SQS_ACCESS_KEY_ID=your-access-key SQS_SECRET_ACCESS_KEY=your-secret-key SQS_ACCOUNT_ID=123456789 SQS_REGION=us-east-1
S3/MinIO Storage:
S3_ENABLED=true S3_ACCESS_KEY=your-access-key S3_SECRET_KEY=your-secret-key S3_BUCKET=evolution S3_ENDPOINT=s3.amazonaws.com # or minio endpoint S3_PORT=443 S3_USE_SSL=true
WebSocket:
WEBSOCKET_ENABLED=true WEBSOCKET_GLOBAL_EVENTS=false
Quick Start
1. Create Instance
# Using cURL
curl -X POST https://your-domain.com/instance/create \
-H "apikey: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"instanceName": "my-whatsapp-bot",
"qrcode": true,
"integration": "WHATSAPP-BAILEYS"
}'
# Response includes QR code
{
"instance": {
"instanceName": "my-whatsapp-bot",
"status": "created"
},
"qrcode": {
"code": "data:image/png;base64,...",
"base64": "..."
}
}
2. Connect WhatsApp
Scan the QR code with WhatsApp on your phone:
- •Open WhatsApp
- •Go to Settings > Linked Devices
- •Click "Link a Device"
- •Scan the QR code from the API response
3. Check Connection Status
curl -X GET https://your-domain.com/instance/connectionState/my-whatsapp-bot \
-H "apikey: your-api-key"
# Response
{
"instance": {
"instanceName": "my-whatsapp-bot",
"state": "open"
}
}
4. Send Message
curl -X POST https://your-domain.com/message/sendText/my-whatsapp-bot \
-H "apikey: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"number": "5511999999999",
"text": "Hello from Evolution API!"
}'
API Endpoints
Instance Management
# Create instance
POST /instance/create
{
"instanceName": "bot-name",
"qrcode": true,
"integration": "WHATSAPP-BAILEYS" # or WHATSAPP-BUSINESS
}
# List instances
GET /instance/fetchInstances
# Get instance info
GET /instance/connectionState/{instanceName}
# Restart instance
PUT /instance/restart/{instanceName}
# Logout instance
DELETE /instance/logout/{instanceName}
# Delete instance
DELETE /instance/delete/{instanceName}
Messaging
Text Messages:
POST /message/sendText/{instanceName}
{
"number": "5511999999999",
"text": "Your message here"
}
Media Messages:
# Image
POST /message/sendMedia/{instanceName}
{
"number": "5511999999999",
"mediatype": "image",
"media": "https://example.com/image.jpg", # or base64
"caption": "Image caption"
}
# Video
POST /message/sendMedia/{instanceName}
{
"number": "5511999999999",
"mediatype": "video",
"media": "https://example.com/video.mp4",
"caption": "Video caption"
}
# Audio
POST /message/sendWhatsAppAudio/{instanceName}
{
"number": "5511999999999",
"audio": "https://example.com/audio.mp3" # or base64
}
# Document
POST /message/sendMedia/{instanceName}
{
"number": "5511999999999",
"mediatype": "document",
"media": "https://example.com/file.pdf",
"fileName": "document.pdf"
}
Advanced Messages:
# Location
POST /message/sendLocation/{instanceName}
{
"number": "5511999999999",
"latitude": "-23.550520",
"longitude": "-46.633308",
"name": "Location Name",
"address": "Address details"
}
# Contact
POST /message/sendContact/{instanceName}
{
"number": "5511999999999",
"contact": [{
"fullName": "John Doe",
"wuid": "5511888888888",
"phoneNumber": "+55 11 98888-8888"
}]
}
# List Message (Interactive)
POST /message/sendList/{instanceName}
{
"number": "5511999999999",
"title": "Choose an option",
"description": "Select one option below",
"buttonText": "Options",
"footerText": "Footer text",
"sections": [{
"title": "Section 1",
"rows": [{
"title": "Option 1",
"description": "Description 1",
"rowId": "opt1"
}]
}]
}
# Button Message
POST /message/sendButtons/{instanceName}
{
"number": "5511999999999",
"title": "Button Message",
"description": "Choose an action",
"buttons": [{
"type": "replyButton",
"displayText": "Button 1",
"id": "btn1"
}],
"footerText": "Footer"
}
Groups
# Create group
POST /group/create/{instanceName}
{
"subject": "Group Name",
"participants": ["5511999999999", "5511888888888"]
}
# Update group info
PUT /group/updateGroupPicture/{instanceName}
{
"groupJid": "groupid@g.us",
"image": "base64-image-data"
}
# Add participants
POST /group/updateParticipant/{instanceName}
{
"groupJid": "groupid@g.us",
"action": "add", # or remove, promote, demote
"participants": ["5511999999999"]
}
# Leave group
DELETE /group/leaveGroup/{instanceName}
{
"groupJid": "groupid@g.us"
}
Contacts & Profile
# Get profile picture
GET /chat/profilePic/{instanceName}?number=5511999999999
# Get contacts
GET /chat/findContacts/{instanceName}?id=5511999999999
# Update profile name
PUT /chat/updateProfileName/{instanceName}
{
"name": "My Bot Name"
}
# Update profile status
PUT /chat/updateProfileStatus/{instanceName}
{
"status": "Available 24/7"
}
# Update profile picture
PUT /chat/updateProfilePicture/{instanceName}
{
"picture": "base64-image-data"
}
Webhooks
# Set instance webhook
POST /webhook/set/{instanceName}
{
"url": "https://your-webhook.com/endpoint",
"webhook_by_events": true,
"webhook_base64": false,
"events": [
"QRCODE_UPDATED",
"MESSAGES_UPSERT",
"MESSAGES_UPDATE",
"SEND_MESSAGE",
"CONNECTION_UPDATE"
]
}
# Get webhook info
GET /webhook/find/{instanceName}
Integration Examples
Typebot Integration
# Set Typebot on instance
POST /typebot/set/{instanceName}
{
"enabled": true,
"url": "https://typebot.io",
"typebot": "typebot-flow-id",
"expire": 20, # Minutes of inactivity
"keywordFinish": "exit",
"delayMessage": 1000,
"unknownMessage": "I didn't understand",
"listeningFromMe": false
}
# Start Typebot session
POST /typebot/start/{instanceName}
{
"url": "https://typebot.io",
"typebot": "flow-id",
"remoteJid": "5511999999999@s.whatsapp.net",
"startSession": true,
"variables": [{
"name": "userName",
"value": "John"
}]
}
# Change Typebot status
POST /typebot/changeStatus/{instanceName}
{
"remoteJid": "5511999999999@s.whatsapp.net",
"status": "paused" # or closed
}
Chatwoot Integration
# Enable Chatwoot
POST /chatwoot/set/{instanceName}
{
"enabled": true,
"accountId": "123",
"token": "chatwoot-api-token",
"url": "https://app.chatwoot.com",
"signMsg": true,
"reopenConversation": true,
"conversationPending": false
}
OpenAI Integration
# Set OpenAI
POST /openai/set/{instanceName}
{
"enabled": true,
"apiKey": "sk-...",
"model": "gpt-4o",
"maxTokens": 2000,
"temperature": 0.7,
"systemMessages": [{
"role": "system",
"content": "You are a helpful assistant."
}],
"assistantMessages": [{
"role": "assistant",
"content": "How can I help you?"
}]
}
Dify Integration
# Set Dify
POST /dify/set/{instanceName}
{
"enabled": true,
"apiUrl": "https://api.dify.ai/v1",
"apiKey": "app-...",
"botType": "chatbot", # or agent, workflow
"expire": 20,
"keywordFinish": "exit"
}
Webhook Handling
Webhook Structure
// Example webhook payload
{
"event": "messages.upsert",
"instance": "my-whatsapp-bot",
"data": {
"key": {
"remoteJid": "5511999999999@s.whatsapp.net",
"fromMe": false,
"id": "BAE5F4...",
"participant": null
},
"pushName": "John Doe",
"message": {
"conversation": "Hello, how are you?"
},
"messageType": "conversation",
"messageTimestamp": 1234567890,
"instanceId": "instance-uuid",
"source": "android"
},
"destination": "https://your-webhook.com/endpoint",
"date_time": "2024-01-01T12:00:00.000Z",
"server_url": "https://your-evolution-api.com",
"apikey": "your-api-key"
}
Node.js Webhook Handler
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook', async (req, res) => {
const { event, instance, data } = req.body;
console.log(`Received event: ${event} from instance: ${instance}`);
// Handle different events
switch (event) {
case 'messages.upsert':
// New message received
const message = data.message?.conversation ||
data.message?.extendedTextMessage?.text || '';
const from = data.key.remoteJid;
const fromMe = data.key.fromMe;
if (!fromMe && message) {
console.log(`Message from ${from}: ${message}`);
// Process message and send response
await sendResponse(instance, from, message);
}
break;
case 'connection.update':
// Connection status changed
console.log('Connection status:', data);
break;
case 'qrcode.updated':
// New QR code generated
console.log('QR Code updated:', data.qrcode);
break;
default:
console.log('Unhandled event:', event);
}
// Always respond 200 OK
res.sendStatus(200);
});
async function sendResponse(instance, to, originalMessage) {
const response = await fetch(`https://your-api.com/message/sendText/${instance}`, {
method: 'POST',
headers: {
'apikey': 'your-api-key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
number: to.replace('@s.whatsapp.net', ''),
text: `You said: ${originalMessage}`
})
});
return response.json();
}
app.listen(3000, () => {
console.log('Webhook server running on port 3000');
});
Python Webhook Handler
from flask import Flask, request
import requests
app = Flask(__name__)
API_URL = "https://your-evolution-api.com"
API_KEY = "your-api-key"
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.json
event = data.get('event')
instance = data.get('instance')
event_data = data.get('data')
print(f"Received event: {event} from instance: {instance}")
if event == 'messages.upsert':
handle_message(instance, event_data)
elif event == 'connection.update':
handle_connection(event_data)
elif event == 'qrcode.updated':
handle_qrcode(event_data)
return '', 200
def handle_message(instance, data):
from_me = data['key'].get('fromMe', False)
if from_me:
return
message = (data.get('message', {}).get('conversation') or
data.get('message', {}).get('extendedTextMessage', {}).get('text') or '')
remote_jid = data['key']['remoteJid']
number = remote_jid.replace('@s.whatsapp.net', '')
print(f"Message from {number}: {message}")
# Send response
send_message(instance, number, f"You said: {message}")
def send_message(instance, number, text):
url = f"{API_URL}/message/sendText/{instance}"
headers = {
'apikey': API_KEY,
'Content-Type': 'application/json'
}
payload = {
'number': number,
'text': text
}
response = requests.post(url, json=payload, headers=headers)
return response.json()
def handle_connection(data):
print(f"Connection update: {data}")
def handle_qrcode(data):
print(f"QR Code updated")
if __name__ == '__main__':
app.run(port=3000)
Advanced Use Cases
1. AI-Powered Customer Service Bot
const OpenAI = require('openai');
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
async function handleCustomerMessage(instance, from, message) {
// Get conversation history from database
const history = await getConversationHistory(from);
// Get AI response
const completion = await openai.chat.completions.create({
model: "gpt-4o",
messages: [
{ role: "system", content: "You are a helpful customer service agent." },
...history,
{ role: "user", content: message }
]
});
const aiResponse = completion.choices[0].message.content;
// Save to history
await saveToHistory(from, message, aiResponse);
// Send response
await sendMessage(instance, from, aiResponse);
}
2. Group Management Bot
async function handleGroupCommand(instance, groupJid, command, sender) {
const isAdmin = await checkIfAdmin(instance, groupJid, sender);
if (!isAdmin) {
await sendMessage(instance, groupJid, "Only admins can use this command");
return;
}
switch (command) {
case '/welcome':
await setWelcomeMessage(groupJid);
break;
case '/rules':
await sendGroupRules(instance, groupJid);
break;
case '/ban':
const userToRemove = extractUserFromCommand(command);
await removeParticipant(instance, groupJid, userToRemove);
break;
}
}
3. Broadcast System
async function sendBroadcast(instance, recipients, message) {
const results = [];
for (const recipient of recipients) {
try {
await sendMessage(instance, recipient, message);
results.push({ recipient, status: 'sent' });
// Delay to avoid rate limiting
await delay(1000);
} catch (error) {
results.push({ recipient, status: 'failed', error: error.message });
}
}
return results;
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
4. Media Downloader Bot
async function handleMediaMessage(instance, data) {
const messageType = data.messageType;
if (['imageMessage', 'videoMessage', 'documentMessage'].includes(messageType)) {
// Download media
const media = data.message[messageType];
const buffer = await downloadMedia(instance, data.key.id);
// Upload to S3
const s3Url = await uploadToS3(buffer, media.mimetype);
// Save to database
await saveMediaReference({
messageId: data.key.id,
type: messageType,
url: s3Url,
from: data.key.remoteJid,
timestamp: data.messageTimestamp
});
}
}
Production Best Practices
1. Security
# Use strong API key AUTHENTICATION_API_KEY=$(openssl rand -hex 32) # Enable HTTPS SERVER_TYPE=https # Restrict CORS CORS_ORIGIN=https://your-frontend.com CORS_CREDENTIALS=true # Use environment-specific configs # .env.production, .env.staging, .env.development
2. High Availability
# docker-compose.yml with replicas
services:
evolution-api:
image: atendai/evolution-api:latest
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
max_attempts: 3
environment:
- DATABASE_ENABLED=true
- CACHE_REDIS_ENABLED=true
# Load balancer
nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- evolution-api
3. Monitoring
# Enable detailed logging LOG_LEVEL=DEBUG LOG_COLOR=true LOG_BAILEYS=info # Use external monitoring # - Prometheus for metrics # - Grafana for dashboards # - Sentry for error tracking # Health check endpoint curl https://your-api.com/health
4. Backup Strategy
# Database backups pg_dump -h localhost -U evolution evolution > backup_$(date +%Y%m%d).sql # Instance data backup tar -czf instances_backup_$(date +%Y%m%d).tar.gz /evolution/instances/ # Automated backups with cron 0 2 * * * /scripts/backup.sh
5. Rate Limiting
// Implement rate limiting in webhook handler
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests, please try again later.'
});
app.use('/webhook', limiter);
Troubleshooting
Common Issues
QR Code Not Generating
# Check instance status curl -X GET https://your-api.com/instance/connectionState/instance-name \ -H "apikey: your-api-key" # Restart instance curl -X PUT https://your-api.com/instance/restart/instance-name \ -H "apikey: your-api-key" # Check logs docker-compose logs -f evolution-api
Messages Not Sending
# Verify connection
GET /instance/connectionState/{instanceName}
# Check if number is valid
# Format: Country code + number (no +, no spaces)
# Example: 5511999999999
# Verify API key
curl -X GET https://your-api.com/instance/fetchInstances \
-H "apikey: your-api-key"
Webhook Not Receiving Events
# Verify webhook configuration
GET /webhook/find/{instanceName}
# Test webhook endpoint
curl -X POST https://your-webhook.com/endpoint \
-H "Content-Type: application/json" \
-d '{"test": "data"}'
# Check webhook URL is publicly accessible
# Use ngrok for local development:
ngrok http 3000
Database Connection Errors
# Test database connection psql "postgresql://user:pass@localhost:5432/evolution" # Check environment variables echo $DATABASE_CONNECTION_URI # Verify database exists psql -l | grep evolution # Run migrations if needed npm run migration:run
Instance Disconnects Frequently
# Enable keep-alive # Check mobile connection # Verify phone battery saver is off # Check WhatsApp version is up to date # Increase session timeout CONFIG_SESSION_PHONE_CLIENT=Evolution API QRCODE_LIMIT=60 # Increase timeout
Performance Optimization
1. Enable Caching
# Redis cache CACHE_REDIS_ENABLED=true CACHE_REDIS_URI=redis://localhost:6379/6 CACHE_REDIS_SAVE_INSTANCES=true
2. Database Optimization
# Index frequently queried fields CREATE INDEX idx_messages_instance ON messages(instanceId); CREATE INDEX idx_messages_jid ON messages(remoteJid); CREATE INDEX idx_messages_timestamp ON messages(messageTimestamp); # Partition large tables # Clean old messages periodically DELETE FROM messages WHERE messageTimestamp < NOW() - INTERVAL '90 days';
3. Media Storage
# Use S3 for media files S3_ENABLED=true S3_BUCKET=evolution-media # Don't save media in database DATABASE_SAVE_DATA_NEW_MESSAGE=false
4. Message Queue
# Use RabbitMQ for high volume RABBITMQ_ENABLED=true RABBITMQ_URI=amqp://localhost:5672 # Or SQS for AWS deployments SQS_ENABLED=true
Migration Guide
From WhatsApp Web.js
// WhatsApp Web.js
const { Client } = require('whatsapp-web.js');
const client = new Client();
client.on('message', msg => {
if (msg.body === 'ping') {
msg.reply('pong');
}
});
client.initialize();
// Evolution API equivalent
app.post('/webhook', (req, res) => {
const { event, data } = req.body;
if (event === 'messages.upsert') {
const message = data.message?.conversation;
if (message === 'ping') {
sendMessage(data.instance, data.key.remoteJid, 'pong');
}
}
res.sendStatus(200);
});
From Baileys Directly
Evolution API is built on Baileys, so migration is straightforward. Instead of managing Baileys directly, use Evolution API's REST endpoints.
API Reference Summary
Base URL Structure
https://your-domain.com/{endpoint}/{instanceName}
Authentication
# All requests require API key header apikey: your-api-key
Main Endpoint Categories
- •
/instance/*- Instance management - •
/message/*- Send messages - •
/chat/*- Chat and contact operations - •
/group/*- Group management - •
/webhook/*- Webhook configuration - •
/typebot/*- Typebot integration - •
/chatwoot/*- Chatwoot integration - •
/openai/*- OpenAI integration - •
/dify/*- Dify integration
Resources
Official Links
- •Documentation: https://doc.evolution-api.com/
- •GitHub: https://github.com/EvolutionAPI/evolution-api
- •Website: https://evolution-api.com
Community
- •GitHub Discussions: https://github.com/EvolutionAPI/evolution-api/discussions
- •Issues: https://github.com/EvolutionAPI/evolution-api/issues
Integration Partners
- •Typebot: https://typebot.io
- •Chatwoot: https://chatwoot.com
- •Dify: https://dify.ai
- •N8N: https://n8n.io
- •Flowise: https://flowiseai.com
License
Evolution API is licensed under Apache License 2.0 with specific requirements regarding branding notifications in implementations.
Note: This skill provides comprehensive guidance for building WhatsApp integrations with Evolution API. Always ensure compliance with WhatsApp's Terms of Service and local regulations when deploying messaging solutions.