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

# Embeddable Widget

> Drop a chat agent onto any website with a browser-safe publishable key.

The widget puts a published agent on your own site as a chat bubble. It authenticates in the
browser with a **publishable key** (`flowyte_pk_…`) — agent-pinned, origin-allowlisted, and
limited to public chat — so it is safe to ship in client-side code. No secret key ever touches
the browser.

## How it works

<Steps>
  <Step title="Mint a publishable key">
    Create a key for the agent and list the exact origins (sites) allowed to use it. The full key
    is returned on create — it is public by design, not a show-once secret.
  </Step>

  <Step title="Get the embed snippet">
    Fetch the loader `<script>` snippet for the agent (optionally pinned to a specific key).
  </Step>

  <Step title="Drop it on your site">
    Paste the snippet before <code>\</body></code>. The loader boots the widget, which
    bootstraps its theme/copy from the public config and opens a chat session on demand.
  </Step>
</Steps>

```html theme={null}
<!-- Paste before </body>. The publishable key is safe to expose. -->
<script
  src="https://builder.flowyte.com/widget/loader.js"
  data-flowyte-key="flowyte_pk_live_…"
  async
></script>
```

## Origin allowlisting

A publishable key only works from an origin you listed. Browser requests must send an `Origin`
that matches the key's `allowedOrigins`; anything else is rejected with `403`. Keep the list
tight — one key per site is a good default. You can rotate a key (same agent and origins, with a
grace window) or revoke it instantly.

## Customize and harden

* **Appearance & copy** live in the agent's widget config (`theme`, `copy`, `behavior`).
* **Rate limiting** per key (`rateLimitRpm`) caps abuse from a single origin.
* **Identity verification** (`requireIdentityVerification`) can require a signed visitor token
  before a session opens, for logged-in experiences.

## In the API

| Action                      | Endpoint                                              | Scope                            |
| --------------------------- | ----------------------------------------------------- | -------------------------------- |
| List publishable keys       | `GET /agents/{agentId}/publishable-keys`              | `pubkeys:read`                   |
| Mint a publishable key      | `POST /agents/{agentId}/publishable-keys`             | `pubkeys:write`                  |
| Update a key                | `PATCH /agents/{agentId}/publishable-keys/{id}`       | `pubkeys:write`                  |
| Rotate a key (grace window) | `POST /agents/{agentId}/publishable-keys/{id}/rotate` | `pubkeys:write`                  |
| Revoke a key                | `DELETE /agents/{agentId}/publishable-keys/{id}`      | `pubkeys:write`                  |
| Get / replace widget config | `GET` · `PUT /agents/{agentId}/widget`                | `widgets:read` · `widgets:write` |
| Get the embed snippet       | `GET /agents/{agentId}/widget/embed`                  | `widgets:read`                   |

```bash theme={null}
# Mint a publishable key scoped to two origins
curl -X POST https://builder.flowyte.com/api/v1/agents/AGENT_ID/publishable-keys \
  -H "Authorization: Bearer flowyte_sk_…" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Marketing site",
    "allowedOrigins": ["https://example.com", "https://www.example.com"],
    "env": "live"
  }'
```

<Note>
  The widget talks to the public chat surface (`chat:public` scope) using only the publishable key —
  visitors get an anonymous session pinned to the one agent. Your secret key stays server-side.
</Note>

<Tip>
  The widget serves the agent's **published** version. Republish after editing, or visitors keep
  seeing the old behavior.
</Tip>
