Skip to content

Commit 8f590a3

Browse files
authored
docs: enhance Generate Session and Creator Mode documentation with ne… (cube-js#10823)
1 parent 2928766 commit 8f590a3

4 files changed

Lines changed: 396 additions & 117 deletions

File tree

docs-mintlify/embedding/iframe/creator-mode.mdx

Lines changed: 16 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,48 +7,29 @@ description: Embed the full Cube application so users can build and modify their
77
Creator Mode is available on the [Enterprise plan](https://cube.dev/pricing).
88
</Info>
99

10-
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.
10+
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.
11+
12+
To enable it, pass `creatorMode: true` to the [Generate Session API][ref-generate-session].
1113

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

16-
## How it works
17-
18-
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:
19-
20-
- Create new dashboards
21-
- Modify existing dashboards
22-
- Access all workbook and dashboard functionality
23-
- Build custom analytics experiences
24-
25-
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.
18+
## Embed tenant scoping
2619

27-
## Embed tenant name
20+
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.
2821

29-
`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.
22+
`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 `-`.
3023

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

33-
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).
26+
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.
3427

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

37-
To use Creator Mode and embed the app:
38-
39-
1. **Set the embed type to "App"** in the form
40-
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
41-
3. **Click "Generate Session & Embed"** — the request automatically includes `creatorMode: true` for app embeddings
42-
4. The app is embedded at `/embed/d/{deploymentId}/app?session={sessionId}` and displayed in the iframe
43-
44-
Creator mode is enabled automatically when the embed type is "app"; no additional configuration is needed.
45-
46-
### Example
30+
## Example
4731

4832
```javascript
49-
const API_KEY = "YOUR_API_KEY";
50-
const DEPLOYMENT_ID = 32;
51-
5233
const session = await fetch(
5334
"https://your-account.cubecloud.dev/api/v1/embed/generate-session",
5435
{
@@ -58,22 +39,18 @@ const session = await fetch(
5839
Authorization: `Api-Key ${API_KEY}`,
5940
},
6041
body: JSON.stringify({
61-
deploymentId: DEPLOYMENT_ID,
42+
deploymentId: 32,
6243
externalId: "user@example.com",
63-
creatorMode: true,
64-
// Optional — defaults to the current tenant when omitted:
6544
embedTenantName: "acme-corp",
45+
creatorMode: true,
6646
}),
6747
},
6848
);
6949

70-
const data = await session.json();
71-
const sessionId = data.sessionId;
50+
const { sessionId } = await session.json();
7251
```
7352

74-
### Embedding the app
75-
76-
Use the session ID to embed the full Cube application:
53+
Embed the app with the returned session ID:
7754

7855
```html
7956
<iframe
@@ -84,18 +61,7 @@ Use the session ID to embed the full Cube application:
8461
></iframe>
8562
```
8663

87-
Replace `{deploymentId}` with your deployment ID and `{sessionId}` with the session ID returned from the Generate Session API.
88-
89-
## Example application
90-
91-
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:
92-
93-
- A full working example of iframe embedding
94-
- Implementation of signed iframe embedding with session generation
95-
- Support for creator mode with an optional embed tenant name
96-
- A React-based UI for testing embedding functionality
97-
- Backend server that securely handles API key authentication
98-
99-
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.
64+
For a complete working example, see the [cube-embedding-demo](https://github.com/cubedevinc/cube-embedding-demo) repository.
10065

10166
[ref-generate-session]: /reference/embed-apis/generate-session
67+
[ref-bootstrap]: /reference/embed-apis/generate-session#creator-mode-bootstrapping-groups-and-user-attributes

docs-mintlify/reference/embed-apis/generate-session.mdx

Lines changed: 183 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,21 @@ POST https://{accountName}.cubecloud.dev/api/v1/embed/generate-session
3232

3333
| Field | Type | Required | Description |
3434
|-------|------|----------|-------------|
35-
| `externalId` | string | No | Unique identifier for the external user. Either `externalId` or `internalId` should be provided. |
36-
| `internalId` | string | No | Email address of an internal Cube Cloud user. Either `externalId` or `internalId` should be provided. |
37-
| `userAttributes` | array | No | Array of `{name, value}` pairs for row-level security. Not allowed with `internalId`. |
38-
| `groups` | string[] | No | Array of group names for user. Not allowed with `internalId`. |
35+
| `deploymentId` | number | Yes | ID of the deployment the session should grant access to. |
36+
| `externalId` | string | Conditional | Stable identifier for the external user. Provide either `externalId` or `internalId` (not both). Must be lowercase and trimmed. |
37+
| `internalId` | string | Conditional | Username of an existing internal Cube Cloud user. Provide either `externalId` or `internalId` (not both). The user must already exist. |
38+
| `email` | string | No | Email to attach to the provisioned external user. Used only with `externalId`. |
39+
| `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. |
40+
| `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. |
41+
| `userAttributes` | array | No | Attribute values for row-level security. See [User attributes](#user-attributes). Not allowed with `internalId`. |
42+
| `groups` | string[] | No | Group memberships for the user. See [Groups](#groups). Not allowed with `internalId`. |
43+
| `userAttributeDefinitions` | array | No | Idempotently upsert attribute definitions before applying values. Requires `creatorMode: true`. See [Creator mode bootstrap](#creator-mode-bootstrapping-groups-and-user-attributes). |
44+
| `groupDefinitions` | array | No | Idempotently upsert group definitions before assigning memberships. Requires `creatorMode: true`. See [Creator mode bootstrap](#creator-mode-bootstrapping-groups-and-user-attributes). |
3945
| `securityContext` | object | No | Custom security context object passed to Cube queries. Not allowed with `internalId`. |
4046

4147
<Info>
4248

43-
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.
49+
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.
4450

4551
</Info>
4652

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

5157
</Warning>
5258

59+
## User attributes
60+
61+
`userAttributes` is an array of `{ name, value }` pairs that drive row-level security in queries.
62+
63+
```json
64+
{
65+
"userAttributes": [
66+
{ "name": "department", "value": "Sales" },
67+
{ "name": "tier", "value": 2 },
68+
{ "name": "regions", "value": ["us-east", "eu-west"] },
69+
{ "name": "thresholds", "value": [10, 25, 50] }
70+
]
71+
}
72+
```
73+
74+
| Property | Type | Notes |
75+
|----------|------|-------|
76+
| `name` | string | Must reference an existing attribute definition (see lookup rules below). |
77+
| `value` | `string` \| `number` \| `string[]` \| `number[]` \| `null` | The value type must match the definition's `type`. `null` clears the value. |
78+
79+
**Attribute definition lookup**:
80+
81+
- **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`.
82+
- **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).
83+
84+
**Rules**:
85+
86+
- Duplicate `name` entries are rejected with `400 Bad Request`.
87+
- Values are persisted per user. Subsequent calls with the same `externalId` overwrite previous values for the supplied names.
88+
89+
## Groups
90+
91+
`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).
92+
93+
```json
94+
{ "groups": ["analysts", "marketing"] }
95+
```
96+
97+
**Behavior**:
98+
99+
| Value | Effect |
100+
|-------|--------|
101+
| Field omitted (`undefined`) | Existing memberships are preserved. |
102+
| `[]` (empty array) | All memberships are cleared. |
103+
| Populated array | Memberships are replaced with exactly the supplied names. |
104+
105+
**Group definition lookup**:
106+
107+
- **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.
108+
- **Creator mode**: names are resolved against the embed tenant's scoped groups (`embed_user_groups`). Use `groupDefinitions` in the same request to upsert them.
109+
110+
If any name in `groups` cannot be resolved, the request fails with `Groups with names <missing> not found`.
111+
112+
## Creator mode: bootstrapping groups and user attributes
113+
114+
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.
115+
116+
Both fields:
117+
118+
- Require `creatorMode: true`.
119+
- Require an `embedTenantName` (definitions are only meaningful inside an embed tenant).
120+
- Require the `useCreatorMode` tenant flag — contact support to enable.
121+
- Land in the embed-tenant scope only — they never modify tenant-wide groups or attributes.
122+
- Are idempotent: running the same request twice produces the same end state.
123+
124+
### `groupDefinitions`
125+
126+
```json
127+
{
128+
"groupDefinitions": [
129+
{ "name": "analysts", "description": "Read-only viewers" },
130+
{ "name": "marketing" }
131+
]
132+
}
133+
```
134+
135+
| Property | Type | Required | Notes |
136+
|----------|------|----------|-------|
137+
| `name` | string | Yes | Group name. Existing groups with this name are reused. |
138+
| `description` | string | No | Updated when supplied and different from the stored value. Never cleared. |
139+
140+
Duplicate `name` entries within the same request are rejected.
141+
142+
### `userAttributeDefinitions`
143+
144+
```json
145+
{
146+
"userAttributeDefinitions": [
147+
{
148+
"name": "department",
149+
"type": "string",
150+
"displayName": "Department",
151+
"defaultValue": "Unassigned",
152+
"description": "Org unit"
153+
}
154+
]
155+
}
156+
```
157+
158+
| Property | Type | Required | Notes |
159+
|----------|------|----------|-------|
160+
| `name` | string | Yes | Attribute name. Existing attributes with this name are reused. |
161+
| `type` | enum | Yes | One of `string`, `number`, `string_array`, `number_array`. **Immutable** — see below. |
162+
| `displayName` | string | No | Updated when supplied and different from the stored value. |
163+
| `defaultValue` | string | No | Updated when supplied and different from the stored value. |
164+
| `description` | string | No | Updated when supplied and different from the stored value. |
165+
166+
**`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.
167+
168+
Duplicate `name` entries within the same request are rejected.
169+
170+
### Bootstrap example
171+
172+
Define a group and an attribute, assign the user to both, and mint a session — all in one call:
173+
174+
```javascript
175+
const session = await fetch(
176+
`https://${ACCOUNT_NAME}.cubecloud.dev/api/v1/embed/generate-session`,
177+
{
178+
method: 'POST',
179+
headers: {
180+
'Content-Type': 'application/json',
181+
Authorization: `Api-Key ${API_KEY}`,
182+
},
183+
body: JSON.stringify({
184+
deploymentId: DEPLOYMENT_ID,
185+
externalId: 'user-123',
186+
embedTenantName: 'acme-corp',
187+
creatorMode: true,
188+
189+
// Upserted before validation runs
190+
groupDefinitions: [
191+
{ name: 'analysts', description: 'Read-only viewers' },
192+
],
193+
userAttributeDefinitions: [
194+
{ name: 'department', type: 'string', displayName: 'Department' },
195+
],
196+
197+
// Reference the names we just defined
198+
groups: ['analysts'],
199+
userAttributes: [{ name: 'department', value: 'Sales' }],
200+
}),
201+
},
202+
);
203+
```
204+
205+
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.
206+
207+
## Embed-tenant admin API
208+
209+
To list or delete the groups and attributes that have been bootstrapped into an embed tenant, use the admin endpoints scoped to that tenant:
210+
211+
```text
212+
GET /api/v1/embed-tenants/{embedTenantName}/groups
213+
DELETE /api/v1/embed-tenants/{embedTenantName}/groups/{id}
214+
GET /api/v1/embed-tenants/{embedTenantName}/user-attributes
215+
DELETE /api/v1/embed-tenants/{embedTenantName}/user-attributes/{id}
216+
```
217+
218+
These endpoints use the same `Api-Key` authentication as Generate Session and require admin access. List endpoints return cursor-paginated results (`?first=`, `?after=`).
219+
53220
### Response
54221

55222
The API returns a session object:
@@ -84,10 +251,12 @@ response = requests.post(
84251
'Authorization': f'Api-Key {API_KEY}'
85252
},
86253
json={
254+
'deploymentId': 32,
87255
'externalId': 'user@example.com',
88256
'userAttributes': [
89257
{'name': 'department', 'value': 'Sales'}
90-
]
258+
],
259+
'groups': ['analysts']
91260
}
92261
)
93262

@@ -108,10 +277,12 @@ const response = await fetch(
108277
'Authorization': `Api-Key ${API_KEY}`
109278
},
110279
body: JSON.stringify({
280+
deploymentId: 32,
111281
externalId: 'user@example.com',
112282
userAttributes: [
113283
{ name: 'department', value: 'Sales' }
114-
]
284+
],
285+
groups: ['analysts']
115286
})
116287
}
117288
);
@@ -124,10 +295,12 @@ curl -X POST "https://your-account.cubecloud.dev/api/v1/embed/generate-session"
124295
-H "Content-Type: application/json" \
125296
-H "Authorization: Api-Key YOUR_API_KEY" \
126297
-d '{
298+
"deploymentId": 32,
127299
"externalId": "user@example.com",
128300
"userAttributes": [
129301
{"name": "department", "value": "Sales"}
130-
]
302+
],
303+
"groups": ["analysts"]
131304
}'
132305
```
133306

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

138311
[ref-api-keys]: /admin/account-billing/api-keys
139-
[ref-signed-embedding]: /embedding/iframe/auth/signed
312+
[ref-signed-embedding]: /embedding/iframe/auth/signed
313+
[ref-creator-mode]: /embedding/iframe/creator-mode

0 commit comments

Comments
 (0)