Documentação / Completo
Percurso do integrador: cadastro e webhooks 100 % por API
GET /v1/onboarding-links/{id}
Se você cadastra seus clientes a partir do seu sistema, sem entrar no painel, este é o caminho inteiro, em cinco passos.
1. Um link por cliente. POST /v1/onboarding-links com o seu externalId (o seu id para esse cliente) e webhook: { url }. Devolvemos a url para o seu cliente e o segredo whsec_… do webhook uma única vez: guarde já, ele assina tudo desse cliente. Um externalId que outro número da sua conta já usa dá 409 neste momento, não no fim do cadastro.
2. O seu cliente conecta. Abre a url, entra com a conta da Meta e escolhe o número. Ao terminar, o número já nasce com o seu webhook (a URL do link) e chega ali onboarding.completed, com connection.id (conn_…), o seu externalId, reconnected e o webhookId. Um número novo também traz connection.created, como sempre.
3. Se não terminar, você fica sabendo do mesmo jeito. Cada tentativa interrompida (falhou, foi cancelada ou abandonada) manda onboarding.failed para a URL do webhook do link, assinado com o mesmo segredo: reason (meta_error, incomplete, timeout, cancelled, abandoned…), metaErrorCode e metaMessage se a Meta os deu, e linkUsable (se o seu cliente pode tentar de novo com o mesmo link). Se preferir perguntar: GET /v1/onboarding-links?externalId=… ou GET /v1/onboarding-links/{id} trazem outcome (pending, completed ou failed, com o mesmo motivo).
4. O webhook do número é seu. Veja e altere com /v1/webhooks?externalId=…: URL, eventos, cabeçalho fixo, rotacionar o segredo, testar.
5. O desligamento. Quando o número é desconectado (pelo painel, porque o negócio nos tirou o acesso na Meta ou porque a permissão foi revogada), o webhook dele fica desligado (active: false, disabledReason: "connection_disconnected") e para de receber. Se o mesmo número reconectar, ele volta sozinho; os que você pausou ou os que desligamos por falha, não.
# 1) one link per end-customer: your id + the webhook its number will have
curl -X POST https://api.waiaconnect.com/v1/onboarding-links \
-H "Authorization: Bearer wc_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"externalId": "pharmacy-42", "label": "Pharmacy 42", "mode": "coexistence",
"webhook": {"url": "https://api.yourcompany.com/hooks/connect"}}'
# → 201 { "publicId": "onb_…", "url": "https://…/c#<token>", "expiresAt": "…",
# "webhook": { "secret": "whsec_…", "createdOnCompletion": true, … } } ← store the secret NOW
# 2) send "url" to your customer. Then, on https://api.yourcompany.com/hooks/connect:
# { "type": "onboarding.completed", "connection": { "id": "conn_…", "externalId": "pharmacy-42", … },
# "data": { "onboardingLinkId": "onb_…", "reconnected": false, "webhookId": "wh_…", … } }
# { "type": "onboarding.failed", "connection": { "id": null, … },
# "data": { "externalId": "pharmacy-42", "reason": "meta_error", "metaErrorCode": 2655093,
# "metaMessage": "The business is already sharing…", "linkUsable": true, … } }
# 3) or ask (polling) by your id
curl "https://api.waiaconnect.com/v1/onboarding-links?externalId=pharmacy-42" -H "Authorization: Bearer wc_live_YOUR_API_KEY"
# → { "links": [ { "id": "onb_…", "status": "used", "connectionId": "conn_…",
# "outcome": { "state": "completed", "connectionId": "conn_…", "webhookId": "wh_…", … } } ] }
curl https://api.waiaconnect.com/v1/onboarding-links/onb_… -H "Authorization: Bearer wc_live_YOUR_API_KEY"
# 4) the number's webhook, by your id (PATCH to change url/events, rotate-secret, test)
curl "https://api.waiaconnect.com/v1/webhooks?externalId=pharmacy-42" -H "Authorization: Bearer wc_live_YOUR_API_KEY"
# 5) offboarding: disconnecting the number switches its webhook off
# (active: false, disabledReason: "connection_disconnected"); reconnecting it switches it back onSem webhook no link, onboarding.completed e onboarding.failed vão para os webhooks da conta (em onboarding.failed, connection.id vem null: o seu externalId vai em data).
Um webhook com events explícito que não inclui estes tipos não os recebe; um com todos os eventos passa a recebê-los.
Nos links de cadastro, connectionId agora sai como conn_…; o id interno fica em legacyConnectionId, que vai ser retirado.
outcome.state = failed também quando o link venceu (link_expired) ou você o revogou (link_revoked) antes de o cliente terminar.