Documentazione / Completo
Percorso dell'integratore: attivazione e webhook 100 % via API
GET /v1/onboarding-links/{id}
Se attivi i tuoi clienti dal tuo sistema, senza entrare nel pannello, questo è il percorso completo, in cinque passi.
1. Un link per cliente. POST /v1/onboarding-links con il tuo externalId (il tuo id per quel cliente) e webhook: { url }. Ti restituiamo l'url per il tuo cliente e il segreto whsec_… del webhook una sola volta: salvalo subito, firma tutto ciò che riguarda quel cliente. Un externalId già usato da un altro numero del tuo account dà 409 in questo momento, non alla fine dell'attivazione.
2. Il tuo cliente si collega. Apre l'url, entra con il suo account Meta e sceglie il numero. Alla fine, il numero nasce con il suo webhook (l'URL del link) e lì arriva onboarding.completed, con connection.id (conn_…), il tuo externalId, reconnected e il webhookId. Un numero nuovo porta anche connection.created, come sempre.
3. Se non finisce, lo sai lo stesso. Ogni tentativo interrotto (fallito, annullato o abbandonato) manda onboarding.failed all'URL del webhook del link, firmato con lo stesso segreto: reason (meta_error, incomplete, timeout, cancelled, abandoned…), metaErrorCode e metaMessage se Meta li ha dati, e linkUsable (se il tuo cliente può riprovare con lo stesso link). Se preferisci chiedere: GET /v1/onboarding-links?externalId=… o GET /v1/onboarding-links/{id} restituiscono outcome (pending, completed o failed, con lo stesso motivo).
4. Il webhook del numero è tuo. Lo vedi e lo modifichi con /v1/webhooks?externalId=…: URL, eventi, intestazione fissa, ruotare il segreto, provarlo.
5. La disattivazione. Quando il numero si scollega (dal pannello, perché l'azienda ci ha tolto l'accesso su Meta o perché il permesso è stato revocato), il suo webhook viene spento (active: false, disabledReason: "connection_disconnected") e smette di ricevere. Se si ricollega lo stesso numero, si riaccende da solo; quelli che hai messo in pausa tu o che abbiamo spento per errori, no.
# 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 onSenza webhook nel link, onboarding.completed e onboarding.failed vanno ai webhook dell'account (in onboarding.failed, connection.id è null: il tuo externalId è in data).
Un webhook con events esplicito che non include questi tipi non li riceve; uno con tutti gli eventi inizia a riceverli.
Nei link di attivazione, connectionId ora esce come conn_…; l'id interno resta in legacyConnectionId, che verrà ritirato.
outcome.state = failed anche quando il link è scaduto (link_expired) o l'hai annullato (link_revoked) prima che il cliente finisse.