Documentação / Completo
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.
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.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.
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.