# Signed embedding

<InfoBox>
  Signed embedding is available on [Premium and Enterprise plans](https://cube.dev/pricing).
</InfoBox>

Signed embedding is designed for **external, customer-facing analytics**. It uses JWT tokens for seamless authentication, making it ideal for:

- Embedding analytics in your SaaS application for customers
- White-label analytics solutions
- Multi-tenant applications where each customer sees their own data
- Public-facing dashboards with controlled access

Users authenticate through your application without needing Cube accounts, providing a seamless experience. The session tokens are cryptographically signed to ensure secure access with user-specific permissions.

## Getting started

Signed embedding works through a two-step authentication flow:

1. **Generate a session** – Your backend generates a temporary session using the Cube API
2. **Exchange for a token** – The iframe automatically exchanges the session for a long-lived access token

**Session lifecycle:**
- **Sessions** are valid for **5 minutes** and must be exchanged within this window
- **Tokens** are valid for **24 hours** after exchange
- Sessions are single-use and expire after being exchanged

This ensures secure authentication while maintaining a smooth user experience.

### Get your API key

To use the embedded chat or dashboard, you need an [API key][ref-api-keys]:

- Go to <Btn>Access → API Keys</Btn> in your Cube admin panel
- Generate or copy your existing API key.
- You'll use this key to authenticate API calls for generating embed sessions.

### Generate an embed session

Use the [Generate Session API][ref-generate-session] to create a session for your user. This endpoint will automatically create (insert) or update the external user based on the `externalId` provided.

<WarningBox>
  Accounts are limited to 10,000 external users. To increase this limit, please
  contact support.
</WarningBox>

#### Example (JavaScript)

```javascript
const API_KEY = "YOUR_API_KEY";
const DEPLOYMENT_ID = 32;

const session = await fetch(
  "https://your-account.cubecloud.dev/api/v1/embed/generate-session",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: "Api-Key ${API_KEY}",
    },
    body: JSON.stringify({
      deploymentId: DEPLOYMENT_ID,
      externalId: "user@example.com",
      userAttributes: [
        // optional - enables row-level security
        {
          name: "city",
          value: "San Francisco",
        },
        {
          name: "department",
          value: "Sales",
        },
      ],
    }),
  },
);

const data = await session.json();
const sessionId = data.sessionId;
```

### Embedding via iframe

Use the session ID to embed the chat UI or the dashboard UI in your application:

```html
<iframe
  title="Analytics Chat"
  src="https://your-tenant.cubecloud.dev/embed/chat?sessionId=YOUR_SESSION_ID"
></iframe>
```

```html
<iframe
  title="Dashboard"
  src="https://your-tenant.cubecloud.dev/embed/dashboard/YOUR_DASHBOARD_PUBLIC_ID?session=YOUR_SESSION_ID"
  width="100%"
></iframe>
```

#### Complete example

Here's a complete HTML example that demonstrates the full flow for embedding a dashboard:

```html
<html>
  <head>
    <script>
      (async () => {
        const API_BASE_URL = "https://your-tenant.cubecloud.dev";
        const API_KEY = "YOUR_API_KEY";
        const DEPLOYMENT_ID = 32;
        const externalId = "user@example.com";

        const sessionResponse = await fetch(
          `${API_BASE_URL}/api/v1/embed/generate-session`,
          {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              Authorization: `Api-Key ${API_KEY}`,
            },
            body: JSON.stringify({
              deploymentId: DEPLOYMENT_ID,
              externalId: externalId,
            }),
          },
        );

        const sessionData = await sessionResponse.json();

        const iframe = document.getElementById("dashboard-iframe");
        const baseUrl =
          "https://your-tenant.cubecloud.dev/embed/dashboard/YOUR_DASHBOARD_PUBLIC_ID";
        iframe.src = `${baseUrl}?session=${sessionData.sessionId}`;
      })();
    </script>
  </head>

  <body>
    <iframe
      id="dashboard-iframe"
      src=""
      width="100%"
      height="800"
      frameborder="0"
      allowtransparency="true"
      allowfullscreen="true"
    ></iframe>
  </body>
</html>
```

## Pre-setting dashboard filters via URL

You can pre-set dashboard filter values by adding URL parameters in the format
`?f_<semantic_view>.<dimension>=<JSON>`. The `<semantic_view>` and `<dimension>`
must match the internal names (not display titles) of the semantic view and
dimension configured on the filter widget. If the filter type is omitted, it
defaults to `equals`.

Example:

```
https://your-tenant.cubecloud.dev/embed/dashboard/YOUR_DASHBOARD_PUBLIC_ID?session=YOUR_SESSION_ID&f_orders_transactions.users_country={"value":"USA"}
```

This works on both regular and published (embedded) dashboards. The filter is
only applied if a matching filter widget for that dimension already exists on the
dashboard.

## Customize dashboard style

You can customize the appearance of your dashboard — including background, widget
styling, borders, titles, and fonts — using the <Btn>Styling</Btn> pane in the
Dashboard Builder. Open your dashboard, click <Btn>Dashboard Builder</Btn> in the
top bar, then click the gear icon to open the <Btn>Styling</Btn> panel.

## User attributes

User attributes enable row-level security and personalized chat responses by filtering data based on user permissions. The attributes you pass during session generation automatically filter data queries and responses.

<InfoBox>
  User attributes must first be configured in your Cube admin panel. See the
  [User Attributes documentation](/product/administration/users-and-permissions/user-attributes) for
  setup instructions.
</InfoBox>

**How it works:**

1. **Configure attributes** in your admin panel (e.g., `city`, `department`)
2. **Pass attributes** during session generation
3. **Data is automatically filtered** based on user permissions through access policies
4. **AI responses are personalized** to the user's context

**Example use cases:**

- Sales reps only see data for their assigned territory
- Regional managers see data filtered by their city
- Department heads see only their department's metrics

## Example application

For a complete working example of signed embedding, check out the [cube-embedding-demo](https://github.com/cubedevinc/cube-embedding-demo) repository. This demo application provides:

- A full working example of iframe embedding
- Implementation of signed iframe embedding with session generation
- A React-based UI for testing embedding functionality
- Backend server that securely handles API key authentication

You can clone the repository, configure it with your Cube credentials, and run it locally to test embedding functionality or use it as a reference implementation for your own application.

[ref-api-keys]: /product/administration/api-keys
[ref-generate-session]: /product/apis-integrations/embed-apis/generate-session
