Evolution API: Instale uma API Não Oficial do WhatsApp em sua VPS e Automatize o Envio de Mensagens

Instale a Evolution API no Docker da sua VPS e envie mensagens no WhatsApp com uma API não oficial

Evolution API: Instale uma API Não Oficial do WhatsApp em sua VPS e Automatize o Envio de Mensagens

Olá meus Unicórnios! 🦄✨

Se você já precisou enviar mensagens automatizadas via WhatsApp sabe que existem milhares de APIs que fazem isto, mas, em resumo, todas se resumem a duas.

API Oficial

Esta é a API Oficial do WhatsApp, mantida pela Meta.

Eu preferencialmente prefixo a API Oficial, já que evita problemas do número ser bloqueado sem um motivo claro.

Mesmo também podendo ser bloqueado, vais acabar tendo indicadores claros antes disto, e se você utilizar de forma moderada (sem spam), não terá problemas.

Porem, temos desvantagens claras:

  • Precisa de uma conta Facebook Business
  • É Pago
  • Se quiser enviar muitas, mensagens vai precisar validar a conta Facebook Business
  • Cada "primeira mensagem" precisa de aprovação do Template da Mensagem

API não Oficial

Esta é uma forma muito comum em APIs com preços baixos, onde existe uma aplicação que simula o uso do WhatsApp Web e cria uma camada de API para gerenciar as ações.

O preço é muito menor que a API Oficial, mas precisamos lembrar, é algo NÃO OFICIAL.

Este é uma abordagem muito boa quando precisas de algo simples, por exemplo, enviar notificações de pagamento de um pedido.

Porem, também temos desvantagens:

  • O Número pode ser bloqueado a qualquer momento
  • As ações que podes executar são limitadas ao que você pode fazer no WhatsApp Web (Com algumas poucas exceções)
  • Caso for instalar em uma VPS, ira requer um conhecimento maior

Evolution API

Neste tutorial iremos abordagem a utilização de uma API não Oficial, instalada em uma VPS, a "Evolution API":

Evolution API
Evolution API - Omni-Channel Communication Platform

Esta é uma ferramenta que possui versão Self-Hosting, totalmente gratuita, e excelente!

A API dela é muito ampla:

Postman

Instalando o Evolution API

Iremos utilizar uma VPS com o Ubuntu 22.04, e instalar o Evolution API (e suas dependências) via Docker Compose.

O Evolution precisa de uma base de dados (postgres) e um cache (redis).

Iremos instalar as dependência de forma separada, para podermos reaproveitar o mesmo postgres e o mesmo redis em outros projetos.

Antes de tudo vamos instalar o docker-compose:

sudo apt update
sudo apt install docker-compose

Agora, crie uma pasta "utilitarios" e entre nela:

mkdir utilitarios
cd utilitarios

Crie o "docker-compose.yaml":

nano docker-compose.yaml

Preencha com o conteúdo abaixo:

services:

  redis:
    image: redis:latest
    networks:
      - utilitarios-net
    container_name: redis
    command: >
      redis-server --port 6379 --appendonly yes
    volumes:
      - redis_data:/data
    ports:
      - 6379:6379

  postgres:
    container_name: postgres
    image: postgres:15
    networks:
      - utilitarios-net
    command: ["postgres", "-c", "max_connections=1000", "-c", "listen_addresses=*"]
    restart: always
    ports:
      - 5432:5432
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=utilitarios
      - POSTGRES_HOST_AUTH_METHOD=trust
    volumes:
      - postgres_data:/var/lib/postgresql/data
    expose:
      - 5432

volumes:
  redis_data:
  postgres_data:

networks:
  utilitarios-net:
    name: utilitarios-net
    driver: bridge

Vamos subir o Compose:

sudo docker-compose up -d

Quando a instalação for completada, será exibido "done" em tudo:

Agora que instalamos o postgress e o redis, vamos instalar o evolutionapi.

Crie uma pasta "evolutionapi" e entre nela:

mkdir evolutionapi
cd evolutionapi

Crie o "docker-compose.yaml":

nano docker-compose.yaml

Preencha com o conteúdo abaixo:

services:
  evolution_api:
    container_name: evolution_api
    image: atendai/evolution-api:homolog
    restart: always
    ports:
      - 8080:8080
    volumes:
      - evolution_instances:/evolution/instances
    networks:
      - evolution-net
      - utilitarios-net
    env_file:
      - .env

volumes:
  evolution_instances:

networks:
  evolution-net:
    name: evolution-net
    driver: bridge
  utilitarios-net:
    external: true 

Agora iremos criar nosso arquivo ".env" com todas as configurações da aplicação:

nano .env

Preencha com o conteúdo abaixo:

SERVER_TYPE=http
SERVER_PORT=8080
# Server URL - Set your application url
SERVER_URL=http://localhost:8080

SENTRY_DSN=

# Cors - * for all or set separate by commas -  ex.: 'yourdomain1.com, yourdomain2.com'
CORS_ORIGIN=*
CORS_METHODS=GET,POST,PUT,DELETE
CORS_CREDENTIALS=true

# Determine the logs to be displayed
LOG_LEVEL=ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,DARK,WEBHOOKS,WEBSOCKET
LOG_COLOR=true
# Log Baileys - "fatal" | "error" | "warn" | "info" | "debug" | "trace"
LOG_BAILEYS=error

# Set the maximum number of listeners that can be registered for an event
EVENT_EMITTER_MAX_LISTENERS=50

# Determine how long the instance should be deleted from memory in case of no connection.
# Default time: 5 minutes
# If you don't even want an expiration, enter the value false
DEL_INSTANCE=false

# Provider: postgresql | mysql
DATABASE_PROVIDER=postgresql
DATABASE_CONNECTION_URI='postgresql://user:pass@postgres:5432/evolution?schema=public'
# Client name for the database connection
# It is used to separate an API installation from another that uses the same database.
DATABASE_CONNECTION_CLIENT_NAME=evolution_exchange

# Choose the data you want to save in the application's database
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
DATABASE_SAVE_DATA_LABELS=true
DATABASE_SAVE_DATA_HISTORIC=true
DATABASE_SAVE_IS_ON_WHATSAPP=true
DATABASE_SAVE_IS_ON_WHATSAPP_DAYS=7
DATABASE_DELETE_MESSAGE=true

# RabbitMQ - Environment variables
RABBITMQ_ENABLED=false
RABBITMQ_URI=amqp://localhost
RABBITMQ_EXCHANGE_NAME=evolution
# Global events - By enabling this variable, events from all instances are sent in the same event queue.
RABBITMQ_GLOBAL_ENABLED=false
# Prefix key to queue name
RABBITMQ_PREFIX_KEY=evolution
# Choose the events you want to send to RabbitMQ
RABBITMQ_EVENTS_APPLICATION_STARTUP=false
RABBITMQ_EVENTS_INSTANCE_CREATE=false
RABBITMQ_EVENTS_INSTANCE_DELETE=false
RABBITMQ_EVENTS_QRCODE_UPDATED=false
RABBITMQ_EVENTS_MESSAGES_SET=false
RABBITMQ_EVENTS_MESSAGES_UPSERT=false
RABBITMQ_EVENTS_MESSAGES_EDITED=false
RABBITMQ_EVENTS_MESSAGES_UPDATE=false
RABBITMQ_EVENTS_MESSAGES_DELETE=false
RABBITMQ_EVENTS_SEND_MESSAGE=false
RABBITMQ_EVENTS_CONTACTS_SET=false
RABBITMQ_EVENTS_CONTACTS_UPSERT=false
RABBITMQ_EVENTS_CONTACTS_UPDATE=false
RABBITMQ_EVENTS_PRESENCE_UPDATE=false
RABBITMQ_EVENTS_CHATS_SET=false
RABBITMQ_EVENTS_CHATS_UPSERT=false
RABBITMQ_EVENTS_CHATS_UPDATE=false
RABBITMQ_EVENTS_CHATS_DELETE=false
RABBITMQ_EVENTS_GROUPS_UPSERT=false
RABBITMQ_EVENTS_GROUP_UPDATE=false
RABBITMQ_EVENTS_GROUP_PARTICIPANTS_UPDATE=false
RABBITMQ_EVENTS_CONNECTION_UPDATE=false
RABBITMQ_EVENTS_REMOVE_INSTANCE=false
RABBITMQ_EVENTS_LOGOUT_INSTANCE=false
RABBITMQ_EVENTS_CALL=false
RABBITMQ_EVENTS_TYPEBOT_START=false
RABBITMQ_EVENTS_TYPEBOT_CHANGE_STATUS=false

# SQS - Environment variables
SQS_ENABLED=false
SQS_ACCESS_KEY_ID=
SQS_SECRET_ACCESS_KEY=
SQS_ACCOUNT_ID=
SQS_REGION=

# Websocket - Environment variables
WEBSOCKET_ENABLED=false
WEBSOCKET_GLOBAL_EVENTS=false

# Pusher - Environment variables
PUSHER_ENABLED=false
PUSHER_GLOBAL_ENABLED=false
PUSHER_GLOBAL_APP_ID=
PUSHER_GLOBAL_KEY=
PUSHER_GLOBAL_SECRET=
PUSHER_GLOBAL_CLUSTER=
PUSHER_GLOBAL_USE_TLS=true
# Choose the events you want to send to Pusher
PUSHER_EVENTS_APPLICATION_STARTUP=true
PUSHER_EVENTS_QRCODE_UPDATED=true
PUSHER_EVENTS_MESSAGES_SET=true
PUSHER_EVENTS_MESSAGES_UPSERT=true
PUSHER_EVENTS_MESSAGES_EDITED=true
PUSHER_EVENTS_MESSAGES_UPDATE=true
PUSHER_EVENTS_MESSAGES_DELETE=true
PUSHER_EVENTS_SEND_MESSAGE=true
PUSHER_EVENTS_CONTACTS_SET=true
PUSHER_EVENTS_CONTACTS_UPSERT=true
PUSHER_EVENTS_CONTACTS_UPDATE=true
PUSHER_EVENTS_PRESENCE_UPDATE=true
PUSHER_EVENTS_CHATS_SET=true
PUSHER_EVENTS_CHATS_UPSERT=true
PUSHER_EVENTS_CHATS_UPDATE=true
PUSHER_EVENTS_CHATS_DELETE=true
PUSHER_EVENTS_GROUPS_UPSERT=true
PUSHER_EVENTS_GROUPS_UPDATE=true
PUSHER_EVENTS_GROUP_PARTICIPANTS_UPDATE=true
PUSHER_EVENTS_CONNECTION_UPDATE=true
PUSHER_EVENTS_LABELS_EDIT=true
PUSHER_EVENTS_LABELS_ASSOCIATION=true
PUSHER_EVENTS_CALL=true
PUSHER_EVENTS_TYPEBOT_START=false
PUSHER_EVENTS_TYPEBOT_CHANGE_STATUS=false

# WhatsApp Business API - Environment variables
# Token used to validate the webhook on the Facebook APP
WA_BUSINESS_TOKEN_WEBHOOK=evolution
WA_BUSINESS_URL=https://graph.facebook.com
WA_BUSINESS_VERSION=v20.0
WA_BUSINESS_LANGUAGE=en_US

# Global Webhook Settings
# Each instance's Webhook URL and events will be requested at the time it is created
WEBHOOK_GLOBAL_ENABLED=false
# Define a global webhook that will listen for enabled events from all instances
WEBHOOK_GLOBAL_URL=''
# With this option activated, you work with a url per webhook event, respecting the global url and the name of each event
WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false
# Set the events you want to hear
WEBHOOK_EVENTS_APPLICATION_STARTUP=false
WEBHOOK_EVENTS_QRCODE_UPDATED=true
WEBHOOK_EVENTS_MESSAGES_SET=true
WEBHOOK_EVENTS_MESSAGES_UPSERT=true
WEBHOOK_EVENTS_MESSAGES_EDITED=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_REMOVE_INSTANCE=false
WEBHOOK_EVENTS_LOGOUT_INSTANCE=false
WEBHOOK_EVENTS_LABELS_EDIT=true
WEBHOOK_EVENTS_LABELS_ASSOCIATION=true
WEBHOOK_EVENTS_CALL=true
# This events is used with Typebot
WEBHOOK_EVENTS_TYPEBOT_START=false
WEBHOOK_EVENTS_TYPEBOT_CHANGE_STATUS=false
# This event is used to send errors
WEBHOOK_EVENTS_ERRORS=false
WEBHOOK_EVENTS_ERRORS_WEBHOOK=

# Name that will be displayed on smartphone connection
CONFIG_SESSION_PHONE_CLIENT=Evolution API
# Browser Name = Chrome | Firefox | Edge | Opera | Safari
CONFIG_SESSION_PHONE_NAME=Chrome

# Whatsapp Web version for baileys channel
# https://web.whatsapp.com/check-update?version=0&platform=web
CONFIG_SESSION_PHONE_VERSION=2.3000.1015901307

# Set qrcode display limit
QRCODE_LIMIT=30
# Color of the QRCode on base64
QRCODE_COLOR='#175197'

# Typebot - Environment variables
TYPEBOT_ENABLED=false
# old | latest
TYPEBOT_API_VERSION=latest

# Chatwoot - Environment variables
CHATWOOT_ENABLED=false
# If you leave this option as false, when deleting the message for everyone on WhatsApp, it will not be deleted on Chatwoot.
CHATWOOT_MESSAGE_READ=true
# If you leave this option as true, when sending a message in Chatwoot, the client's last message will be marked as read on WhatsApp.
CHATWOOT_MESSAGE_DELETE=true
# If you leave this option as true, a contact will be created on Chatwoot to provide the QR Code and update messages about the instance.
CHATWOOT_BOT_CONTACT=true
# This db connection is used to import messages from whatsapp to chatwoot database
CHATWOOT_IMPORT_DATABASE_CONNECTION_URI=postgresql://user:passwprd@host:5432/chatwoot?sslmode=disable
CHATWOOT_IMPORT_PLACEHOLDER_MEDIA_MESSAGE=true

# OpenAI - Environment variables
OPENAI_ENABLED=false

# Dify - Environment variables
DIFY_ENABLED=false

# Cache - Environment variables
# Redis Cache enabled
CACHE_REDIS_ENABLED=true
CACHE_REDIS_URI=redis://redis:6379/6
CACHE_REDIS_TTL=604800
# Prefix serves to differentiate data from one installation to another that are using the same redis
CACHE_REDIS_PREFIX_KEY=evolution
# Enabling this variable will save the connection information in Redis and not in the database.
CACHE_REDIS_SAVE_INSTANCES=false
# Local Cache enabled
CACHE_LOCAL_ENABLED=false

# Amazon S3 - Environment variables
S3_ENABLED=false
S3_ACCESS_KEY=
S3_SECRET_KEY=
S3_BUCKET=evolution
S3_PORT=443
S3_ENDPOINT=s3.domain.com
S3_REGION=eu-west-3
S3_USE_SSL=true

# AMAZON S3 - Environment variables
# S3_ENABLED=true
# S3_BUCKET=bucket_name
# S3_ACCESS_KEY=access_key_id
# S3_SECRET_KEY=secret_access_key
# S3_ENDPOINT=s3.amazonaws.com # region: s3.eu-west-3.amazonaws.com
# S3_REGION=eu-west-3

# MINIO Use SSL - Environment variables
# S3_ENABLED=true
# S3_ACCESS_KEY=access_key_id
# S3_SECRET_KEY=secret_access_key
# S3_BUCKET=bucket_name
# S3_PORT=443
# S3_ENDPOINT=s3.domain.com
# S3_USE_SSL=true
# S3_REGION=eu-south

# Evolution Audio Converter - Environment variables - https://github.com/EvolutionAPI/evolution-audio-converter
# API_AUDIO_CONVERTER=http://localhost:4040/process-audio
# API_AUDIO_CONVERTER_KEY=429683C4C977415CAAFCCE10F7D57E11

# Define a global apikey to access all instances.
# OBS: This key must be inserted in the request header to create an instance.
AUTHENTICATION_API_KEY=429683C4C977415CAAFCCE10F7D57E11
# If you leave this option as true, the instances will be exposed in the fetch instances endpoint.
AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true
LANGUAGE=en

# Define a global proxy to be used if the instance does not have one
# PROXY_HOST=
# PROXY_PORT=80
# PROXY_PROTOCOL=http
# PROXY_USERNAME=
# PROXY_PASSWORD=

Nestas configurações, defina uma API KEY única em:

AUTHENTICATION_API_KEY=429683C4C977415CAAFCCE10F7D57E11

Temos nosso "docker-compose.yaml' e nosso ".env", vamos subir o Compose:

sudo docker-compose up -d

Quando a instalação for completada, será exibido "done" em tudo:

Para testar, acesse o IP de sua VPS com a porta "8080", que no meu caso é:

http://192.168.20.155:8080/

Caso tiver tido sucesso na instalação, será exibido "Welcome to the Evolution API, it is working!":

{
  "status": 200,
  "message": "Welcome to the Evolution API, it is working!",
  "version": "2.2.3",
  "clientName": "evolution_exchange",
  "manager": "http://192.168.20.155:8080/manager",
  "documentation": "https://doc.evolution-api.com"
}

Criando nossa primeira instancia no Evolution API

Dentro do Evolution API você pode ter diversas instancias, cada instancia é um número do whatsapp que será conectado.

Acesse o painel via ":8080/manager/":

http://192.168.20.155:8080/manager/

Será exibido uma espécie de janela de Login:

Aqui você precisa preencher a "AUTHENTICATION_API_KEY" que populamos no ".env", depois disto clique em "Login".

Clique em "Instance +":

Preencha um "Name" (Este é o "ID" que iremos utilizar na API), e deixe os outros campos sem alteração e clique em "Save":

Clique na instancia recém criada:

Clique em "Get QR Code":

Será exibido o QRCode para conexão:

Através do seu celular, no whatsapp, adicione um novo "Dispositivo" scaneando o QRCode exibido.

Depois disto, atualize a janela e você já deve ver "Connected":

Observe também que abaixo do nome da Instancia, temos a API KEY desta instancia, salve esta API KEY para utilizarmos na API:

Pronto! Seu WhatsApp foi conectado na Instancia da Evolution API.

Enviando Mensagens através da API

A Evoluiton possui uma API excelente que pode ser explorada em:

Postman

O envio de mensagens é feito via:

http://[IP_DA_VPS]:8080/message/sendText/[NOME_DA_INTANCIA]

Enviando um POST, com um Json bem simples:

{
  "number": "554799999999",
  "text": "Teste1"
}

E no Header, adicionando a API KEY de nossa intancia:

apikey: BD2867802851-4C3E-B212-3ADC64F45FEB

O retorno será um HttpCode 200:

{
  "key": {
    "remoteJid": "[email protected]",
    "fromMe": true,
    "id": "XXXXXXXXXXXXXXXXXXXXXXXX"
  },
  "pushName": "",
  "status": "PENDING",
  "message": {
    "conversation": "Teste1"
  },
  "contextInfo": null,
  "messageType": "conversation",
  "messageTimestamp": 111111111111,
  "instanceId": "fd9b1edb-2f56-47c7-a412-9e7caa71f03f",
  "source": "unknown"
}

Por hoje é só, meus unicórnios! 🦄✨

Que a magia do arco-íris continue brilhando em suas vidas! Até mais! 🌈🌟