Instalação local
Como rodar a API completa na sua máquina para desenvolvimento.
Pré-requisitos
- Node 20+ e npm.
- PostgreSQL e Redis acessíveis — via Docker (
docker compose, ver abaixo) ou instalados localmente.
npm test roda 100% mockado — sem PostgreSQL, sem Redis, sem .env
real. Docker só entra em cena se você quiser subir PostgreSQL/Redis via
docker compose, ou para buildar a imagem de produção. Se você só quer
rodar a suíte de testes, pule direto para Testes e lint.
1. Clonar e subir PostgreSQL + Redis
git clone <url-do-repositorio>
cd api-whatsapp
docker compose up -d postgres redis
O docker-compose.yml da raiz define três serviços: app (a própria API,
não usado neste passo), postgres (imagem postgres:16-alpine, expõe
localhost:5432) e redis (imagem redis:7-alpine, expõe
localhost:6379). Subir apenas postgres e redis é suficiente para
desenvolvimento — a API roda direto com npm run dev, fora do container.
2. Configurar o .env
cp .env.example .env
O .env.example usa os hostnames postgres/redis (só resolvem dentro da
rede do docker compose). Para rodar a API fora do container, ajuste para
localhost:
DATABASE_URL=postgresql://whats:whats@localhost:5432/whatsapp
REDIS_URL=redis://localhost:6379
Defina também AUTHENTICATION_API_KEY com uma chave forte e JWT_SECRET
com um segredo aleatório de pelo menos 16 caracteres — veja a tabela
completa abaixo.
3. Instalar dependências e gerar o client do Prisma
npm install
npx prisma generate
4. Rodar as migrations
npx prisma migrate dev
5. Subir a API em modo watch
npm run dev
A API sobe em http://localhost:8080 (ou na porta definida em PORT).
Swagger interativo em http://localhost:8080/docs; o Portal de
Controle fica em http://localhost:8080/panel assim que o
build do painel existir (ver panel/ abaixo).
Rodando o Portal de Controle em desenvolvimento
O painel (panel/, SPA React) é buildado à parte e servido pela própria
API em produção, mas em desenvolvimento roda como servidor Vite separado,
com proxy para a API local:
cd panel
npm install
npm run dev
Testes e lint
Testes e typecheck não precisam de Docker nem de .env real (exceto
onde o próprio teste indicar o contrário):
npm test
npx tsc --noEmit
npm run lint
O painel (panel/) tem sua própria suíte, rodada dentro da pasta:
cd panel
npm install
npm test
npx tsc -b
npm run lint
npm run build
Variáveis de ambiente
A lista abaixo reflete a validação real feita no boot da API
(src/infra/config.ts, com Zod) — se uma variável
obrigatória estiver ausente ou inválida, a API não sobe e o processo
termina com um erro de configuração.
| Variável | Obrigatória? | Descrição |
|---|---|---|
AUTHENTICATION_API_KEY | Sim | Chave global exigida no header apikey em todas as rotas, exceto /health, /docs*, /panel* e /auth/login. Sem valor, a API não sobe. |
DATABASE_URL | Sim | String de conexão do PostgreSQL (usada pelo Prisma). Sem valor, a API não sobe. |
REDIS_URL | Sim | String de conexão do Redis (usada pelas filas BullMQ). Sem valor, a API não sobe. |
JWT_SECRET | Sim | Segredo usado para assinar/verificar os tokens de sessão do Portal de Controle. Precisa ter ao menos 16 caracteres — validado no boot. A API não sobe sem essa variável. Gere um valor longo e aleatório e nunca reutilize entre ambientes. |
PORT | Não (padrão 8080) | Porta em que a API escuta. |
WEBHOOK_GLOBAL_URL | Não | Webhook padrão usado por instâncias sem webhook próprio configurado. Se definida, precisa ser uma URL válida. |
MAX_INSTANCES | Não (padrão 10) | Quantidade máxima de instâncias simultâneas — ver dimensionamento de memória em Deploy no EasyPanel. |
LOG_LEVEL | Não (padrão info) | Nível de log do Fastify/Pino (fatal, error, warn, info, debug, trace). |
PUPPETEER_EXECUTABLE_PATH | Não | Caminho do binário do Chromium usado pelo Puppeteer. Na imagem de produção já vem definido (/usr/bin/chromium); em dev local, normalmente não precisa ser definido (o Puppeteer usa o Chromium baixado por ele mesmo). |
SESSIONS_PATH | Não (padrão /app/sessions) | Diretório onde as sessões autenticadas do WhatsApp ficam salvas. |
TZ | Não (padrão America/Cuiaba) | Timezone padrão usado nas janelas de horário do anti-ban. |
CORS_ORIGIN | Não (padrão *) | Origem(ns) permitida(s) para CORS, separadas por vírgula. * reflete qualquer origem; em produção, restrinja à origem do portal. |
ADMIN_EMAIL | Não | Usada apenas para semear o primeiro usuário administrador do portal — só tem efeito se a tabela de usuários estiver vazia. Ver Portal de Controle. |
ADMIN_PASSWORD | Não | Idem ADMIN_EMAIL — se definida, precisa ter ao menos 8 caracteres. |
Diferente de ADMIN_EMAIL/ADMIN_PASSWORD (que são opcionais e só afetam
o seed do primeiro admin), JWT_SECRET é validada como obrigatória no
schema de configuração (src/infra/config.ts). Sem ela — ou com menos de
16 caracteres — a API falha ao subir, mesmo fora do contexto do portal.
Próximos passos
- Primeiros passos — criar sua primeira instância e enviar uma mensagem de teste.
- Deploy no EasyPanel — levar esta mesma stack para produção.