Publish & embed

A published app has three destinations. They share one configuration — publishing to a second costs nothing extra.

A link

https://platform.rsi-data.com/a/<app-id>?key=<embed-key>

A full-page surface with no platform chrome around it. Send it to someone, put it behind a QR code, drop it in a newsletter. The person opening it needs no account.

A widget on your own site

One script tag. It renders a launcher on your page and opens the app in an iframe.

<script
  src="https://platform.rsi-data.com/embed.js"
  data-app="app_7f21…"
  data-key="wk_live_…"
></script>

Useful attributes

| Attribute | What it does | | --- | --- | | data-app | The app id. Required. | | data-key | The embed key (wk_…). Required. | | data-token-url | Your own endpoint that mints a short-lived token per visitor. See below. | | data-preload | lazy to skip warming the iframe on page load. |

Warm-up

The loader fires one cheap request on mount so the platform is awake by the time a visitor clicks. That overlaps a cold start with the time someone spends reading your page, and it is why the widget usually opens instantly.

Visitor continuity

Without data-token-url, the loader keeps an anonymous continuity id so a visitor's conversation survives a reload. It is stored first-party on your page — never inside the iframe, because iframe storage gets partitioned away in Safari and in Chrome with third-party cookies blocked.

That id is not identity and not authentication. It is never used as a metering subject, and an anonymous conversation is never silently merged into a signed-in one — promoting one has to be something you ask for, not a side effect of a login.

A client config

The same app, as MCP configuration for your own agent. Use this when the app is for your own team rather than for visitors.

Access

Two modes, and the difference matters.

Public — the embed key alone authorises the call. Anyone holding it can use the app. This is what ships today.

Restricted — your backend holds a server secret (sk_live_…) and mints a short-lived token per visitor; the widget presents that token on every call.

Restricted mode is not enforceable yet. The gateway has no secret storage, no access mode and no domain list, so the option is shown disabled with that reason rather than hidden. Do not design around it until it ships.

The origin allowlist is not authentication

Say this the same way everywhere, because getting it wrong is expensive:

The allowlist is enforced by browsers. A browser refuses to send a request from a page that is not on the list, so the allowlist stops other websites from embedding your widget. It stops nothing scripted — curl, a server, or any non-browser client can set an Origin header to whatever it likes.

Treat it as a sensible default that keeps your widget off other people's sites, never as the thing protecting your app. An empty list deliberately means "any site" rather than a silent deny that would break a working embed.

Revoking

Rotating the embed key invalidates every existing copy immediately. A visitor mid- conversation on a revoked app is told the assistant is no longer available — one neutral message, the same for a deleted app, a disabled widget or a rotated key, so that probing reveals nothing about which it was.