Guias/Instalação e ambiente
Documentação

Instalação e ambiente

Variáveis de ambiente e configuração do servidor.

Capa da aula Como Instalar a CodeChat API WhatsApp em GoComo Instalar a CodeChat API WhatsApp em Go | Guia CompletoNeste vídeo, você vai aprender a instalar e executar a CodeChat API WhatsApp em Go.youtu.be
VariávelObrigatóriaExemploDescrição
SERVER_PORTNão8084Porta do listener HTTP. A aplicação escuta em :SERVER_PORT. O padrão é 8084.
LOG_LEVELNãotraceNível global do Zerolog. Valores aceitos: trace, debug, info, warn, error, fatal, panic, disabled. O padrão é info.
DATABASE_URLSimpostgres://...String de conexão com o PostgreSQL.
DATABASE_SAVE_DATA_NEW_MESSAGENãotrueHabilita a persistência de linhas WhatsApp Message a partir de eventos de mensagens recebidas. O padrão é true.
DATABASE_SAVE_MESSAGE_UPDATENãofalseHabilita a persistência de eventos de recibo do WhatsApp em MessageUpdate. O padrão é false.
DATABASE_SAVE_DATA_CONTACTSNãofalseHabilita a persistência de sincronização e eventos de contatos do WhatsApp em Contact. O padrão é false.
WHATSAPP_SESSION_STORENãopostgresBanco usado pelo whatsmeow para sessões e dispositivos. Valores aceitos: sqlite, postgres. O padrão é postgres quando não for definido.
WHATSAPP_SESSION_SQLITE_DSNNãofile:./data/whatsmeow.db?_foreign_keys=onDSN do SQLite usado somente quando WHATSAPP_SESSION_STORE=sqlite. As chaves estrangeiras precisam continuar habilitadas.
WHATSAPP_SESSION_POSTGRES_URLNãopostgres://...String de conexão opcional e dedicada do PostgreSQL para as sessões do whatsmeow. Quando vazia, DATABASE_URL é usada pelo SQL store do whatsmeow.
WEBHOOK_GLOBAL_URLNãohttps://example.com/webhookURL do webhook global. Precisa ser http ou https absoluta; obrigatória somente quando WEBHOOK_GLOBAL_ENABLED=true.
WEBHOOK_GLOBAL_ENABLEDNãofalseHabilita o envio de todos os eventos reconhecidos de todas as instâncias para WEBHOOK_GLOBAL_URL. O padrão é false.
WEBSOCKET_ENABLEDNãotrueHabilita as rotas /ws/instance/events e /ws/global/events. O padrão é true.
WEBSOCKET_ALLOWED_ORIGINSNãohttp://localhost:3000,http://localhost:5173Lista separada por vírgula de origens aceitas para browsers. Quando vazia, clientes com Origin são rejeitados.
WEBSOCKET_ALLOW_EMPTY_ORIGINNãotruePermite clientes backend sem header Origin.
WEBSOCKET_PING_INTERVALNão25sIntervalo de ping do servidor WebSocket.
WEBSOCKET_PONG_TIMEOUTNão60sPrazo máximo para receber pong antes de encerrar a conexão.
WEBSOCKET_WRITE_TIMEOUTNão10sPrazo máximo de escrita de frames.
WEBSOCKET_SEND_BUFFERNão256Tamanho do buffer por cliente WebSocket.
AUTHENTICATION_JWT_EXPIRES_INSim3600Expiração do JWT em segundos. O valor 0 remove a claim exp.
AUTHENTICATION_JWT_SECRETSimstrong-secretChave secreta usada para assinar JWTs com HS256.
AUTHENTICATION_GLOBAL_AUTH_TOKENSimadmin-tokenToken usado somente para criar e listar instâncias.
QRCODE_LIMITSim5Número máximo de QR codes servidos durante uma tentativa de pareamento.
QRCODE_EXPIRATION_TIMESim30Tempo máximo de vida do QR code em segundos.
QRCODE_LIGHT_COLORSim#ffffffCor clara usada na geração do QR PNG.
QRCODE_DARK_COLORSim#198754Cor escura usada na geração do QR PNG.
CONFIG_SESSION_PHONE_CLIENTNãoDESKTOPTipo de plataforma exibido nos dispositivos conectados do WhatsApp. O padrão é DESKTOP. Valores aceitos: ALOHA, ANDROID_AMBIGUOUS, ANDROID_PHONE, ANDROID_TABLET, AR_DEVICE, AR_WRIST, CATALINA, CHROME, CLOUD_API, DESKTOP, EDGE, FIREFOX, IE, IOS_CATALYST, IOS_PHONE, IPAD, OHANA, OPERA, SAFARI, SMARTGLASSES, TCL_TV, UWP, VR, WEAR_OS.
CONFIG_SESSION_PHONE_NAMENãoCodeChatNome do sistema ou cliente exibido nos dispositivos conectados do WhatsApp. O padrão é CodeChat.
WHATSAPP_PAIRING_TIMEOUTNão3mTimeout total do contexto de pareamento por QR. O padrão é 3m quando não for definido.
WHATSAPP_AUTO_RECONNECTSimtrueHabilita a restauração, na inicialização, das sessões que deveriam estar online.
WHATSAPP_STARTUP_RECONNECT_CONCURRENCYSim5Número máximo de sessões WhatsApp restauradas em paralelo.
WHATSAPP_CONNECT_TIMEOUTSim30Timeout inicial de espera da conexão, em segundos.
WHATSAPP_RECONNECT_INITIAL_DELAYSim2Backoff inicial de reconexão, em segundos.
WHATSAPP_RECONNECT_MAX_DELAYSim60Backoff máximo de reconexão, em segundos.
WHATSAPP_PROFILE_PICTURE_TIMEOUTSim15Timeout para buscar foto de perfil, em segundos.
WHATSAPP_ADDRESS_CACHE_TTLNão168hTTL dos mapeamentos em cache entre endereço WhatsApp e JID canônico. O padrão é 168h.
MESSAGE_PROCESSING_WORKERSNão4Número máximo de jobs assíncronos de mensagem processados em paralelo. O padrão é 4.
MESSAGE_PROCESSING_QUEUE_SIZENão100Número máximo de jobs assíncronos de mensagem aguardando em memória. O padrão é 100; os valores precisam ser maiores que zero.
MESSAGE_PROCESSING_TIMEOUTNão60sTimeout total para um job assíncrono de mensagem. O padrão é 60s.
MESSAGE_GROUP_INFO_TIMEOUTNão30sTimeout para carregar informações e participantes de grupo do WhatsApp durante o processamento de mentionAll. O padrão é 30s.
MESSAGE_SEND_TIMEOUTNão30sTimeout para presença/delay e envio final pelo WhatsApp durante o processamento assíncrono de mensagem. O padrão é 30s.
MESSAGE_BATCH_WORKER_ENABLEDNãotrueHabilita o worker persistente de Envio em lote. Com false, os endpoints e os dados continuam disponíveis, mas nenhum item é consumido.
MESSAGE_BATCH_WORKER_POLL_INTERVAL_MSNão1000Intervalo, em milissegundos, entre consultas do worker e da outbox. Precisa ser maior que zero.
MESSAGE_BATCH_INSTANCE_RECHECK_INTERVAL_MSNão5000Intervalo, em milissegundos, para reavaliar instâncias de lotes em WAITING_FOR_INSTANCE.
MESSAGE_BATCH_MAX_DELAY_MSNão86400000Maior options.delay.maxMs aceito na criação de um lote; o padrão equivale a 24 horas.
MESSAGE_BATCH_MAX_RECIPIENTSNão10000Limite de entradas recebidas em recipients por lote, antes da remoção de duplicidades.
MEDIA_PRE_UPLOAD_MAX_FILE_SIZENão100MBTamanho máximo aceito em POST /instance/:instance/media/uploads. O padrão é 100MB; valores maiores são rejeitados antes de carregar o arquivo inteiro em memória.

Execução local

cp .env.dev .env
go run ./cmd/...

Quando DOCKER_ENV está ausente ou definido como false, a aplicação carrega .env e depois lê os valores do ambiente do processo. Variáveis já definidas no processo têm prioridade sobre os valores em .env.

.env.dev é um arquivo de referência para desenvolvimento local e não é carregado automaticamente.

Store de sessão do Whatsmeow

DATABASE_URL continua sendo o banco principal da API. WHATSAPP_SESSION_POSTGRES_URL é opcional e é usado somente pelo SQL store do whatsmeow quando estiver preenchido. Os repositórios da API e as migrations sempre usam DATABASE_URL.

O SQLite armazena sessões em um arquivo local e exige armazenamento persistente em containers. O DSN padrão mantém as chaves estrangeiras do SQLite habilitadas:

WHATSAPP_SESSION_STORE="sqlite"
WHATSAPP_SESSION_SQLITE_DSN="file:./data/whatsmeow.db?_foreign_keys=on"
WHATSAPP_SESSION_POSTGRES_URL=""

Quando Postgres é selecionado e WHATSAPP_SESSION_POSTGRES_URL está vazio, o whatsmeow usa o mesmo servidor/banco PostgreSQL configurado em DATABASE_URL, mas ainda com sua própria conexão SQL e seu próprio ciclo de vida:

DATABASE_URL="postgresql://api:password@postgres:5432/codechat"

WHATSAPP_SESSION_STORE="postgres"
WHATSAPP_SESSION_POSTGRES_URL=""

Quando WHATSAPP_SESSION_POSTGRES_URL está preenchido, as sessões do whatsmeow são inicializadas e migradas somente nesse banco dedicado. A aplicação não volta para DATABASE_URL se a URL dedicada estiver inválida ou indisponível:

DATABASE_URL="postgresql://api:password@postgres:5432/codechat"

WHATSAPP_SESSION_STORE="postgres"
WHATSAPP_SESSION_POSTGRES_URL="postgresql://sessions:password@postgres:5432/codechat_sessions"

Alterar WHATSAPP_SESSION_STORE não migra sessões existentes automaticamente. Os dispositivos só ficam disponíveis no novo backend se os dados do whatsmeow tiverem sido migrados antes; caso contrário, pode ser necessário parear as instâncias novamente. O backend anterior não é apagado.

Instalação com Docker

As imagens oficiais estão disponíveis no Docker Hub:

  • Imagem padrão: codechat/whatsapp-go-api
  • Imagem Pro: codechat/whatsapp-go-api:pro-1.0.0

A partir do diretório que contém a pasta whatsapp-go-api, inicie a API com o arquivo Compose do projeto:

docker compose -f whatsapp-go-api/docker-compose.yml up -d

Para usar a imagem Pro, altere o campo image do serviço em whatsapp-go-api/docker-compose.yml para codechat/whatsapp-go-api:pro-1.0.0 antes de executar o comando.

Variáveis do container

As variáveis precisam ser fornecidas diretamente ao container:

environment:
  SERVER_PORT: "${SERVER_PORT}"
  LOG_LEVEL: "${LOG_LEVEL}"
  DATABASE_URL: "${DATABASE_URL}"
  DATABASE_SAVE_DATA_NEW_MESSAGE: "${DATABASE_SAVE_DATA_NEW_MESSAGE:-true}"
  DATABASE_SAVE_MESSAGE_UPDATE: "${DATABASE_SAVE_MESSAGE_UPDATE:-false}"
  DATABASE_SAVE_DATA_CONTACTS: "${DATABASE_SAVE_DATA_CONTACTS:-false}"
  WHATSAPP_SESSION_STORE: "${WHATSAPP_SESSION_STORE:-postgres}"
  WHATSAPP_SESSION_SQLITE_DSN: "${WHATSAPP_SESSION_SQLITE_DSN:-file:./data/whatsmeow.db?_foreign_keys=on}"
  WHATSAPP_SESSION_POSTGRES_URL: "${WHATSAPP_SESSION_POSTGRES_URL:-}"
  WEBHOOK_GLOBAL_URL: "${WEBHOOK_GLOBAL_URL:-}"
  WEBHOOK_GLOBAL_ENABLED: "${WEBHOOK_GLOBAL_ENABLED:-false}"
  AUTHENTICATION_JWT_EXPIRES_IN: "${AUTHENTICATION_JWT_EXPIRES_IN}"
  AUTHENTICATION_JWT_SECRET: "${AUTHENTICATION_JWT_SECRET}"
  AUTHENTICATION_GLOBAL_AUTH_TOKEN: "${AUTHENTICATION_GLOBAL_AUTH_TOKEN}"
  QRCODE_LIMIT: "${QRCODE_LIMIT}"
  QRCODE_EXPIRATION_TIME: "${QRCODE_EXPIRATION_TIME}"
  QRCODE_LIGHT_COLOR: "${QRCODE_LIGHT_COLOR}"
  QRCODE_DARK_COLOR: "${QRCODE_DARK_COLOR}"
  CONFIG_SESSION_PHONE_CLIENT: "${CONFIG_SESSION_PHONE_CLIENT:-DESKTOP}"
  CONFIG_SESSION_PHONE_NAME: "${CONFIG_SESSION_PHONE_NAME:-CodeChat}"
  WHATSAPP_PAIRING_TIMEOUT: "${WHATSAPP_PAIRING_TIMEOUT}"
  WHATSAPP_AUTO_RECONNECT: "${WHATSAPP_AUTO_RECONNECT}"
  WHATSAPP_STARTUP_RECONNECT_CONCURRENCY: "${WHATSAPP_STARTUP_RECONNECT_CONCURRENCY}"
  WHATSAPP_CONNECT_TIMEOUT: "${WHATSAPP_CONNECT_TIMEOUT}"
  WHATSAPP_RECONNECT_INITIAL_DELAY: "${WHATSAPP_RECONNECT_INITIAL_DELAY}"
  WHATSAPP_RECONNECT_MAX_DELAY: "${WHATSAPP_RECONNECT_MAX_DELAY}"
  WHATSAPP_PROFILE_PICTURE_TIMEOUT: "${WHATSAPP_PROFILE_PICTURE_TIMEOUT}"
  WHATSAPP_ADDRESS_CACHE_TTL: "${WHATSAPP_ADDRESS_CACHE_TTL:-168h}"
  MESSAGE_PROCESSING_WORKERS: "${MESSAGE_PROCESSING_WORKERS:-4}"
  MESSAGE_PROCESSING_QUEUE_SIZE: "${MESSAGE_PROCESSING_QUEUE_SIZE:-100}"
  MESSAGE_PROCESSING_TIMEOUT: "${MESSAGE_PROCESSING_TIMEOUT:-60s}"
  MESSAGE_GROUP_INFO_TIMEOUT: "${MESSAGE_GROUP_INFO_TIMEOUT:-30s}"
  MESSAGE_SEND_TIMEOUT: "${MESSAGE_SEND_TIMEOUT:-30s}"
  MESSAGE_BATCH_WORKER_ENABLED: "${MESSAGE_BATCH_WORKER_ENABLED:-true}"
  MESSAGE_BATCH_WORKER_POLL_INTERVAL_MS: "${MESSAGE_BATCH_WORKER_POLL_INTERVAL_MS:-1000}"
  MESSAGE_BATCH_INSTANCE_RECHECK_INTERVAL_MS: "${MESSAGE_BATCH_INSTANCE_RECHECK_INTERVAL_MS:-5000}"
  MESSAGE_BATCH_MAX_DELAY_MS: "${MESSAGE_BATCH_MAX_DELAY_MS:-86400000}"
  MESSAGE_BATCH_MAX_RECIPIENTS: "${MESSAGE_BATCH_MAX_RECIPIENTS:-10000}"

Quando DOCKER_ENV=true, .env e .env.dev não são carregados.

Se WHATSAPP_SESSION_STORE=sqlite, monte um volume persistente para o diretório do SQLite. Para o DSN padrão, persista /app/data ou o caminho equivalente data do diretório de trabalho usado pela imagem:

volumes:
  - whatsmeow_sessions:/app/data

AUTHENTICATION_GLOBAL_AUTH_TOKEN autentica POST /instance, GET /instance e os aliases legados POST /instance/create e GET /instance/fetchInstances. Ele não autentica GET /instance/:instance, GET /instance/fetchInstance/:instanceName, PUT /instance/refreshToken/:instanceName nem as rotas /message/batches....

As rotas /message/batches... usam Authorization: Bearer <jwt-do-usuario>. Esse JWT precisa conter userId em formato UUID e exp; a expiração não é ignorada nesse fluxo.

O endpoint de refresh exige Authorization: Bearer <token> e o mesmo JWT atual no campo oldToken do corpo da requisição. Ele rotaciona o Auth.token armazenado para aquela instância, invalida imediatamente o token antigo e não representa um segundo tipo de refresh-token.

AUTHENTICATION_JWT_EXPIRES_IN=0 remove completamente a claim exp. Ele não gera exp: 0.

Não use segredos de desenvolvimento em produção. JWTs, chaves de API, tokens globais, URLs de banco e segredos não devem ser escritos em logs.

GET /instance/:instance/connect retorna o primeiro QR code do WhatsApp como código bruto mais um PNG data:image/png;base64,... gerado com as cores de QR configuradas. O alias legado GET /instance/connect/:instanceName permanece ativo. O processo de pareamento continua depois da resposta HTTP e usa WHATSAPP_PAIRING_TIMEOUT como deadline total do contexto.

GET /instance/:instance/connect/code/:phoneNumber retorna exatamente o código de pareamento do Whatsmeow. O alias legado mantém o formato /instance/connect/:instanceName/code/:phoneNumber. Números de telefone são normalizados para dígitos antes de chamar o Whatsmeow.

Os dois endpoints de conexão exigem o bearer token da instância armazenado em Auth.token; o token global de admin não é aceito.

CONFIG_SESSION_PHONE_CLIENT e CONFIG_SESSION_PHONE_NAME são aplicados uma vez durante a inicialização, antes da criação do SQL Store e dos clientes do Whatsmeow. Eles afetam somente novos vínculos. Dispositivos já vinculados não são apagados, deslogados nem reescritos automaticamente; para ver um novo rótulo, desconecte a instância pelo fluxo existente, remova o dispositivo vinculado no telefone, reinicie a aplicação, gere um novo QR code e vincule novamente.