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

# Embeddable widget

> How the Kataven embeddable voice + chat widget works — pk_live_ vs sk_live_ keys, anonymous vs authenticated visitors, domain allowlists, agent pinning, and the bootstrap protocol.

The Kataven widget is a voice/chat launcher you embed on any web
page. End-users click it and talk (or chat) with one of your agents
in their browser via WebRTC.

## Two key types

| Key                   | Prefix                       | Where it lives                                  | What it does                                            |
| --------------------- | ---------------------------- | ----------------------------------------------- | ------------------------------------------------------- |
| **Public client key** | `pk_live_<account>_<random>` | The customer's web page (visible to browsers)   | Identifies the account + (optionally) pins to one agent |
| **Secret key**        | `sk_live_<account>_<random>` | The customer's backend only — never the browser | Used server-to-server to mint authenticated user tokens |

Both keys are minted as a pair via the admin endpoint and **returned
exactly once**. Save them immediately — the secret is bcrypt-hashed
on store and unrecoverable.

```python theme={null}
created = client.widget_keys.create(
    name="Acme website",
    domain_allowlist=["https://acme.com", "https://www.acme.com"],
    agent_id="<agent uuid>",  # optional pin
)
print(created["public_key"])  # pk_live_...
print(created["secret_key"])  # sk_live_... — save now
```

## Widget settings

Two layers:

### Account-level branding (`/api/v1/widget-settings`)

```python theme={null}
client.widget_settings.update(
    primary_color="#2563eb",
    accent_color="#7c3aed",
    logo_url="https://acme.com/logo.svg",
    launcher_position="br",         # br/bl/tr/tl
    launcher_label="Talk to us",
    privacy_notice="Calls may be recorded for quality.",
)
```

### Per-agent policy (`/api/v1/agents/{id}/widget-settings`)

```python theme={null}
client.widget_settings.update_agent(
    agent_id="<agent uuid>",
    widget_enabled=True,
    auth_mode="both",   # guest | user | both
)
```

`auth_mode` controls whether anonymous visitors (`guest`),
authenticated end-users (`user`), or both can talk to this agent.

## End-user auth flows

The widget calls **public, cross-origin endpoints** to mint short-lived
JWTs. There are two paths:

### Guest (anonymous)

```mermaid theme={null}
sequenceDiagram
    Browser->>Hub: POST /api/v1/widget/auth/guest { client_key }
    Hub-->>Browser: { jwt, session_id, agent_id, expires_at }
    Browser->>Gateway: WebRTC connect with jwt
```

### Authenticated user

The customer's backend mints an exchange token using its secret key,
the browser swaps it for a real user JWT.

```mermaid theme={null}
sequenceDiagram
    participant CustomerBackend
    CustomerBackend->>Hub: POST /api/v1/widget/auth/user-token<br/>Authorization: Bearer sk_live_...
    Hub-->>CustomerBackend: { user_token, expires_at }
    CustomerBackend-->>Browser: user_token (5 min TTL)
    Browser->>Hub: POST /api/v1/widget/auth/exchange<br/>{ client_key, user_token }
    Hub-->>Browser: { jwt, session_id, agent_id, external_user_id, expires_at }
    Browser->>Gateway: WebRTC connect with jwt
```

The exchange endpoint re-validates the client key + Origin so a
leaked exchange token can't be replayed across origins.

### Refresh

`POST /api/v1/widget/auth/refresh` accepts an expired-grace-period
JWT and returns a fresh one. Skips Zitadel entirely — pure widget
token refresh.

## Origin enforcement

Each public client key has a `domain_allowlist`. The widget auth
handler checks the request's `Origin` (or `Referer`) header against
that list before minting any token. The cross-origin CORS plumbing is
permissive by design — the per-key allowlist is the actual security
boundary.

## Widget SDK (browser side)

This page is about the **management** side. For the actual browser
embed (`<KatavenAgent />` component, `KatavenClient` for custom UIs),
see [`@kataven/client`](https://www.npmjs.com/package/@kataven/client).
