# Alta de un cliente nuevo
Qué hay que pedirle a cada taller y qué hacemos nosotros, para poner en marcha el bot de
reservas por WhatsApp. El detalle técnico de las piezas está en [whatsapp.md](whatsapp.md);
acá está el orden operativo y quién hace cada cosa.
Cada cliente necesita **su propia** cuenta de Meta, su propia app y su propio número.
Nada se comparte entre clientes: ni el token, ni el App Secret, ni el número.
`Taller Beldor` es nuestro ambiente de pruebas y no sirve como cuenta productiva de nadie.
Tiempo realista: **varios días**. La configuración activa lleva una tarde, pero Meta mete
esperas que no se pueden apurar: la revisión de la cuenta, la aprobación del Display Name y
la liberación del número de WhatsApp. Planificar el alta con margen, nunca para el mismo día.
> **Lo que más caro sale es equivocarse en el orden.** Varios pasos dependen de otros de
> forma no evidente, y reintentarlos deja basura que después bloquea. Las secciones están en
> el orden en que hay que hacerlas.
---
## 0. Antes de tocar nada: los cuatro preparativos
Estos cuatro se resuelven **antes** de abrir el panel de Meta. Saltearlos es lo que nos costó
una jornada entera en el alta de Taller Beldor.
1. **El teléfono del titular tiene que estar confirmado en el Centro de cuentas.**
No alcanza con tenerlo a mano: Meta exige que ya esté confirmado antes de dejar verificar
la cuenta de desarrollador, y el mensaje de error no lo dice así.
2. **El nombre del negocio y el del sitio web tienen que coincidir.**
Meta compara el nombre declarado contra el `
` del sitio que se declara como
respaldo. Si no coinciden, rechaza el alta con el error de política `#2494070`, que no
explica la causa.
3. **El sitio tiene que servir contenido público.** Una raíz que redirige al login no sirve:
el verificador de Meta ve una pantalla vacía. Hace falta al menos una home con el nombre
del taller y qué hace.
4. **Una política de privacidad en una URL pública.** Es requisito para publicar la app, y
sin publicar la app Meta no entrega datos de producción al webhook.
---
## 1. Lo que le pedimos al cliente antes de empezar
Conviene mandarle esta lista completa de entrada, porque casi todo depende de él.
| Qué | Para qué | Cuidado |
|---|---|---|
| Quién va a ser **titular** de la cuenta de Meta | Todo cuelga de esa cuenta | Si es el dueño, mejor; si es un empleado y se va, se complica |
| **Cuenta de Facebook** de esa persona, con sesión iniciada | Es la puerta de entrada a todo | — |
| **Celular con SMS** para verificar esa cuenta | Meta exige verificar la cuenta de desarrollador | **El número tiene que estar confirmado en el Centro de cuentas ANTES de empezar** |
| **Nombre público exacto** del taller | Nombre del portfolio comercial y base del Display Name | Sin caracteres especiales |
| **Email del negocio** | Contacto del portfolio y de la app | Tiene que poder recibir el mail de verificación |
| **Número de WhatsApp** que va a atender | Es el número del bot | **No puede estar activo en WhatsApp normal ni Business** (ver punto 5) |
| **Jefes mecánicos** con nombre | El bot los ofrece como botones | Más de 3 → los primeros 3 son botón, el resto se elige por número |
| **Tipos de servicio** y duración | El bot los ofrece después del mecánico | Pueden ser globales o propios de cada jefe |
| **Horarios de atención** | Cálculo de los turnos disponibles | — |
## 2. Cuentas de Meta — lo hace el cliente, nosotros guiamos
Son actos que quedan a nombre del cliente: aceptan condiciones legales y crean cuentas.
**Nosotros no los hacemos por él**, aunque estemos compartiendo pantalla.
1. **Confirmar el teléfono** en el Centro de cuentas → Perfiles y datos personales →
Información de contacto → Agregar número → **Confirmar número** con el código del SMS.
2. **Portfolio comercial** en `business.facebook.com`: nombre del negocio, su nombre, email.
3. **Cuenta de desarrollador** en `developers.facebook.com` → "Empezar". Cuatro pasos:
Register (acepta condiciones) → Verify account (el SMS) → Contact info → About you.
4. **Crear la app**: tipo Business, caso de uso **"Conectarte con los clientes a través de
WhatsApp"**, vinculada al portfolio del paso 2.
El **nombre de la app no puede contener "WhatsApp", "Facebook" ni "Insta"**: Meta los
rechaza. Es un nombre interno, no el que ven los clientes.
> **El SMS es el punto donde más veces se traba el alta.** Si no llega: verificar que el
> número ya esté confirmado en el Centro de cuentas (es un SMS distinto del de la cuenta de
> desarrollador), revisar la bandeja de spam del teléfono, y **no reintentar muchas veces
> seguidas** — Meta deja de entregar los códigos por un rato sin avisar. Si pasó eso,
> esperar unas horas y pedir uno solo.
### Reintentar tiene costo: cada intento fallido deja una WABA huérfana
El asistente de alta **crea la cuenta de WhatsApp Business antes de validar el formulario**.
Si el alta falla después de ese punto, la cuenta queda igual, vacía y contando para el cupo.
Un portfolio sin verificar admite pocas, así que a los pocos reintentos aparece el error
`#2494067` ("Se alcanzó el límite de cuentas de WhatsApp Business").
En el alta de Taller Beldor quedaron **seis cuentas, cinco de ellas basura**, y hubo que
borrarlas a mano para poder seguir. Conclusión práctica: **no reintentar a ciegas**. Si el
alta falla, averiguar la causa antes del siguiente intento, y revisar después en
Business Suite → Cuentas de WhatsApp si quedaron cuentas vacías para borrar.
### El campo "Sitio web" es obligatorio
Figura como opcional en algunas pantallas pero el formulario no deja avanzar sin él. Y el
sitio que se declare es el que Meta va a comparar contra el nombre del negocio (ver punto 0).
## 3. Credenciales — las saca el cliente, nosotros no las tocamos
Las cuatro variables del `.env`. **Nunca pasan por chat, mail ni WhatsApp**: el cliente las
copia de la pantalla de Meta y las pega directo en el `.env` del servidor, o nos da acceso
al servidor y las carga él ahí.
| Variable | De dónde sale | Forma esperada |
|---|---|---|
| `WHATSAPP_PHONE_NUMBER_ID` | Caso de uso WhatsApp → Paso 1 "Pruébalo" | Numérico, ~16 dígitos. **No es el teléfono** |
| `WHATSAPP_TOKEN` | Business Settings → Usuarios del sistema → Generar token | **Empieza con `EAA`**, ~200 chars |
| `WHATSAPP_VERIFY_TOKEN` | Lo inventamos nosotros | Alfanumérico, sin símbolos ni espacios |
| `WHATSAPP_APP_SECRET` | App → Configuración → Básica → "Mostrar" | **32 caracteres hexadecimales** |
**System user** (de donde sale el token):
- Crear uno por cliente, por ejemplo `taller-bot`, rol Employee.
- Asignarle **dos activos**: la app (permiso *Desarrollar app*) y la cuenta de WhatsApp
(permisos *Mensajes* y *Números de teléfono — ver y administrar*).
- Generar token con caducidad **Nunca** y los permisos `whatsapp_business_messaging` y
`whatsapp_business_management`.
- **El token se muestra una sola vez.** Tener el `.env` abierto antes de apretar el botón.
Errores que ya nos pasaron y conviene chequear:
- Token **cortado al copiar**: si no empieza con `EAA`, está incompleto.
- Placeholders sin reemplazar: que no queden `<...>` en el `.env`.
- `APP_SECRET` que no tiene 32 hex: quedó truncado.
- Sin `APP_SECRET` correcto, **el webhook rechaza todo con 403** y no entra ningún mensaje.
## 4. Lo que hacemos nosotros
1. Desplegar la app para ese cliente con su dominio propio y certificado válido.
Meta **exige HTTPS** para el webhook.
2. Cargar las 4 variables en el `.env` de ese despliegue y `docker compose up -d`.
El `.env` no está en el repo: un `git push` no lo toca.
3. Verificar el webhook **antes** de darlo de alta en Meta:
```bash
curl "https:///api/whatsapp/webhook?hub.mode=subscribe&hub.verify_token=&hub.challenge=12345"
```
Tiene que devolver exactamente `12345` en texto plano. Si devuelve 403, la variable no
llegó al contenedor.
4. Verificar que el token funciona contra la Graph API:
```bash
curl "https://graph.facebook.com/v21.0/?fields=display_phone_number,verified_name" \
-H "Authorization: Bearer "
```
5. Dar de alta el webhook en Meta: **Paso 2 → Configurar webhooks**, con la Callback URL del
cliente y el mismo verify token. Meta suscribe **`messages`** solo al guardar; verificar
que el aviso aparezca, porque sin esa suscripción no llega ningún mensaje.
6. **Suscribir la app a la WABA.** Es una segunda suscripción, distinta de la anterior y
fácil de pasar por alto: el campo `messages` se suscribe a nivel app, pero además la app
tiene que estar asociada a esa cuenta de WhatsApp. Si falta, Meta recibe los mensajes y
los entrega a su propia app de pruebas, no al webhook del cliente.
```bash
curl -X POST "https://graph.facebook.com/v21.0//subscribed_apps" \
-H "Authorization: Bearer "
```
Verificar que el nombre de la app aparezca al consultar ese mismo endpoint con GET.
**Ojo:** si se crea una WABA nueva, hay que rehacer esta suscripción — es por WABA.
7. Cargar los datos del taller: jefes mecánicos, tipos de servicio y horarios.
8. Probar punta a punta, mirando `docker logs -f taller_app`.
El endpoint **solo escribe en el log cuando algo falla**, así que un mensaje que entra
bien es silencioso: la confirmación real es que aparezcan filas en
`MensajeWhatsappProcesado` y `ConversacionWhatsapp`.
> **Los números de prueba de Meta no sirven para probar el bot.** El que regala el panel
> queda en `status: PENDING`, no se le puede escribir, no envía (`133010 Account not
> registered`) y no acepta `/register`. Sirve para los ejemplos de curl de la documentación,
> nada más. La prueba punta a punta necesita el número real ya conectado.
## 5. Migrar el número real del taller
El último paso, el que más fricción genera con el cliente y donde está la espera más larga.
- El número **no puede estar activo en la app de WhatsApp normal o Business**. Hay que
**borrar esa cuenta** antes de migrarlo a Cloud API. Se pierde el historial de chats.
- Avisarle al cliente con tiempo: si el taller venía atendiendo por ese número, va a querer
elegir el momento.
- Después de liberarlo, Meta tarda **hasta 3 minutos** en actualizar el estado. Si al
cargarlo dice que sigue registrado, esperar y reintentar: no falló el borrado.
### Verificar el número NO es lo mismo que conectarlo
Son dos cosas distintas y el número tiene un campo para cada una:
| Campo | Qué significa | Cómo se consigue |
|---|---|---|
| `code_verification_status: VERIFIED` | El cliente probó que la línea es suya | Código por SMS o llamada |
| `status: CONNECTED` | El número está operativo sobre Cloud API | Lo aprovisiona Meta |
**Un número en `PENDING` no envía ni recibe, y ni siquiera existe en WhatsApp**: si se
intenta escribirle desde otro teléfono, WhatsApp solo ofrece "Invitar". Entre que se borra la
cuenta común y que Meta lo conecta, el número queda en tierra de nadie. Es el estado normal
durante la espera, no un error de configuración.
### La revisión de la cuenta bloquea todo, y no se puede apurar
Mientras la cuenta de WhatsApp Business figure **`Pending review`**, Meta deshabilita el
botón "Registrar" del Paso 2 con este mensaje:
> "Number registration and webhook subscription are unavailable for this account now."
No hay nada que configurar mientras tanto. Es el cuello de botella real del alta: **planificar
el alta de cada cliente contando con esta espera**, y no prometerle una fecha hasta que la
cuenta salga de revisión.
- El **Display Name** necesita aprobación, pero suele salir sin revisión
(`name_status: AVAILABLE_WITHOUT_REVIEW`) si coincide con el nombre del negocio.
- La **Business Verification** se saltea mientras el cliente esté abajo de 1000 usuarios
únicos cada 24hs. Para un taller eso es muchísimo, así que en la práctica no aplica.
## 6. Costos a aclarar antes de vender
- El flujo del bot ocurre **dentro de la ventana de 24hs que abre el cliente final**, así que
**no usa plantillas aprobadas y no tiene costo por conversación**.
- Si en algún momento se quisiera que el taller **inicie** la conversación (recordatorios de
turno, por ejemplo), eso **sí** requiere plantillas aprobadas y **sí** tiene costo.
Hoy el bot no lo hace.
## 7. Manejo de credenciales
Vale para todos los clientes y no es negociable:
- **Las credenciales no viajan por chat, mail ni WhatsApp.** Van de la pantalla de Meta al
`.env` del servidor, directo. Un token pegado en una conversación queda registrado ahí para
siempre y hay que revocarlo y regenerarlo.
- **El token de System User se muestra una sola vez.** Tener el `.env` abierto antes.
- Para verificar sin exponer valores, chequear **largo y prefijo** en vez de imprimirlos:
```bash
docker exec sh -c 'v=$(printenv WHATSAPP_TOKEN); echo "${#v} chars"'
```
- **Cuidado con los mensajes de error de la Graph API**: cuando un token es inválido, la
respuesta lo devuelve completo en el campo `message`. No volcar esas respuestas crudas en
un log compartido ni en una conversación.
- El PIN de verificación en dos pasos del número lo elige el cliente y conviene que lo anote:
Meta lo pide si alguna vez hay que re-registrar el número.