Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 16 additions & 50 deletions docs-mintlify/embedding/iframe/creator-mode.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,29 @@ description: Embed the full Cube application so users can build and modify their
Creator Mode is available on the [Enterprise plan](https://cube.dev/pricing).
</Info>

Creator Mode lets you embed the entire Cube application into your product so users can create and modify their own dashboards directly within the embedded experience.
Creator Mode embeds the full Cube application instead of an individual dashboard or chat. Users can create and modify workbooks, dashboards, and reports inside the iframe.

To enable it, pass `creatorMode: true` to the [Generate Session API][ref-generate-session].

<Note>
Creator Mode requires [Signed embedding](/embedding/iframe/auth/signed). Private embedding is not supported.
</Note>

## How it works

In Creator Mode, you embed the full Cube application instead of individual dashboards or chat interfaces. This provides users with the complete Cube experience, including the ability to:

- Create new dashboards
- Modify existing dashboards
- Access all workbook and dashboard functionality
- Build custom analytics experiences

To enable Creator Mode, pass `creatorMode: true` to the [Generate Session API][ref-generate-session] when generating an embed session. Optionally, pass `embedTenantName` to scope content to a specific embed tenant — by default, creator mode uses the current tenant's name.
## Embed tenant scoping

## Embed tenant name
In Creator Mode, content (workbooks, dashboards) and the groups/user attributes referenced by the session are scoped to an **embed tenant**. Pass `embedTenantName` to isolate content per customer; omit it to use the current tenant.

`embedTenantName` is an optional parameter on the Generate Session API used to scope all content (dashboards, workbooks, etc.) that users create within the embedded application to a specific embed tenant. This ensures proper data isolation in multi-tenant scenarios.
`embedTenantName` must be lowercase, 5–36 chars, start with a letter, end with a letter or digit, and contain only `a-z`, `0-9`, or `-`.

When `embedTenantName` is omitted in creator mode, the session defaults to the current tenant, so most setups don't need to set it.
## Provisioning groups and user attributes

The value must be lowercase, start with a letter, end with a letter or number, and only contain letters, numbers, or hyphens (length 5–36).
In Creator Mode, `groups` and `userAttributes` resolve against the embed tenant's scoped catalog (separate from the tenant-wide one used by read-only embedding). To define those entries from your backend in the same call, pass `groupDefinitions` and `userAttributeDefinitions` — they are idempotent and validated before memberships and values are applied.

## Using Creator Mode
See [Generate Session → Creator mode bootstrap][ref-bootstrap] for the input shape, value types, and the immutable-`type` rule on attribute definitions.

To use Creator Mode and embed the app:

1. **Set the embed type to "App"** in the form
2. **Fill in Deployment ID** and either **External ID** or **Internal ID** (email). Optionally provide an **Embed Tenant Name** to scope content to a specific embed tenant
3. **Click "Generate Session & Embed"** — the request automatically includes `creatorMode: true` for app embeddings
4. The app is embedded at `/embed/d/{deploymentId}/app?session={sessionId}` and displayed in the iframe

Creator mode is enabled automatically when the embed type is "app"; no additional configuration is needed.

### Example
## Example

```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",
{
Expand All @@ -58,22 +39,18 @@ const session = await fetch(
Authorization: `Api-Key ${API_KEY}`,
},
body: JSON.stringify({
deploymentId: DEPLOYMENT_ID,
deploymentId: 32,
externalId: "user@example.com",
creatorMode: true,
// Optional — defaults to the current tenant when omitted:
embedTenantName: "acme-corp",
creatorMode: true,
}),
},
);

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

### Embedding the app

Use the session ID to embed the full Cube application:
Embed the app with the returned session ID:

```html
<iframe
Expand All @@ -84,18 +61,7 @@ Use the session ID to embed the full Cube application:
></iframe>
```

Replace `{deploymentId}` with your deployment ID and `{sessionId}` with the session ID returned from the Generate Session API.

## Example application

For a complete working example of embedding, including Creator Mode, 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
- Support for creator mode with an optional embed tenant name
- 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.
For a complete working example, see the [cube-embedding-demo](https://github.com/cubedevinc/cube-embedding-demo) repository.

[ref-generate-session]: /reference/embed-apis/generate-session
[ref-bootstrap]: /reference/embed-apis/generate-session#creator-mode-bootstrapping-groups-and-user-attributes
192 changes: 183 additions & 9 deletions docs-mintlify/reference/embed-apis/generate-session.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,21 @@ POST https://{accountName}.cubecloud.dev/api/v1/embed/generate-session

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `externalId` | string | No | Unique identifier for the external user. Either `externalId` or `internalId` should be provided. |
| `internalId` | string | No | Email address of an internal Cube Cloud user. Either `externalId` or `internalId` should be provided. |
| `userAttributes` | array | No | Array of `{name, value}` pairs for row-level security. Not allowed with `internalId`. |
| `groups` | string[] | No | Array of group names for user. Not allowed with `internalId`. |
| `deploymentId` | number | Yes | ID of the deployment the session should grant access to. |
| `externalId` | string | Conditional | Stable identifier for the external user. Provide either `externalId` or `internalId` (not both). Must be lowercase and trimmed. |
| `internalId` | string | Conditional | Username of an existing internal Cube Cloud user. Provide either `externalId` or `internalId` (not both). The user must already exist. |
| `email` | string | No | Email to attach to the provisioned external user. Used only with `externalId`. |
| `embedTenantName` | string | No | Embed tenant to scope content to. Lowercase, 5–36 chars, must start with a letter and end with a letter or digit, only `a-z`, `0-9`, `-`. Defaults to the current tenant. |
| `creatorMode` | boolean | No | When `true`, mints a [creator-mode][ref-creator-mode] session and resolves groups/attributes against the embed tenant's scoped tables. Requires the `useCreatorMode` tenant flag. |
| `userAttributes` | array | No | Attribute values for row-level security. See [User attributes](#user-attributes). Not allowed with `internalId`. |
| `groups` | string[] | No | Group memberships for the user. See [Groups](#groups). Not allowed with `internalId`. |
| `userAttributeDefinitions` | array | No | Idempotently upsert attribute definitions before applying values. Requires `creatorMode: true`. See [Creator mode bootstrap](#creator-mode-bootstrapping-groups-and-user-attributes). |
| `groupDefinitions` | array | No | Idempotently upsert group definitions before assigning memberships. Requires `creatorMode: true`. See [Creator mode bootstrap](#creator-mode-bootstrapping-groups-and-user-attributes). |
| `securityContext` | object | No | Custom security context object passed to Cube queries. Not allowed with `internalId`. |

<Info>

When using `internalId`, the user must already exist in Cube Cloud. You cannot specify `roles`, `groups`, `userAttributes`, or `securityContext` with `internalId` — the internal user's existing permissions are used instead.
When using `internalId`, the user must already exist in Cube Cloud. You cannot specify `groups`, `userAttributes`, `groupDefinitions`, `userAttributeDefinitions`, or `securityContext` with `internalId` — the internal user's existing permissions are used instead.

</Info>

Expand All @@ -50,6 +56,167 @@ Accounts are limited to 10,000 external users. To increase this limit, please co

</Warning>

## User attributes

`userAttributes` is an array of `{ name, value }` pairs that drive row-level security in queries.

```json
{
"userAttributes": [
{ "name": "department", "value": "Sales" },
{ "name": "tier", "value": 2 },
{ "name": "regions", "value": ["us-east", "eu-west"] },
{ "name": "thresholds", "value": [10, 25, 50] }
]
}
```

| Property | Type | Notes |
|----------|------|-------|
| `name` | string | Must reference an existing attribute definition (see lookup rules below). |
| `value` | `string` \| `number` \| `string[]` \| `number[]` \| `null` | The value type must match the definition's `type`. `null` clears the value. |

**Attribute definition lookup**:

- **Read-only mode** (`creatorMode` omitted or `false`): names are resolved against the tenant-wide attribute catalog (managed in **Settings → User Attributes** or via the admin GraphQL API). Any name not present there fails with `User attributes not found`.
- **Creator mode** (`creatorMode: true`): names are resolved against the embed tenant's scoped catalog (`embed_user_attributes`). Use `userAttributeDefinitions` in the same request to upsert definitions on the fly — see [Creator mode bootstrap](#creator-mode-bootstrapping-groups-and-user-attributes).

**Rules**:

- Duplicate `name` entries are rejected with `400 Bad Request`.
- Values are persisted per user. Subsequent calls with the same `externalId` overwrite previous values for the supplied names.

## Groups

`groups` is an array of group **names** (not IDs) that the user should belong to. Group definitions must already exist (or be created in the same request via `groupDefinitions` in creator mode).

```json
{ "groups": ["analysts", "marketing"] }
```

**Behavior**:

| Value | Effect |
|-------|--------|
| Field omitted (`undefined`) | Existing memberships are preserved. |
| `[]` (empty array) | All memberships are cleared. |
| Populated array | Memberships are replaced with exactly the supplied names. |

**Group definition lookup**:

- **Read-only mode**: names are resolved against tenant-wide groups (managed in **Settings → Groups** or via the admin GraphQL API). The membership row references the global group.
- **Creator mode**: names are resolved against the embed tenant's scoped groups (`embed_user_groups`). Use `groupDefinitions` in the same request to upsert them.

If any name in `groups` cannot be resolved, the request fails with `Groups with names <missing> not found`.

## Creator mode: bootstrapping groups and user attributes

In API-first integrations you often want to mint an embed session and define the groups/attributes it references in a single call, without first making a round trip to the admin UI. The `groupDefinitions` and `userAttributeDefinitions` fields do that — they idempotently upsert definitions in the embed tenant's scoped tables and are validated **before** `groups` and `userAttributes` are applied.

Both fields:

- Require `creatorMode: true`.
- Require an `embedTenantName` (definitions are only meaningful inside an embed tenant).
- Require the `useCreatorMode` tenant flag — contact support to enable.
- Land in the embed-tenant scope only — they never modify tenant-wide groups or attributes.
- Are idempotent: running the same request twice produces the same end state.

### `groupDefinitions`

```json
{
"groupDefinitions": [
{ "name": "analysts", "description": "Read-only viewers" },
{ "name": "marketing" }
]
}
```

| Property | Type | Required | Notes |
|----------|------|----------|-------|
| `name` | string | Yes | Group name. Existing groups with this name are reused. |
| `description` | string | No | Updated when supplied and different from the stored value. Never cleared. |

Duplicate `name` entries within the same request are rejected.

### `userAttributeDefinitions`

```json
{
"userAttributeDefinitions": [
{
"name": "department",
"type": "string",
"displayName": "Department",
"defaultValue": "Unassigned",
"description": "Org unit"
}
]
}
```

| Property | Type | Required | Notes |
|----------|------|----------|-------|
| `name` | string | Yes | Attribute name. Existing attributes with this name are reused. |
| `type` | enum | Yes | One of `string`, `number`, `string_array`, `number_array`. **Immutable** — see below. |
| `displayName` | string | No | Updated when supplied and different from the stored value. |
| `defaultValue` | string | No | Updated when supplied and different from the stored value. |
| `description` | string | No | Updated when supplied and different from the stored value. |

**`type` is immutable.** If a definition with the supplied `name` already exists with a different `type`, the request fails with `cannot change type` and nothing is upserted. This protects every value already stored against that attribute from silently becoming invalid. To change the type, delete the attribute via the [embed-tenant admin API](#embed-tenant-admin-api) and recreate it.

Duplicate `name` entries within the same request are rejected.

### Bootstrap example

Define a group and an attribute, assign the user to both, and mint a session — all in one call:

```javascript
const session = await fetch(
`https://${ACCOUNT_NAME}.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-123',
embedTenantName: 'acme-corp',
creatorMode: true,

// Upserted before validation runs
groupDefinitions: [
{ name: 'analysts', description: 'Read-only viewers' },
],
userAttributeDefinitions: [
{ name: 'department', type: 'string', displayName: 'Department' },
],

// Reference the names we just defined
groups: ['analysts'],
userAttributes: [{ name: 'department', value: 'Sales' }],
}),
},
);
```

A second call with the same body produces the same end state: the group and attribute already exist, descriptions/display names are reconciled if they changed, and the user's memberships and values are re-applied.

## Embed-tenant admin API

To list or delete the groups and attributes that have been bootstrapped into an embed tenant, use the admin endpoints scoped to that tenant:

```text
GET /api/v1/embed-tenants/{embedTenantName}/groups
DELETE /api/v1/embed-tenants/{embedTenantName}/groups/{id}
GET /api/v1/embed-tenants/{embedTenantName}/user-attributes
DELETE /api/v1/embed-tenants/{embedTenantName}/user-attributes/{id}
```

These endpoints use the same `Api-Key` authentication as Generate Session and require admin access. List endpoints return cursor-paginated results (`?first=`, `?after=`).

### Response

The API returns a session object:
Expand Down Expand Up @@ -84,10 +251,12 @@ response = requests.post(
'Authorization': f'Api-Key {API_KEY}'
},
json={
'deploymentId': 32,
'externalId': 'user@example.com',
'userAttributes': [
{'name': 'department', 'value': 'Sales'}
]
],
'groups': ['analysts']
}
)

Expand All @@ -108,10 +277,12 @@ const response = await fetch(
'Authorization': `Api-Key ${API_KEY}`
},
body: JSON.stringify({
deploymentId: 32,
externalId: 'user@example.com',
userAttributes: [
{ name: 'department', value: 'Sales' }
]
],
groups: ['analysts']
})
}
);
Expand All @@ -124,10 +295,12 @@ curl -X POST "https://your-account.cubecloud.dev/api/v1/embed/generate-session"
-H "Content-Type: application/json" \
-H "Authorization: Api-Key YOUR_API_KEY" \
-d '{
"deploymentId": 32,
"externalId": "user@example.com",
"userAttributes": [
{"name": "department", "value": "Sales"}
]
],
"groups": ["analysts"]
}'
```

Expand All @@ -136,4 +309,5 @@ curl -X POST "https://your-account.cubecloud.dev/api/v1/embed/generate-session"
Use session ID in [signed embedding][ref-signed-embedding].

[ref-api-keys]: /admin/account-billing/api-keys
[ref-signed-embedding]: /embedding/iframe/auth/signed
[ref-signed-embedding]: /embedding/iframe/auth/signed
[ref-creator-mode]: /embedding/iframe/creator-mode
Loading
Loading