Variables de entorno¶
Requeridas¶
| Variable | Descripción |
|---|---|
POSTGRES_HOST |
Host del Postgres (típicamente postgres en overlay). |
POSTGRES_PASSWORD |
Password del usuario de qrsgen. |
DOWNSTREAM_BASE_URL |
URL del sistema downstream (ej: https://chat.example.com). |
DOWNSTREAM_API_TOKEN |
Token con permisos full sobre la cuenta downstream. |
INSTANCE_NAME |
Nombre de la instancia "default" creada al boot (puede coincidir con una existente para no crear nada nuevo). |
Opcionales (defaults razonables)¶
| Variable | Default | Notas |
|---|---|---|
QRSGEN_VERSION |
0.53.2 |
Tag de imagen Docker (qrsgen:${QRSGEN_VERSION}). Última versión: v0.53.2 (reactions como quote-reply visual del msg target en Chatwoot via content_attributes.in_reply_to). |
POSTGRES_PORT |
5432 |
|
POSTGRES_DB |
bridge |
|
POSTGRES_USER |
postgres |
|
DOWNSTREAM_ACCOUNT_ID |
1 |
|
DOWNSTREAM_INBOX_ID |
0 |
Inbox fallback cuando una instancia no tiene inbox_id configurado. |
QRSGEN_API_TOKEN |
(vacío) | Si vacío, auth desactivada (modo dev, log WARNING). Genera con python3 -c "import secrets;print(secrets.token_urlsafe(32))". |
WEBHOOK_HMAC_SECRET |
(vacío) | Si vacío, el webhook entrante queda abierto. Si set, exige X-Qrsgen-Signature HMAC-SHA256. |
PUBLIC_STATS_ENABLED |
false |
Si true, habilita GET /api/public/stats (sin auth, telemetría agregada). Ver Telemetría pública. |
PUBLIC_STATS_ALLOW_ORIGIN |
(vacío) | Header Access-Control-Allow-Origin para el endpoint público. Ejemplo: https://rricajos.github.io. |
OUTBOX_ENCRYPTION_KEY |
(vacío) | AES-256 key (32 bytes en base64 estándar) para cifrar payloads del outbox en reposo. Si vacío, payloads se guardan en claro (compat). Ver Outbox encryption. Desde v0.27.0. |
QRSGEN_GROUP_PREFIX_SENDER |
true |
Si true, mensajes incoming de grupos se postean a downstream con prefijo `+<E164> · <~?><Name>`\n<body> — desde v0.39.6 el header tiene estructura phone-first: teléfono en E.164 primero, separador middle dot · (U+00B7) con espacios a ambos lados, y nombre al final. Toda la línea va envuelta en un inline code block (backticks, heredado de v0.39.4) y el teléfono se incluye siempre (esté o no guardado el contacto, heredado de v0.39.4). El carácter ~ antes del nombre aparece solo si el contacto NO está guardado en la libreta del bot owner (IsContactSaved == false); contactos saved (FullName/FirstName) van sin tilde — replica la convención de la UI de WhatsApp (lógica de v0.39.5). v0.39.6 elimina los marcadores **bold** y los tabs \t heredados de v0.39.2/v0.39.3 porque Chatwoot no procesa bold dentro de inline code y colapsa los tabs a un único espacio dentro del code block. Pon a false si tu integración parsea el body raw. Desde v0.29.0 (formato actualizado en v0.30.1, v0.32.0, v0.39.2, v0.39.3, v0.39.4, v0.39.5 y v0.39.6 — v0.39.6 reordena a phone-first con · y retira **bold** + tabs por comportamiento de render observado en Chatwoot). |
QRSGEN_GROUP_HEADER_TTL |
10m |
Suprime el header de remitente en mensajes consecutivos del mismo participante dentro de un grupo, si caen dentro de este TTL. Replica la convención de WhatsApp (header en el primer msg del burst, nada en los siguientes). 0 desactiva la feature (header siempre). Desde v0.30.0. |
QRSGEN_GROUP_HEADER_SEP |
paragraph |
Separador entre el header `+phone · name` y el body del mensaje. Default paragraph (\n\n) por compatibilidad con Chatwoot. Alias soportados: paragraph/p (\n\n), br (<br> — en Chatwoot renderiza como <code>br</code>, no recomendado), br_self/br/ (<br/>), lsep/u2028 (Unicode LINE SEPARATOR U+2028), nl/soft (\n — en Chatwoot queda inline), slash/slash_nl (\\\n trailing-backslash hard break), spaced_br (<br> con espacios). Cualquier otro valor se usa literal. Permite iterar sin rebuild si tu downstream tiene un renderer markdown distinto. Desde v0.40.1. |
QRSGEN_HEADER_TEMPLATE |
`$phone · $name` |
Template del header de sender en group prefix y reactions. Tokens: $phone (E.164 con +), $name (nombre canónico con ~ automático si no saved). Ejemplos: `$phone` · **$name** (phone en code + bold name), $phone \| $name (plano), [$phone] $name (con corchetes). El ~ para no-saved está integrado vía IsContactSaved — el operador solo elige el wrapper visual. Solo aplica cuando hay AMBOS phone y name; sin uno de ellos cae a formato fijo `phone:` o `~name:`. Desde v0.45.0. |
QRSGEN_REACTION_HEADER_SEP |
nl |
Separador entre el header y el verb (reaccionó con 👍) en reacciones. Distinto del QRSGEN_GROUP_HEADER_SEP porque la reacción es más compacta visualmente. Default nl (\n) — single line break. Mismos alias que QRSGEN_GROUP_HEADER_SEP. Desde v0.45.1. |
QRSGEN_MENTION_TEMPLATE |
@$name |
Template para sustituir @<jid_user> inline por @<nombre>. WhatsApp envía las menciones como @148855681191942 (LID raw) + array ContextInfo.MentionedJID. qrsgen las une y muestra el nombre legible. Tokens: $name (con ~ automático si no saved), $phone (E.164). Vacío desactiva la feature. Ejemplos: @$name (default), @$name ($phone), **$name**. Desde v0.53.0. |
QRSGEN_REACTION_AS_REPLY |
true |
Si true, las reacciones WhatsApp se postean al downstream con content_attributes.in_reply_to apuntando al msg target → Chatwoot renderiza la reacción como quote-reply visual del msg original (el agente ve a qué se reaccionó). Si el msg target no está tracked (pre-v0.44.0), degrada al formato standalone. Desactivar si tu downstream no renderiza in_reply_to o prefieres msg suelto. Desde v0.53.2. |
QRSGEN_HISTORY_IMPORT_ENABLED |
false |
Si true, qrsgen procesa los blobs de *events.HistorySync que recibe (al parear instancias o como respuesta on-demand) y postea los msgs históricos al downstream con created_at backdated + source_id=WAID:<id> para idempotencia. Opt-in por implicaciones de volumen (puede ser cientos de POSTs en una pasada). Desde v0.46.0. |
QRSGEN_HISTORY_IMPORT_DAYS |
7 |
Cuántos días hacia atrás importar. Clamped a [1, 30]. WhatsApp limita el histórico que devuelve según ajustes del phone — pedir 30 cuando el phone solo guarda 7 da los 7. Desde v0.46.0. |
QRSGEN_HISTORY_IMPORT_RATE_PER_SEC |
5 |
Límite de POST/s al downstream durante el import — evita bursts que estresen Chatwoot. Aumentar con cuidado (>20 puede generar rate limits en el backend). Desde v0.46.0. |
QRSGEN_GROUP_EVENTS_ENABLED |
false |
Si true, qrsgen propaga *events.GroupInfo (cambios de nombre/topic/miembros/lock/announce/ephemeral), *events.JoinedGroup (bot añadido a un grupo nuevo) y *events.IdentityChange (código de seguridad cambia) como activity msgs en la conv del grupo/contacto en Chatwoot. Default false (opt-in). Desde v0.47.0. |
QRSGEN_AVATAR_SYNC |
true |
Si true, qrsgen descarga la foto de perfil WhatsApp del contacto/grupo al crear el contact en downstream y la sube como avatar via PUT multipart. Fire-and-forget (no bloquea el msg). false desactiva la sincronización; los contactos quedan con letter-avatar autogenerado. Desde v0.31.0. |
QRSGEN_AVATAR_REFRESH_TTL |
24h |
Si > 0, contactos existentes se re-chequean cada este TTL para detectar cambios de foto WhatsApp. La comparación usa el info.ID (cheap metadata, no descarga); solo se descarga + sube si el ID cambió. 0 desactiva el refresh (solo sync al crear). Desde v0.31.1. |
QRSGEN_REACTIONS_SYNC |
true |
Si true, las reacciones (emojis) que los clientes WhatsApp añaden a mensajes se postean al downstream como mensaje incoming. Desde v0.39.7 el formato se alinea con el prefijo de grupo v0.39.6: `+<E164> · <~?>name reaccionó con <emoji>` (línea completa en inline code block, phone-first, middle dot · como separador, tilde solo si el contacto no está guardado). Reacción retirada (text=""): `+<E164> · <~?>name quitó su reacción` (sin italic — markdown no se procesa dentro de inline code). false las ignora silenciosamente. Desde v0.33.0 (formato actualizado en v0.39.7). |
QRSGEN_TYPING_SYNC |
true |
Si true, los eventos de typing (composing/paused) que emite WhatsApp se propagan al downstream como toggle_typing_status — el agente ve "está escribiendo" en la UI. Throttle interno de 4s para evitar saturar. false ignora los eventos. Desde v0.34.0. |
QRSGEN_READ_RECEIPTS_SYNC |
true |
Si true, los read receipts WhatsApp (cliente abrió el chat y vio los mensajes del agente) actualizan el contact_last_seen_at del conv en el downstream — la UI marca los mensajes como leídos. false los ignora. Desde v0.34.1. |
QRSGEN_MARK_AS_READ_OUTGOING |
true |
Si true, qrsgen rastrea los WAIDs de mensajes incoming y los marca como leídos en WhatsApp cuando el downstream envía un webhook conversation_updated con un nuevo agent_last_seen_at. El cliente ve doble check azul. REQUIERE config explícita del downstream para enviar ese evento. Desde v0.39.0. |
QRSGEN_RETROACTIVE_NAME_UPDATE |
true |
Si true, qrsgen recuerda mensajes posteados con prefix de grupo "no-saved" (~Name) y los reescribe vía PATCH cuando el dueño añade el contacto a su agenda WhatsApp. El histórico en el downstream pasa a mostrar el nombre canónico sin tilde. State in-memory: restart pierde el tracked. Desde v0.40.0. |
QRSGEN_RETROACTIVE_CAP_PER_SENDER |
200 |
Cap de mensajes recordados por sender en el tracker de retroactive name update. Al desbordar, los más viejos caen FIFO. >100 da margen para que el update llegue tras horas/días. Desde v0.40.0. |
QRSGEN_RETROACTIVE_PERSIST |
true |
Si true, el tracker de retroactive name update persiste sus entries en la tabla bridge_msg_history (Postgres). El histórico sobrevive a restart y deploys. false → modo in-memory only (v0.40.0): restart pierde tracked. Desde v0.41.0. |
QRSGEN_RETROACTIVE_TTL |
720h |
Cuánto tiempo conservar las entries en DB. Tras este TTL el cron de cleanup (cada 6h) las borra. Default 30 días. Trade-off: más TTL → más capacidad de actualizar mensajes viejos, más espacio en DB. Desde v0.41.0. |
DEDUP_ENABLED |
true |
|
DEDUP_WINDOW_MS |
10000 |
Ventana LID-twin dedup. |
LOG_LEVEL |
info |
debug / info / warn / error. |
OVERLAY_NETWORK |
net |
Red docker overlay externa. |
PORT |
3100 |
HTTP listener. |
Glosario¶
Variable de entorno: parámetro de configuración que el proceso lee
al arrancar via os.Getenv. qrsgen las parsea con caarlos0/env.
Required vs optional: una env required hace fallar el boot si está ausente o vacía. Las optional tienen default.
Default value: valor que toma una env si no se pasa. qrsgen usa defaults razonables para el 90% de casos.
Backward-compat: cuando una env nueva opt-in queda desactivada por default para que despliegues antiguos sigan funcionando sin tocar config.
Opt-in: feature que requiere activación explícita (env=true o similar). Filosofía conservadora — más seguro que opt-out.
Token / Bearer: credencial de auth que qrsgen exige en
Authorization: Bearer .... Generar con secrets.token_urlsafe(32).
HMAC secret: string usado como clave para firmar/verificar HMACs del webhook entrante. Debe ser largo y aleatorio.
DSN (Data Source Name): cadena de conexión a la base de datos. qrsgen
la construye internamente desde POSTGRES_HOST/USER/DB/PASSWORD.