Servicio HTTP en Node.js/Express que gestiona sesión de WhatsApp Web, expone endpoints para enviar mensajes y sirve imágenes QR de vinculación. Genera eventos hacia un backend externo mediante solicitudes POST.
- Node.js 22+
- pnpm 8+
pnpm installCrea un archivo .env en la raíz del proyecto:
# URL del backend que recibe los eventos (qr, ready, msg-received, etc.)
API_URL=https://tu-backend.com/api
# Identificador único del cliente/sesión (empresa)
CLIENT_ID=empresa-123
# URL pública donde se sirve esta API (útil para callback/consumo externo)
API_URL_FLY=https://tu-app.fly.dev
# Puerto local (opcional, por defecto 3000)
PORT=3000
# Ruta del ejecutable de Chromium/Chrome (opcional).
# En Docker ya se ajusta a /usr/bin/chromium automáticamente.
# En macOS/Linux puede omitirse si Chrome está en PATH.
# PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chromepnpm run start:dev: inicia con recarga y carga.envpnpm run start: inicia en modo producción
GET /yGET /status: healthcheck básico.GET /qr/:foto: sirve la imagen PNG del código QR generado para vincular WhatsApp Web.GET /archive/:id: sirve archivos temporales recibidos (imágenes, audio, documentos, etc.).
Envió de mensajes (requiere sesión conectada):
POST /send-message/text- body:
{ "number": "<numero@c.us>", "text": "Hola" }
- body:
POST /send-message/image- body:
{ "number": "<numero@c.us>", "imageUrl": "https://.../img.jpg", "caption": "opcional" }
- body:
POST /send-message/video- body:
{ "number": "<numero@c.us>", "videoUrl": "https://.../video.mp4", "caption": "opcional" }
- body:
POST /send-message/audio- body:
{ "number": "<numero@c.us>", "audioUrl": "https://.../audio.ogg" }(se envía como nota de voz)
- body:
POST /send-message/document- body:
{ "number": "<numero@c.us>", "documentUrl": "https://.../file.pdf", "caption": "opcional" }
- body:
Verificar estado de sesión:
GET /is-conected→{ status, client, connected, message }
Notas:
- El formato de número de WhatsApp debe terminar en
@c.us. - La sesión se maneja con
LocalAuthy se identifica porCLIENT_ID.
El servicio envía POST a API_URL/whatweb/ con los siguientes type:
qr-generated: cuando se genera un QR nuevo (incluye nombre del archivo PNG enqrs/).loading-screen: progreso de carga del cliente.ready: cuando el cliente queda listo/conectado.msg-received: para cada mensaje entrante (incluye metadatos y archivos temporales si aplica).disconnected: cuando el cliente se desconecta.init-timerydelete-machine: control de un temporizador de 15 minutos iniciado al levantar el servidor.
- Configura
.env. - Ejecuta:
pnpm run start:dev- Abre el QR servido en tu backend (vía evento
qr-generated) o directamente desdeGET /qr/:fotosi conoces el nombre. Escanea con WhatsApp en el teléfono.
Directorios que se crean/usan:
qrs/: guarda PNGs de QR por sesión (<CLIENT_ID>-<uuid>.png).tmp/: guarda archivos de medios recibidos temporalmente.
Se incluye Dockerfile multi-stage con Chromium para Puppeteer.
Build y run local:
docker build -t qr-api .
docker run --rm -p 3000:3000 \
-e API_URL=$API_URL \
-e CLIENT_ID=$CLIENT_ID \
-e API_URL_FLY=$API_URL_FLY \
-v $(pwd)/qrs:/app/qrs \
-v $(pwd)/tmp:/app/tmp \
qr-apiNotas Docker:
- La imagen instala
chromiumy definePUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium. - Expone el puerto 3000 y ejecuta
pnpm run start.
Hay un fly.toml de ejemplo. En este repo está configurado para usar una imagen preconstruida (whastapp/qrcode:1.0.4) y internal_port = 8080. Adapta según tu flujo:
Opciones:
- Usar imagen propia construida desde este Dockerfile (recomendado si modificas código):
- Actualiza
[build]enfly.tomlo eliminaimagey usafly launch/fly deploypara que Fly construya desde el Dockerfile.
- Actualiza
- Usar la imagen preconstruida existente: asegúrate de alinear variables y puerto interno que expone la imagen.
Documentación: https://fly.io/docs/reference/configuration/
curl -s http://localhost:3000/status
curl -s http://localhost:3000/is-conected
curl -s -X POST http://localhost:3000/send-message/text \
-H 'Content-Type: application/json' \
-d '{"number":"1234567890@c.us","text":"Hola desde API"}'- Protege esta API detrás de tu backend o una gateway; agrega autenticación si la expones públicamente.
- Asegura el almacenamiento de
qrs/ytmp/si contienen información sensible. - Mantén actualizado Chromium/Node en entornos de producción.
ISC