Como instalar a Evolution API em uma VPS
A Evolution API expõe o WhatsApp como uma API REST: você envia mensagem por requisição HTTP e recebe as respostas em webhooks. É o que costuma ligar um fluxo do n8n, um bot do Typebot ou um sistema próprio à conversa do cliente.
Este guia sobe a API com PostgreSQL e Redis, atrás de HTTPS, e conecta a primeira instância pelo QR Code.
Antes de começar
- VPS com Ubuntu 22.04 ou 24.04, Docker instalado (veja o guia de Docker).
- Subdomínio apontado para o IP da VPS, por exemplo
api.seudominio.com.br. - 2 GB de RAM para poucas instâncias. Cada instância conectada mantém uma sessão ativa em memória, então planeje 4 GB a partir de três ou quatro números.
Entenda o que você está subindo
A Evolution API é um projeto de código aberto que conversa com o WhatsApp Web. Ela não é um produto oficial da Meta: o uso está sujeito às regras da plataforma, e automação agressiva pode levar ao bloqueio do número.
Para comunicação transacional em volume com garantia de entrega, o caminho oficial é a API Cloud da Meta. Para atendimento, automações internas e integrações de pequeno e médio porte, a Evolution resolve bem.
Use um número dedicado, não o seu pessoal. Se houver bloqueio, você perde aquele número — e recuperar conversa antiga não é possível.
Prepare a pasta e as senhas
A chave da API é o que protege tudo: quem a tiver envia mensagens em seu nome. Gere uma longa e guarde num gerenciador.
mkdir -p /opt/evolution && cd /opt/evolution
cat > .env <<EOF
DOMINIO=api.seudominio.com.br
[email protected]
AUTHENTICATION_API_KEY=$(openssl rand -hex 32)
POSTGRES_PASSWORD=$(openssl rand -hex 24)
EOF
chmod 600 .env
cat .env
Escreva o docker-compose.yml
Quatro serviços: a API, o PostgreSQL que guarda instâncias e mensagens, o Redis para cache de sessão e o Caddy como proxy com certificado automático.
cat > /opt/evolution/docker-compose.yml <<'EOF'
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: evolution
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: evolution
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U evolution"]
interval: 10s
retries: 5
redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
- redis_data:/data
evolution:
image: atendai/evolution-api:v2.1.1
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
SERVER_URL: https://${DOMINIO}
AUTHENTICATION_API_KEY: ${AUTHENTICATION_API_KEY}
DATABASE_ENABLED: "true"
DATABASE_PROVIDER: postgresql
DATABASE_CONNECTION_URI: postgresql://evolution:${POSTGRES_PASSWORD}@postgres:5432/evolution
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"
CACHE_REDIS_ENABLED: "true"
CACHE_REDIS_URI: redis://redis:6379/6
CACHE_REDIS_PREFIX_KEY: evolution
CACHE_LOCAL_ENABLED: "false"
LOG_LEVEL: ERROR
TZ: America/Sao_Paulo
volumes:
- evolution_instances:/evolution/instances
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
DOMINIO: ${DOMINIO}
EMAIL: ${EMAIL}
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
volumes:
postgres_data:
redis_data:
evolution_instances:
caddy_data:
caddy_config:
EOF
cat > /opt/evolution/Caddyfile <<'EOF'
{$DOMINIO} {
tls {$EMAIL}
reverse_proxy evolution:8080
}
EOF
A imagem está presa a uma versão (v2.1.1) de propósito. Com latest, uma atualização automática pode trocar a versão maior e quebrar integrações em produção sem aviso.
Suba e confirme que a API responde
cd /opt/evolution
docker compose up -d
docker compose ps
# a API deve responder com a versão
curl -s https://api.seudominio.com.br | head -20
A resposta é um JSON com o nome e a versão da API. Se vier erro de certificado, espere um minuto — o Caddy emite na primeira requisição.
Crie a primeira instância e leia o QR Code
Cada número de WhatsApp é uma "instância". A criação devolve o QR Code que você lê no aparelho, em Dispositivos conectados.
source /opt/evolution/.env
curl -s -X POST "https://$DOMINIO/instance/create" \
-H "apikey: $AUTHENTICATION_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"instanceName": "principal",
"qrcode": true,
"integration": "WHATSAPP-BAILEYS"
}'
A resposta traz o QR em base64. Mais prático é abrir o gerenciador no navegador: https://api.seudominio.com.br/manager, entrar com a sua chave de API e ler o código pela tela.
Envie a primeira mensagem
Com a instância conectada, o envio é uma requisição. Use o número no formato internacional, sem sinais.
curl -s -X POST "https://$DOMINIO/message/sendText/principal" \
-H "apikey: $AUTHENTICATION_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"number": "5571999999999",
"text": "Funcionou."
}'
Aponte o webhook para o seu fluxo
Para receber mensagens, configure um webhook. É assim que o n8n ou o seu sistema ficam sabendo que alguém respondeu.
curl -s -X POST "https://$DOMINIO/webhook/set/principal" \
-H "apikey: $AUTHENTICATION_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"webhook": {
"enabled": true,
"url": "https://n8n.seudominio.com.br/webhook/whatsapp",
"events": ["MESSAGES_UPSERT"]
}
}'
Assine só os eventos que você vai tratar. MESSAGES_UPSERT cobre mensagens recebidas; assinar tudo gera um volume de chamadas que não serve para nada e ainda pesa no seu fluxo.
Se algo não funcionar
O QR Code expira antes de eu conseguir ler
O código tem validade curta. Peça um novo pelo endpoint de conexão e leia em seguida:
curl -s "https://$DOMINIO/instance/connect/principal" -H "apikey: $AUTHENTICATION_API_KEY"
A instância desconecta sozinha depois de um tempo
Normalmente é o aparelho: o WhatsApp encerra a sessão se o celular ficar muito tempo sem internet. Confirme também que o Redis está de pé — sem cache, a sessão se perde com mais facilidade.
docker compose ps
docker compose logs --tail 50 evolution
Erro 401 em todas as chamadas
O cabeçalho é apikey, em minúsculas, e o valor precisa ser idêntico ao do .env. Confira com grep AUTHENTICATION /opt/evolution/.env.
Rota nacional direta, importante quando cada segundo de latência aparece na conversa do cliente.
Perguntas frequentes
A Evolution API é oficial do WhatsApp?
Não. É um projeto de código aberto que usa a interface do WhatsApp Web. Funciona bem, mas o uso está sujeito às regras da plataforma e existe risco de bloqueio do número em caso de envio em massa ou comportamento tido como abusivo. Para campanhas de grande volume, o caminho oficial é a API Cloud da Meta.
Quantos números posso conectar na mesma instalação?
Não há limite no software, e sim de memória: cada instância conectada mantém a sessão ativa. Com 2 GB você roda uma ou duas com tranquilidade; a partir daí, suba para 4 GB.
Dá para integrar com o n8n?
Sim, e é o uso mais comum. O n8n recebe o webhook de mensagem nova, decide o que fazer e chama de volta o endpoint de envio da Evolution. As duas aplicações podem rodar na mesma VPS, cada uma no seu subdomínio.
Continue por aqui
Como instalar o n8n em uma VPS com Docker e HTTPS
Sobe o n8n com banco PostgreSQL e certificado automático, em uma VPS Ubuntu com acesso root.
Como instalar o Typebot em uma VPS
Construtor de conversas auto-hospedado, com builder e viewer em subdomínios separados e armazenamento de arquivos.
Como instalar o Chatwoot em uma VPS
Central de atendimento auto-hospedada: caixa de entrada única para site, e-mail e WhatsApp, com histórico no seu servidor.