# Onboarding hospedado (o seu cliente conecta o número dele)

`POST /v1/onboarding-links`

Quando o número é do seu cliente e você não quer pedir as credenciais da Meta dele, ele mesmo conecta o WhatsApp numa página com **a sua marca** — sem login, sem ver a nossa marca, sem que você toque no app da Meta. Há **duas formas**, escolha a sua:

**1. Mande um link (sem código).** Você gera o link no painel (Números → 'Enviar link a um cliente') e o passa você mesmo (por WhatsApp, e-mail, o que for). Ideal para conectar clientes um a um. Você não precisa escrever nada.

**2. Integre no seu sistema (com código).** O seu cliente toca em 'Conectar WhatsApp' dentro do SEU produto e se conecta sozinho, sem que você intervenha. O fluxo: o seu backend chama `POST /v1/onboarding-links` com `label`, `externalId` (e `returnOrigin` se for usar popup) → recebe uma `url` → você o manda para lá por **redirecionamento** (o mais robusto, recomendado no celular) ou **popup** (parece embutido). Quando termina, o resultado chega por `postMessage` E pelo webhook `connection.created` com o seu `externalId`. O snippet de frontend e os exemplos de backend estão abaixo.

Nos dois casos você pode fixar o modo (`cloud_api`/`coexistence`; se omitir, a página conecta por Coexistence sem oferecer escolha) e o idioma da página (`lang`: es/it/en/pt, ou omitir para detectar pelo navegador). O token é de **uso único** e vence: o vencimento é configurável (`expiresIn` em segundos, de 5 min a 30 dias) — pela API o padrão é **1 hora**, pelo painel **7 dias**.

## Exemplos

### 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)
```

Você gera um link com a marca do seu cliente; ele conecta o número dele sem entrar no seu painel nem ver a nossa marca. Você recebe `connection.created` com o seu `externalId`. O detalhe completo (diagrama, snippet de popup e por que nunca em um iframe) está dentro do painel, com os seus dados reais.

## Notas

- A URL (com o token) é devolvida UMA única vez, como uma API key — mande-a e guarde-a.
- O token só é consumido quando a **conexão é criada**, não ao abrir a página. Se o seu cliente fechar a janela ou a internet cair, ele **abre de novo o MESMO link** e continua — até vencer.
- **O webhook é a fonte confiável.** O `postMessage` se perde se o seu cliente fechar a janela; o webhook `connection.created` não. Confirme do lado do servidor com esse evento.
- ⚠ **Nunca dentro de um iframe:** o popup do Embedded Signup quebra ali (restrições de popup + bloqueio de cookies de terceiros). Use redirecionamento ou popup de primeiro nível.
- Para o **popup**, `returnOrigin` é obrigatório: é a origem https exata à qual respondemos (nunca `*`), validada ao criar o link.
- O seu cliente NUNCA vê a nossa marca nem entra no seu painel; você NUNCA entra na conta da Meta dele. Configure a sua marca em Ajustes → Marca.
- Estados do link: `pending` (sem uso), `used` (já conectou), `expired` (venceu), `revoked` (você cancelou). Revogue um pendente com `DELETE /v1/onboarding-links/:id`.
- **Seção Links do painel:** ali você vê os que mandou (os dois tipos), para qual cliente, quando vencem e o andamento — **não aberto** / **aberto e não concluído** / **concluído**. Um link sem atividade era ambíguo: não havia como distinguir "não viu" de "travou no formulário", que pedem ações diferentes.
- 🔒 Da abertura registramos **só que aconteceu e quando** (primeira, última e quantas vezes). **Nada do visitante**: nem IP, nem navegador, nem referer. `GET /v1/onboarding-links` devolve `engagement`, `firstOpenedAt`, `lastOpenedAt` e `openCount`.
- Pelo painel você pode **copiar de novo a URL** de um link que continue vivo (owner/admin, auditado). A de um usado/vencido/revogado não é revelada: não serve para nada.
