--- title: "Installare e configurare l’SDK Web" description: "Aggiungi la chat al tuo sito con l’SDK Web con versione fissata, collega i clienti che hanno effettuato l’accesso tramite il tuo backend e ascolta eventi tipizzati." last_updated: "2026-10-15T17:52:44+03:00" --- # Installare e configurare l’SDK Web Source: https://busymate.ai/it/docs/guides/web-sdk Last modified: 2026-10-15T17:52:44+03:00 Put Busymate AI on your website with the official Web SDK distribution **0.1.0**: a typed package, `@busymate/ai-web`, that mounts the chat, recognizes customers who are signed in to your product with a token your server signs, and reports every step as an event. Source, the configuration reference and two runnable examples live in the [public repository](https://github.com/serebano/busymate-ai-sdk-web/tree/0.1.0), released as [0.1.0](https://github.com/serebano/busymate-ai-sdk-web/releases/tag/0.1.0). The SDK pins the page side of the wire to [contract v1](https://github.com/serebano/busymate-ai-sdk-web/blob/0.1.0/CONTRACT-v1.md) (bridge `busymate-ai-v1`), so updates to the hosted chat never change what your page sends or accepts. The [release manifest](https://github.com/serebano/busymate-ai-sdk-web/blob/0.1.0/release-manifest.json) pins the contract hashes. The Web SDK is the recommended way to add the chat to a site you build. The one-line embed script keeps working; section 6 shows how to move. ## 1. Install the pinned version 1. Install the packed tarball attached to the 0.1.0 release: `npm install https://github.com/serebano/busymate-ai-sdk-web/releases/download/0.1.0/busymate-ai-web-0.1.0.tgz`. The package is not on the npm registry. 2. Without a bundler, download `busymate-ai-web-0.1.0.iife.js` from the same release, serve it from your own origin and pin it with `integrity`. It defines `window.BusymateAIWeb`. 3. The package has no runtime dependencies, ships ESM, CommonJS and TypeScript types, and is safe to import during server rendering: nothing touches the page until `mount()` runs in a browser. Read the [versioned installation instructions](https://github.com/serebano/busymate-ai-sdk-web/blob/0.1.0/README.md) before wiring callbacks. ## 2. Mount the chat ```typescript import { createBusymateChat, mintFromEndpoint } from "@busymate/ai-web"; const chat = createBusymateChat({ assistant: "your-assistant", origin: "https://your-assistant.busymate.ai", mode: "launcher", // "launcher" | "panel" | "inline" // YOUR authenticated endpoint: { token, nonce } for a signed-in customer, 401 for a guest. getIdentity: mintFromEndpoint("https://YOUR-PRODUCT-DOMAIN/api/bmai/identity"), }); chat.onLinkStatus(({ state, reason }) => console.debug("account link", state, reason)); chat.mount(); // Wire YOUR auth events, not your router. auth.onSignIn(() => chat.identityChanged()); auth.onSwitchAccount(() => chat.switchAccount()); auth.onSignOut(() => chat.logout()); ``` | Setting | Purpose | | --- | --- | | `assistant` | Required assistant slug from Console › Integration. | | `origin` | The serving origin your embed script uses: `https://.busymate.ai` or your verified custom domain. | | `mode` | `launcher` (floating button and panel), `panel` (no button; open it from your UI) or `inline` (fills `container`). | | `getIdentity` | Your provider: a fresh `{ token, nonce }` from your backend, or `null` for a guest. | | `account` | Optional: your current account id, read in memory only, to catch a switch you forgot to report. | | `locale`, `theme` | First-paint language and theme; later `setLocale()` and `setTheme()`. | | `onSignInRequest`, `onNavigate` | Optional: handle in-chat sign-in and same-site links in your own router. | Add your page's exact origin to Console › Integration › allowed origins. The chat refuses to load anywhere else, and the SDK says so (`origin_not_allowed`) instead of showing an empty panel. See the [complete configuration reference](https://github.com/serebano/busymate-ai-sdk-web/blob/0.1.0/docs/configuration.md). ## 3. Link signed-in customers Your backend mints a one-time launch token; the page never holds a key. Build one authenticated endpoint that reads `{ nonce, returnTo }`, signs an ES256 JWT with your workspace claim, `sub`, the echoed `nonce`, a unique `jti` and an expiry within 120 seconds, and answers `{ token, nonce }`. Copy a reference implementation from [backend signing](https://busymate.ai/it/docs/guides/identity-backend-signing). `mintFromEndpoint` calls it with your cookies, refuses redirects and treats `401` as signed out. Then wire your own auth events, not your router: | Your product | Call | | --- | --- | | Sign-in or token rotation | `chat.identityChanged()`: the same conversation continues, now identified. | | Account switch | `chat.switchAccount()`: the previous person's chat is withdrawn first. | | Sign-out | `chat.logout()`: the chat drops the identity and clears the transcript. | | A token you already hold | `chat.identify({ token, nonce })` or `chat.setUser(...)`. | When a guest taps Sign in inside the chat, the SDK sends them to your login page with `return_to` set to the current page and picks the token up when they return. Pass `onSignInRequest` to keep them on the page with your own login modal. See [in-chat sign-in](https://busymate.ai/it/docs/guides/in-chat-sign-in) and the [identity guide](https://github.com/serebano/busymate-ai-sdk-web/blob/0.1.0/docs/identity.md). ## 4. Listen to events `chat.on(name, listener)` is typed. `ready` reports the visitor kind, `open` and `close` report the source, `message` mirrors every chat message for logging, `navigate`, `signInRequest` and `sessionEnded` report what the chat asked, and `error` names a refused origin or a silent frame. `chat.onLinkStatus(listener)` reports the account link as `{ state, reason, source }`. `state` is `unlinked`, `linking`, `linked` or `failed`. `reason` is a stable code such as `identified`, `not_signed_in`, `mint_failed`, `nonce_mismatch`, `not_verified` or `origin_not_allowed`. New codes can be added in later releases, so always keep a default branch. See [events](https://github.com/serebano/busymate-ai-sdk-web/blob/0.1.0/docs/events.md). ## 5. Content Security Policy and the frame Add the chat origin to `frame-src` and `connect-src`, and your mint endpoint's origin to `connect-src` when it differs. `cspHeader({ origin })` prints the line for you. The SDK loads no remote script. It injects one style element; pass your policy's `nonce`. Leave the frame's `sandbox` and `allow="tools; microphone; autoplay"` as the SDK sets them, and do not block `microphone` for the chat origin in `Permissions-Policy` if you offer voice. Every message is pinned to the frame and its exact origin, never `*`. See [CSP and iframe guidance](https://github.com/serebano/busymate-ai-sdk-web/blob/0.1.0/docs/csp.md). ## 6. Move from the embed script Existing embed snippets keep working, and nothing is switched off. To move a page, remove the embed script tag and create the chat with the same `assistant` and the script's origin. Move your `getIdentity` into the option, then replace `identityChanged()` and `signedOut()` with `chat.identityChanged()` and `chat.logout()`. The SDK uses the same frame and the same visitor storage, so returning visitors keep their conversations. Never run both on one page. Page tools, the floating window and push layout are not in 0.1.0 yet: keep the script on pages that use them. See the [migration table](https://github.com/serebano/busymate-ai-sdk-web/blob/0.1.0/docs/migration.md) and the [widget page API](https://busymate.ai/it/docs/guides/widget-page-api). ## Troubleshoot linking Start from the link status your page logs: - `not_signed_in`: your provider returned `null`. Check that your session reached the mint endpoint. - `mint_failed` or `nonce_mismatch`: your endpoint failed or did not echo the nonce. The `detail` field has the HTTP status. - `not_verified`: the token reached the chat, but the verifier refused it. Open the conversation in the Console and read its account linking timeline. It names the cause, such as wrong issuer or audience, an unknown key id, an expired token or clock skew. Console › People › Identity health shows the same picture across customers. - `origin_not_allowed`: add the page origin to the allowed origins. Then follow [identity troubleshooting](https://busymate.ai/it/docs/guides/identity-troubleshooting). ## Verify 1. Run the example apps (`npm ci && npm run build`, then `node example-app/server.mjs`) against a test workspace that allows `http://localhost:5180`; see the [example-app instructions](https://github.com/serebano/busymate-ai-sdk-web/blob/0.1.0/example-app/README.md). 2. Open the launcher as a guest: `ready` reports `anonymous` and link status stays `unlinked`. 3. Sign in on your site: link status reaches `linked · identified` and the chat greets the customer by name. 4. Switch account and sign out: the previous transcript disappears each time. 5. Load the page on an origin that is not allowed: the SDK reports `origin_not_allowed`. ### Which version should I install? Web SDK distribution 0.1.0, the tarball or the script file attached to the release. It speaks wire contract v1, bridge `busymate-ai-v1`. ### Do I have to replace the embed script? No. Existing snippets keep working. The SDK is the recommended path for new integrations and for pages that need typed events or link status. ### Why does the link status say not_verified? The chat received a token but refused it. The account linking timeline on the conversation in the Console names the exact reason.