# Onboarding hospedado (tu cliente conecta su número)

`POST /v1/onboarding-links`

Cuando el número es de tu cliente y no querés pedirle sus credenciales de Meta, conecta él mismo su WhatsApp en una página con **tu marca** — sin login, sin ver nuestra marca, sin que vos toques la app de Meta. Hay **dos formas**, elegí la tuya:

**1. Mandale un link (sin código).** Generás el link desde el panel (Números → 'Enviar link a un cliente') y se lo pasás vos (por WhatsApp, mail, lo que sea). Ideal para conectar clientes de a uno. No necesitás escribir nada.

**2. Integralo en tu sistema (con código).** Tu cliente toca 'Conectar WhatsApp' dentro de TU producto y se conecta solo, sin que intervengas. El flujo: tu backend llama `POST /v1/onboarding-links` con `label`, `externalId` (y `returnOrigin` si vas a usar popup) → recibe una `url` → lo mandás ahí por **redirección** (la más robusta, recomendada en móvil) o **popup** (se siente embebido). Cuando termina, el resultado te llega por `postMessage` Y por el webhook `connection.created` con tu `externalId`. El snippet de frontend y los ejemplos de backend están abajo.

En ambos casos podés fijar el modo (`cloud_api`/`coexistence`, u omitir para que elija tu cliente) y el idioma de la página (`lang`: es/it/en/pt, u omitir para detectarlo del navegador). El token es de **un solo uso** y vence: el vencimiento es configurable (`expiresIn` en segundos, 5 min–30 días) — por API el default es **1 hora**, desde el panel **7 días**.

## Ejemplos

### cURL

```bash
curl -X POST https://api.waiaconnect.com/v1/onboarding-links \
  -H "Authorization: Bearer wc_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"label":"López Pharmacy","externalId":"pharmacy-42","lang":"es","returnOrigin":"https://app.yourcompany.com","expiresIn":3600}'
# → { "url": "https://…/c/<token>", "expiresAt": "…", "publicId": "onb_…" }
# Send url to your customer. It is shown ONCE; the token is consumed only when they connect.
```

### Node.js

```javascript
// Call this from YOUR backend when your customer taps "Connect WhatsApp".
const res = await fetch("https://api.waiaconnect.com/v1/onboarding-links", {
  method: "POST",
  headers: { "Authorization": "Bearer wc_live_YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
  "label": "López Pharmacy",
  "externalId": "pharmacy-42",
  "lang": "es",
  "returnOrigin": "https://app.yourcompany.com",
  "expiresIn": 3600
})
});
const { url } = await res.json(); // https://…/c/<token> — hand this to the browser (redirect or popup)
```

### PHP

```php
<?php
// Call this from YOUR backend when your customer taps "Connect WhatsApp".
$ch = curl_init("https://api.waiaconnect.com/v1/onboarding-links");
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer wc_live_YOUR_API_KEY", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => json_encode(["label" => "López Pharmacy","externalId" => "pharmacy-42","lang" => "es","returnOrigin" => "https://app.yourcompany.com","expiresIn" => 3600]),
]);
$out = json_decode(curl_exec($ch), true);
echo $out["url"]; // https://…/c/<token> — hand this to the browser (redirect or popup)
```

### Python

```python
import requests
# Call this from YOUR backend when your customer taps "Connect WhatsApp".
res = requests.post("https://api.waiaconnect.com/v1/onboarding-links",
  headers={"Authorization": "Bearer wc_live_YOUR_API_KEY", "Content-Type": "application/json"},
  json={"label":"López Pharmacy","externalId":"pharmacy-42","lang":"es","returnOrigin":"https://app.yourcompany.com","expiresIn":3600})
res.raise_for_status()
print(res.json()["url"])  # https://…/c/<token> — hand this to the browser (redirect or popup)
```

Generás un link con la marca de tu cliente; él conecta su número sin entrar a tu panel ni ver nuestra marca. Recibís `connection.created` con tu `externalId`. El detalle completo (diagrama, snippet de popup, y por qué nunca en un iframe) está dentro del panel, con tus datos reales.

## Notas

- La URL (con el token) se devuelve UNA sola vez, como una API key — mandala y guardala.
- El token se consume recién cuando se **crea la conexión**, no al abrir la página. Si tu cliente cierra la ventana o se le corta internet, **vuelve a abrir el MISMO link** y sigue — hasta que venza.
- **El webhook es la fuente confiable.** El `postMessage` se pierde si tu cliente cierra la ventana; el webhook `connection.created` no. Confirmá del lado del servidor con ese evento.
- ⚠ **Nunca dentro de un iframe:** el popup del Embedded Signup se rompe ahí (restricciones de popup + bloqueo de cookies de terceros). Usá redirección o popup de primer nivel.
- Para el **popup**, `returnOrigin` es obligatorio: es el origen https exacto al que respondemos (nunca `*`), validado al crear el link.
- Tu cliente NUNCA ve nuestra marca ni entra a tu panel; vos NUNCA entrás a su cuenta de Meta (PRODUCTO §7.3). Configurá tu marca en Ajustes → Marca.
- Estados del link: `pending` (sin usar), `used` (ya conectó), `expired` (venció), `revoked` (lo cancelaste). Revocá uno pendiente con `DELETE /v1/onboarding-links/:id`.
- **Sección Enlaces del panel:** ahí ves los que mandaste (los dos tipos), a qué cliente, cuándo vencen, y su avance — **sin abrir** / **abierto y sin completar** / **completado**. Un enlace sin actividad era ambiguo: no había forma de distinguir "no lo vio" de "se trabó en el formulario", que piden acciones distintas.
- 🔒 De la apertura registramos **sólo que ocurrió y cuándo** (primera, última, y cuántas veces). **Nada del visitante**: ni IP, ni navegador, ni referer. `GET /v1/onboarding-links` devuelve `engagement`, `firstOpenedAt`, `lastOpenedAt` y `openCount`.
- Desde el panel podés **volver a copiar la URL** de un enlace que siga vivo (owner/admin, auditado). La de uno usado/vencido/revocado no se revela: no sirve para nada.
