> ## Documentation Index
> Fetch the complete documentation index at: https://docs.switchbord.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Meta Embedded Signup e Multi-WABA

> Come i workspace effettuano l'onboarding di Account WhatsApp Business aggiuntivi tramite Meta Embedded Signup, e come Switchbord mantiene isolato il token di accesso di ogni WABA al momento dell'invio.

I workspace Switchbord non sono più limitati a un singolo Account WhatsApp Business (WABA). Un workspace può fare l'onboarding di WABA aggiuntivi tramite il flusso **Embedded Signup** di Meta — il popup di accesso ospitato direttamente da Meta — senza mai dover gestire un access token copiato manualmente. Ogni WABA ottiene il proprio slot di credenziali isolato, così un secondo (o terzo) numero non sovrascrive mai il primo.

<Info>
  Embedded Signup è additivo. Il wizard originale "porta il tuo token" su `/welcome` è rimasto invariato ed è sempre disponibile — Embedded Signup è un secondo percorso opzionale per i workspace che preferiscono un onboarding ospitato da Meta invece di incollare un token System User.
</Info>

## Tre percorsi di onboarding

Quando Embedded Signup è abilitato, `/welcome` presenta un selettore (`OnboardingPathChooser`) con tre card invece di passare direttamente al wizard manuale:

| Percorso                                | Cosa fa                                                                                                                                                          | Componente                                     |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
| **Porta il tuo token**                  | Il wizard manuale originale — incolla tu stesso un token System User, un Phone Number ID e un WABA ID. Sempre disponibile, incluse le installazioni self-hosted. | `WelcomeWizard`                                |
| **Fai l'onboarding con noi**            | Accedi con Meta e registra un numero completamente nuovo con WhatsApp Business. Nessun copia/incolla di token.                                                   | `EmbeddedSignupCard` (`defaultPath="onboard"`) |
| **Migra un account WhatsApp esistente** | Accedi con Meta e sposta su Switchbord un numero già registrato con WhatsApp Business.                                                                           | `EmbeddedSignupCard` (`defaultPath="migrate"`) |

Scegliere "Fai l'onboarding con noi" o "Migra un account WhatsApp esistente" renderizza entrambi lo stesso `EmbeddedSignupCard` — l'unica differenza è il valore `path` (`onboard` vs `migrate`) inviato all'endpoint di scambio, e la UI di signup di Meta adatta il proprio testo di conseguenza. Una casella di controllo **Abilita Messaggi di Marketing** appare quando è configurato un config ID Meta con ambito marketing, e determina quale `config_id` di login Facebook viene utilizzato.

<Tip>
  Ogni schermata del selettore ha un pulsante "Scegli un metodo diverso" per tornare indietro, così un operatore che avvia Embedded Signup e incontra un vicolo cieco (ad blocker, popup chiuso, errore Meta) può sempre ricorrere al wizard manuale del token senza ricaricare la pagina.
</Tip>

## Feature flag e prerequisiti

Embedded Signup è disattivato per impostazione predefinita ed è vincolato **sia** a un flag client pubblico **sia** a credenziali dell'app lato server:

| Requisito                                                               | Dove                              | Effetto se assente                                                                                                                                   |
| ----------------------------------------------------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NEXT_PUBLIC_EMBEDDED_SIGNUP_ENABLED=1` (o `true`/`on`/`enabled`/`yes`) | Ambiente Vercel `apps/app`        | `/welcome` renderizza solo il wizard manuale — il selettore non appare mai                                                                           |
| `NEXT_PUBLIC_META_APP_ID` + `NEXT_PUBLIC_META_CONFIG_ID`                | Ambiente Vercel `apps/app`        | Il flag client si risolve come disabilitato anche se la variabile d'ambiente sopra è impostata (il Facebook JS SDK non può funzionare senza di essi) |
| `NEXT_PUBLIC_META_CONFIG_ID_MM` (opzionale)                             | Ambiente Vercel `apps/app`        | La casella "Abilita Messaggi di Marketing" viene nascosta; ogni signup usa la configurazione standard                                                |
| `META_APP_ID` + `META_APP_SECRET`                                       | Ambiente server Vercel `apps/app` | La route API di scambio (`/api/onboarding/meta/exchange`) risponde `404 embedded_signup_disabled` anche se la UI è visibile                          |

Il controllo lato server è deliberatamente una difesa a più livelli: attivare da solo il flag client non può mai esporre un flusso Embedded Signup funzionante senza che anche le credenziali dell'app siano configurate.

## Come funziona lo scambio

1. Il browser carica una volta il Facebook JS SDK (`connect.facebook.net/en_US/sdk.js`) e chiama `FB.login()` con il `config_id` risolto, richiedendo un `code` di autorizzazione.
2. Il popup di Meta invia anche un evento `postMessage` `WA_EMBEDDED_SIGNUP` (validato rispetto a un'origine `facebook.com` / `*.facebook.com`) che trasporta il `waba_id` e il `phone_number_id` selezionati dall'operatore all'interno della UI di Meta.
3. Una volta arrivati **entrambi** il `code` e la coppia WABA/telefono, la card invia (POST) una sola volta a `/api/onboarding/meta/exchange` con `{ code, wabaId, phoneNumberId, path, includeMarketingMessages }`.
4. La route (`apps/app/app/api/onboarding/meta/exchange/route.ts`) esegue una sequenza rigorosa lato server:
   * scambia il code con un access token business (`exchangeEmbeddedSignupCode`);
   * ispeziona il token con `debugToken` e richiede sia lo scope `whatsapp_business_management` che `whatsapp_business_messaging`;
   * se gli scope granulari di Meta enumerano gli ID WABA concessi, il `wabaId` fornito **deve** trovarsi in quella lista — un WABA id fornito dal client non è mai considerato attendibile alla cieca;
   * conferma che il numero di telefono appartenga effettivamente a quel WABA tramite `listWabaPhoneNumbers` prima di fare qualsiasi altra cosa;
   * genera e memorizza un PIN di registrazione a 6 cifre usa e getta (segreto `meta-phone-pin`) e chiama `registerPhoneNumberForCloudApi` — un fallimento di registrazione Meta (già registrato, mismatch 2FA in migrazione) viene tollerato e riportato come `phoneRegistered: false` invece di far fallire l'intera richiesta;
   * genera un token di verifica per workspace e sottoscrive l'app Switchbord al WABA con un `override_callback_uri` ambitato per workspace (`.../webhooks/meta?w=<workspaceId>`);
   * risolve in quale slot di credenziali rientra il token di questo WABA (vedi sotto), memorizza il token e importa il numero di telefono in un canale.
5. La risposta non contiene mai l'access token, il PIN, il verify token, `META_APP_SECRET`, né alcun `appsecret_proof` — solo `channelId`, `wabaId`, `phoneNumberId`, `displayName`, `phoneRegistered` e `marketingMessagesEnabled`.

<Warning>
  La route di scambio applica un invariante rigoroso contro la fuoriuscita di segreti: i campi `detail` nelle risposte di errore possono contenere esclusivamente il messaggio di errore già sanificato di Meta. Token, PIN, verify token e l'app secret non vengono mai registrati nei log, catturati nella telemetria delle eccezioni, né rimandati al browser.
</Warning>

## Isolamento del token Multi-WABA

Prima di questo lavoro, il token Meta di ogni workspace viveva sotto un unico tipo di segreto Vault (`meta-access-token`) — un secondo WABA collegato tramite Embedded Signup sovrascriveva silenziosamente il token del primo WABA e interrompeva i suoi invii. Switchbord ora risolve il token di ogni WABA in modo indipendente:

* L'account provider **predefinito** (il primo WABA in un workspace, o uno già contrassegnato come predefinito) continua a usare il tipo di segreto `meta-access-token` — i workspace con un solo WABA non sono affatto interessati.
* Ogni WABA **aggiuntivo** occupa il primo slot libero da `meta-access-token-2` a `meta-access-token-8` (`allocateWabaTokenSlotKind`), registrato su `whatsapp_provider_accounts.credential_secret_kind`. Otto slot superano comodamente qualsiasi conteggio realistico di WABA per workspace.
* `resolveChannelAccessToken(admin, { workspaceId, channelId | channel })` è il risolutore unico usato da ogni percorso critico di invio (dispatch dei messaggi — che copre anche gli invii di campagna — invii di media, invii interattivi e sincronizzazione dei template). Risolve canale → account provider → `credentialSecretKind`, legge quello slot Vault, e ricade sul `meta-access-token` predefinito del workspace e poi sulla variabile d'ambiente `WHATSAPP_META_ACCESS_TOKEN` se lo slot è vuoto. Non lancia mai un'eccezione per un token mancante — i chiamanti fanno fallire il dispatch in modo esplicito esattamente come prima.

```text theme={null}
resolveChannelAccessToken
  1. channel → provider account (whatsapp_provider_accounts)
  2. provider account → credential_secret_kind ("meta-access-token" | "meta-access-token-2".."-8")
  3. readWorkspaceSecret({ workspaceId, kind: credential_secret_kind })
       ↳ if empty and kind ≠ default → retry with "meta-access-token"
       ↳ if still empty → env WHATSAPP_META_ACCESS_TOKEN
```

<Info>
  Questo è trasparente per gli operatori — non esiste un campo token per WABA da gestire nelle Impostazioni. Il tipo di slot viene scelto automaticamente al momento dell'onboarding e letto automaticamente al momento dell'invio. Settings → Provider continua a mostrare solo i tipi di credenziali rivolti all'operatore; i tipi di slot WABA sono interni.
</Info>

## Verificare un workspace Multi-WABA

* Controlla `whatsapp_provider_accounts` per il workspace: la riga predefinita ha `is_default = true` e `credential_secret_kind = 'meta-access-token'`; ogni WABA aggiuntivo ha il proprio slot `credential_secret_kind` e `is_default = false`.
* Un invio per un WABA non predefinito che segnala il numero mittente sbagliato significa quasi sempre che il `credential_secret_kind` del suo account provider è mancante o punta allo slot sbagliato — verifica che `setProviderAccountCredentialKind` sia stato chiamato durante l'onboarding di quel WABA.
* Se Embedded Signup è stato completato ma `phoneRegistered` è tornato `false`, il numero di telefono è collegato al canale ma non è ancora registrato per gli invii Cloud API — completa la registrazione dalle Impostazioni prima di aspettarti che gli invii vengano effettuati.

## Vedi anche

* [Onboarding dell'Operatore](/it/platform/onboarding) — il flusso `/setup` al primo avvio e la checklist di prontezza
* [Credenziali Meta — configurazione passo-passo](/it/getting-started/meta-credentials) — il percorso manuale porta-il-tuo-token
* [Collega WhatsApp](/it/platform/connect-whatsapp) — walkthrough completo di Meta Business Suite
* [Architettura Vault](/it/security/vault-architecture) — come vengono memorizzati e letti i segreti del workspace (inclusi gli slot dei token WABA)
