Custom widget runtime

# Architecture

The SDK authenticates the user, loads the supplied custom bundle, and mounts the configured experience directly inside the host page.

## Three values, three jobs

`widget-id`

Selects the configured widget instance.

`bundle-url`

Selects the JavaScript bundle used by that experience.

`embed-token`

Carries signed user identity for 15 minutes.

## Load lifecycle

01 **Element connects** The SDK reads widget-id, bundle-url, and embed-token.

02 **Token validates** The SDK submits the short-lived token to the Returning.AI widget auth server, which verifies its signed claims.

03 **Bundle loads** The browser downloads the exact widget.js supplied for this experience.

04 **Experience mounts** The bundle reads the widget configuration selected by widget-id and mounts into the page.

05 **Events report state** The element emits authentication, mount, error, and session events to the host page.

## Page DOM

Custom bundles render inside the page. This gives the portal one scroll context and allows normal browser inspection.

`DOM`

```
Host page
└── <rai-custom-widget>
    └── <div class="rai-widget-root">
        └── Configured experience mounted by the supplied bundle
```

> Scope host-page CSS
>
> The widget is part of the page DOM. Broad selectors in the portal can affect its content, so scope application CSS to your own layout roots.

## Authentication boundary

The access ID and access key stay in the client's backend. The browser receives only the short-lived embed token. The SDK sends that token to Returning.AI for validation before loading the configured experience.

- **Server:** stores access credentials and signs user identifiers into the token request.
- **Browser:** stores the current embed token in the element attribute and sends it to Returning.AI APIs.
- **Returning.AI:** validates the token and returns data for the authenticated user and configured widget.

## Token lifecycle

Access Key embed tokens last 15 minutes and are not stored as refresh tokens in local storage. For long-lived pages, the host requests a fresh token from its backend and updates `embed-token`.

Register these observation listeners after your element exists. Use the [complete shared host lifecycle](https://docs.returning.ai/widget-sdk.md#step-06) for renewal, failure handling and account changes rather than adding an independent fetch handler.

`widget-events.js`

```javascript
const widget = document.querySelector('rai-custom-widget')

widget.addEventListener('rai-authenticated', () => {
  console.log('Embed token accepted')
})

widget.addEventListener('rai-mounted', () => {
  console.log('Custom bundle mounted')
})

widget.addEventListener('rai-session-expired', () => {
  console.warn('Widget session needs attention')
})
// Observation only. Use the quickstart's shared host lifecycle
// for token renewal, bounded recovery and account-switch cleanup.
```

## Runtime API

The global `window.ReturningAIWidget` controller can report SDK version and auth state, reload the widget, return safe token metadata, or clear the session. DOM events remain scoped to each custom element.

In SDK 1.8.11, `reload()` tears down and initializes the widget again; it is not a lightweight progress query. Token synchronization updates authentication in a bundle or iframe, not proof of a fresh field, milestone or reward. Use `rai-authenticated` and `rai-mounted` as lifecycle signals, then check the configured visible business result separately.

## Bundle releases, hosting and rollback

Pin the published SDK version separately from the supplied widget bundle. An npm version pins the SDK runtime, not the bundle URL's future contents. A URL shape alone does not establish an immutable release, supported version pair or rollback mechanism.

Before approving a bundle deployment, have the Returning.AI bundle owner and your release owner record the approved artifact/version or hash, supported SDK pair, change notice, tested rollback and permitted hosting model. Obtain the required script, connection and asset sources for your browser security policy; do not guess a version query parameter, mirror the bundle without approval or assume the SDK script is the only required source.

Keep these decisions in the [existing handover](https://docs.returning.ai/broker-integrations/launch-checklist.md#decision-gates). For an installed legacy loader, also follow the [migration and rollback dependency checks](https://docs.returning.ai/widget-sdk/auth-token.md#migrating-to-access-key).

## Legacy runtime paths

The SDK still contains standard element tags, hosted iframe mode, `auth-url`, refresh-token storage, and a postMessage protocol for existing clients. New custom-widget integrations do not need those paths.

See the [legacy embed documentation](https://docs.returning.ai/embed-script.md) only when Returning.AI explicitly approves that method for your supplied setup. Retained runtime paths do not establish a support deadline or compatibility for an unknown loader.

## Browser support

The SDK requires Custom Elements v1 and modern JavaScript. Current Chrome, Firefox, Safari, Edge, and Chromium-based in-app browsers are supported.
