# Recognize signed-in customers | Busymate AI

Source: https://busymate.ai/hi/docs/guides/identified-visitors
Last modified: 2026-09-04T13:24:41+03:00
Busymate AI recognizes your signed-in customers without sharing an account database. So the assistant can trust who is asking, your API signs a short-lived proof for each signed-in customer (a launch token — an ES256 JWT valid for 120 seconds with a one-time nonce), you publish the matching public key (JWKS) as the workspace's identity provider, and the widget calls `getIdentity` and `refreshIdentity`. bro then serves that customer's history and account tools — only theirs.

## Two identities

- **Your team** signs in to the Console with their own accounts to manage the workspace.
- **Your customers** never get a platform account. Each launch carries a short-lived proof your product signed; its subject is your unchanging customer id. The claims prove who is chatting — they are not an account database.

## 1. Keys

Create an ES256 key pair. Publish the public key at `https://yourdomain/.well-known/jwks.json` with a `kid`; keep the private key on your server. ES256 is the reference algorithm; the allowed list is part of the provider registration.

## 2. Register the provider

Open [Console → Identity](https://busymate.ai/console/identity) (or call `upsert_tenant_identity_provider`) and enter:

| Field | Value |
|---|---|
| Issuer | your origin, for example `https://yourdomain` |
| JWKS URL | `https://yourdomain/.well-known/jwks.json` |
| Audience | `busymate-ai` |
| Workspace claim | `tenant_id`, equal to your workspace id |
| Subject claim | `sub` — the unchanging internal customer id |
| Max proof age | at most 120 seconds |
| Mint endpoint | the URL of the endpoint from step 3 |

Save the draft, run the checks, publish. An incomplete sign-in setup blocks the release.

## 3. The mint endpoint

Your API exposes one endpoint that requires your own signed-in session and returns a freshly signed proof for that customer:

{{snippet:identity-endpoint}}

- The nonce arrives from the widget and must match `^[A-Za-z0-9_-]{32,200}$`; the response echoes it.
- Claims: `iss`, `aud`, `sub`, your workspace claim, `nonce`, a one-time `jti`, `iat`, `exp` within the registered max age.
- Respond `201` with `{ token, nonce, expiresIn }` and `Cache-Control: no-store`. Every launch consumes the pair exactly once.

## 4. Wire the widget

Define `window.BusymateAI.getIdentity` before the embed script loads. It returns a fresh `{ token, nonce }` for a signed-in customer, or `null` for a signed-out one. Call `refreshIdentity()` after login, logout, token rotation and every account switch — it reloads the correct visitor or signed-in history. Never keep a token or nonce in storage, cookies or component state. The Console's Integration section renders the full embed snippet with your values.

## 5. Full-page open

For a hosted page instead of an embed, mint the same pair and open your address with the token and nonce in the URL **fragment** — never the query string, referrer or logs. The destination strips the fragment before the exchange. The hosted-handoff snippet in Integration shows the exact form; see also [White-label SDK → Customer identity](https://busymate.ai/hi/developers#identity).

## 6. Acceptance checklist

Setup progress is evidence of configuration; it does not prove the flow works. Run this list before you call sign-in done:

{{snippet:identity-acceptance}}

## Pitfalls

- An email, phone number or session id as `sub`. Use the unchanging internal id.
- A token or nonce kept in `localStorage`, a cookie or React state.
- A proof older than the registered max age, or a missing `kid`.
- Answering `getIdentity` for a signed-out customer with anything but `null`.

## Verify

1. Signed out: the assistant is a visitor session.
2. Log in without reloading the page and call `refreshIdentity()`: the frame is identified.
3. The same customer on a second device sees the same history.
4. A second account cannot see the first account's history or data.

<!-- qa:start -->
### Do you store my customers' accounts?
No. Each launch carries a proof your product signed; the subject is your id. Conversations are keyed to that subject inside your workspace.

### Why does the proof expire in 120 seconds?
It is a launch proof, not a session. A fresh one is minted per launch and used once, so a leaked proof is useless within moments.

### Which algorithm must I use?
ES256 is the reference. The algorithms your provider accepts are part of its registration, checked against your JWKS.

### Can visitors still chat?
Yes, when guest access is on. Signed-out visitors get answers and guidance; account tools need a signed-in customer.
<!-- qa:end -->

## Next

- **[Connect your MCP server as assistant tools](https://busymate.ai/hi/docs/guides/connect-mcp-server)** — the tools that need this identity.
- **[In-app AI support for iOS and Android](https://busymate.ai/hi/docs/guides/mobile-in-app-support)** — the same proof through a native bridge.
- **[White-label SDK → Customer identity](https://busymate.ai/hi/developers#identity)** — the full contract.
