# Embed payload reference > Complete reference for the Holistics embed payload: embedded objects, user identity, permissions, settings, and URL parameters This reference covers every parameter you can use when embedding. The **embed payload** is the signed JSON your backend turns into a token. It describes what to show, who is viewing, and what they can see and do. A handful of unsigned **URL parameters** adjust the UI on top of that. If you're embedding for the first time, start with the [Quickstart](/embedded/quickstart). Come back here when you need the full list. **How parameters work:** | | [**Payload parameters**](#payload-parameters-jwt-signed) | [**URL parameters**](#url-parameters-not-signed) | | ------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | **Location** | [Signed JWT token](/embedded/security#secret-key) | Appended to the embed URL | | **Purpose** | Content, security, permissions, data access (which dashboards to show, row-level rules, export rights) | UI, navigation, display preferences (expand the navigation panel, deep-link to a dashboard, pre-fill a filter) | | **User modifiable** | No | Yes | ## Payload parameters (JWT-signed) Payload parameters are included in the JWT your backend signs with your embed Secret. Because they're cryptographically signed, viewers can't change them, which makes them the right place for anything that affects content, identity, or data access. ### Embedded objects Every payload says what to embed: either a list of dashboards and datasets, or the name of a persisted [Embed Portal](/embedded/embed-portal/). It also sets when the token expires. | Parameter | Type | Description | Required | | -------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | | `objects.dashboards` | array | Dashboards to embed, as a list of unique names. | Yes, unless using `embed_portal` | | `objects.datasets` | array | Datasets to embed, by unique name. Adding a dataset unlocks [exploration, drill-down, and view underlying data](/embedded/self-serve-exploration) on it, and lets [Ask AI](/embedded/ask-ai) query it. | No | | `embed_portal` | string | Name of a persisted [Embed Portal](/embedded/embed-portal/). Use instead of `objects` when your embedded content is defined as code in Holistics. | Yes, unless using `objects` | | `exp` | number | [Token expiration](/embedded/security#token-expiration) as a Unix timestamp (e.g., `1769502969`). The token is rejected after this time. | Recommended | **Example: inline objects** ```javascript const payload = { objects: { dashboards: ["sales_overview", "revenue_trends"], datasets: ["ecommerce"], }, exp: Math.floor(Date.now() / 1000) + 3600, // Expires in 1 hour }; ``` **Example: persisted Embed Portal** ```javascript const payload = { embed_portal: "customer_portal", exp: Math.floor(Date.now() / 1000) + 3600, }; ``` :::caution One source of objects Use either `embed_portal` or `objects`, not both. A payload that sets both is rejected, so it's always clear where the embedded content comes from. ::: :::tip Finding unique names Dashboards and datasets are referenced by the unique name declared in AML (the name after `Dashboard` or `Dataset`), not by their display title. The **Embedded Analytics Sandbox** on the Embedded Analytics page shows the exact names and generates a payload for you. ::: ### User identity These parameters identify who's viewing. They unlock personal features like saving dashboards, email subscriptions, and organization workspaces, and they let Holistics attribute activity to a user in logs. | Parameter | Type | Description | Required | | ------------------ | ------ | ----------------------------------------------------------------------------------------------------------------- | -------------------------------- | | `embed_user_id` | string | Unique identifier for the user in your system. See [Identity & Workspace](/embedded/identity-workspace). | For user-built dashboards and email subscriptions | | `embed_org_id` | string | Unique identifier for the user's organization. See [Identity & Workspace](/embedded/identity-workspace). | For organization workspaces | | `embed_user_email` | string | User's email address for [email subscriptions](/embedded/email-subscriptions) | For email subscriptions | **Example:** ```javascript const payload = { // ... embedded objects embed_user_id: "user_123", embed_org_id: "org_456", embed_user_email: "user@example.com", }; ``` ### Data access Control which rows each viewer can see. There are two ways to express [row-level permissions](/embedded/row-level-permissions), and you can use both at once. When both apply, they are combined with AND, so the payload can only narrow access, never widen it. | Parameter | Type | Description | Required | | ------------------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | | `permissions.row_based` | array | Direct row-level permissions written in the payload. Each rule has a `path` (`dataset`, `model`, `field`), an `operator`, `values`, and an optional `modifier`. See [Direct permissions](/embedded/row-level-permissions#option-a-direct-permissions-in-the-embed-payload). | If restricting data without dataset rules | | `user_attributes` | object | Key-value pairs matched by [attribute-based row-level permissions defined in your datasets](/embedded/row-level-permissions#option-b-attribute-based-permissions-in-datasets). Values must be arrays (e.g., `region: ['US']`). Also used by [dynamic data sources](/embedded/dynamic-data-sources), [localization](/embedded/localization), and as [Ask AI context](/docs/ai/context/custom-context). | If using dataset rules, dynamic data sources, or Ask AI | **Example:** ```javascript const payload = { // ... embedded objects and user identity permissions: { row_based: [ { path: { dataset: "ecommerce", model: "companies", field: "id" }, operator: "is", values: [42], }, ], }, user_attributes: { region: ["US", "EU"], company_id: [42], }, }; ``` ### Settings Configure what viewers can do with the data and how dashboards are displayed. Settings apply to every dashboard in the embed. | Parameter | Type | Description | Default | | ------------------------------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | | `settings.allow_dashboard_export` | boolean | Allow users to export dashboards (PDF, PNG) | `false` | | `settings.allow_raw_data_export` | boolean | Allow raw data export (CSV, Excel) | `false` | | `settings.allow_data_subscribe` | boolean | Enable [email subscriptions](/embedded/email-subscriptions). Requires `embed_user_id`, `embed_user_email`, and `allow_dashboard_export`. | `false` | | `settings.ai.enabled` | boolean | Enable [Ask AI](/embedded/ask-ai). Requires at least one dataset in `objects.datasets` or the portal. | `false` | | `settings.default_timezone` | string | Timezone for data display (e.g., `"UTC"`, `"America/New_York"`). See [Timezone settings](/docs/datetimes/timezones). | Workspace default | | `settings.allow_dashboard_timezone_change` | boolean | Allow users to change the current dashboard's timezone | `true` | | `settings.hide_header_panel` | boolean | Hide the dashboard header panel (title and actions), for example when your app already shows a heading | `false` | | `settings.hide_dashboard_filters_controls_panel` | boolean | Hide the dashboard filter and control panel. Combine with [default filter values](#default-filter-values) or [embed events](/embedded/embed-events) if your app drives the filters itself. | `false` | | `settings.dashboard_autorun_on_changes` | boolean | Re-run the dashboard automatically whenever filters or controls change, without clicking Apply. Overrides the dashboard's own [auto-run on changes](/docs/dashboards/settings#auto-run-on-changes) setting. Every change fires queries, so leave it off for heavy dashboards. | `false` | **Example:** ```javascript const payload = { // ... embedded objects and user identity settings: { default_timezone: "America/New_York", ai: { enabled: true }, allow_dashboard_export: true, allow_raw_data_export: false, allow_data_subscribe: true, allow_dashboard_timezone_change: true, hide_header_panel: false, hide_dashboard_filters_controls_panel: false, dashboard_autorun_on_changes: true, }, }; ``` ### Workspace permissions Define whether the viewer can save their own dashboards and collaborate with their organization. These require `embed_user_id` (and `embed_org_id` for the organization workspace). | Parameter | Type | Description | Default | | --------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | | `permissions.enable_personal_workspace` | boolean | Allow the user to save dashboards to a [personal workspace](/embedded/identity-workspace#option-1-individual-users-only-b2c) | `false` | | `permissions.org_workspace_role` | string | The user's role in the [organization workspace](/embedded/identity-workspace#option-2-business-users-with-organizations-b2b): `'no_access'`, `'viewer'`, `'editor'` | `'no_access'` | **Example:** ```javascript const payload = { // ... embedded objects and user identity permissions: { enable_personal_workspace: true, org_workspace_role: "editor", // Options: 'no_access', 'viewer', 'editor' }, }; ``` ### Full payload example Here's a complete example combining every section: ```javascript const payload = { // What to embed objects: { dashboards: ["sales_overview", "revenue_trends"], datasets: ["ecommerce"], }, // Who is viewing embed_user_id: "user_123", embed_org_id: "org_456", embed_user_email: "user@example.com", // What data they can see user_attributes: { region: ["US", "EU"], company_id: [42], }, // What they can do permissions: { enable_personal_workspace: true, org_workspace_role: "editor", }, settings: { default_timezone: "America/New_York", ai: { enabled: true }, allow_dashboard_export: true, allow_raw_data_export: false, allow_data_subscribe: true, dashboard_autorun_on_changes: true, }, // Token expiration (Unix timestamp) exp: Math.floor(Date.now() / 1000) + 3600, // Expires in 1 hour }; // Generate JWT token const embedSecret = "YOUR_EMBED_SECRET"; // Replace with your Secret from Holistics const token = jwt.sign(payload, embedSecret, { algorithm: "HS256" }); ``` ### Production checklist The payload structure is standard, but some values must match your Holistics setup and your own user model. Check these before signing the token and building the embed URL: - `objects.dashboards` and `objects.datasets` use unique names from AML, not display titles. If you use `embed_portal`, the name must match a published Embed Portal. - Every payload that serves more than one customer carries [row-level permissions](/embedded/row-level-permissions), through `permissions.row_based`, `user_attributes`, or both. - `user_attributes` keys match the attributes used by your dataset permission rules. You can manage user attributes programmatically with the [User Attributes API](/api/v2/reference/user-attributes-list) and [User Attribute Entries API](/api/v2/reference/user-attribute-entries-list). - `embed_user_id` and `embed_org_id` are stable identifiers from your own application. - The embed URL uses the correct regional or custom domain and your Key ID. - Feature flags such as AI, subscriptions, exports, and workspace permissions match your product and security policy. - `exp` is set, ideally 24 hours or less. ## URL parameters (not signed) URL parameters customize the UI without regenerating tokens. Use them to control navigation panel state, deep-link to a specific dashboard, or pre-fill a filter. They don't affect security or data access, so viewers can safely change them (which also makes them good for bookmarks and shared links). ### URL structure Your embed URL must use the domain of your Holistics data center. Holistics has three regional app domains: APAC uses `secure.holistics.io`, US uses `us.holistics.io`, and EU uses `eu.holistics.io`. If you're not sure which one your account uses, see [Data Centers](/docs/security-compliance/data-centers#how-do-i-know-which-data-center-im-on). If you use a custom domain, replace the full host with it. App domain ``` https://secure.holistics.io/embed/{embed_key_id}/{initial_object}?_token={token}&{query_params} └──────┬─────┘ └──────┬───────┘ └──┬──┘ └─────┬─────┘ Key ID Path (optional) Token Query params ``` ``` https://us.holistics.io/embed/{embed_key_id}/{initial_object}?_token={token}&{query_params} └──────┬─────┘ └──────┬───────┘ └──┬──┘ └─────┬─────┘ Key ID Path (optional) Token Query params ``` ``` https://eu.holistics.io/embed/{embed_key_id}/{initial_object}?_token={token}&{query_params} └──────┬─────┘ └──────┬───────┘ └──┬──┘ └─────┬─────┘ Key ID Path (optional) Token Query params ``` | Component | Description | | ------------------ | ------------------------------------------------------------------------------------------ | | `{embed_key_id}` | Your Key ID from the Embedded Analytics page. The same one for every embed. | | `{initial_object}` | Optional path to control which page opens first | | `{query_params}` | Optional query parameters for UI customization (see [Query parameters](#query-parameters)) | ### Initial object (URL path) Deep-link viewers straight to the content they need: a specific dashboard, a dataset, or the Ask AI page. This lets you build targeted links from emails, notifications, or your own navigation. **Supported paths:** - `/objects/`: open a specific dashboard or dataset - `/ai`: open the Ask AI page (requires `settings.ai.enabled: true`) - _(empty)_: use the default (see resolution order below) **Examples:** - Dashboard: `https://{region_domain}.holistics.io/embed/abc123/objects/sales_dashboard?_token=...` - Ask AI: `https://{region_domain}.holistics.io/embed/abc123/ai?_token=...` Replace `{region_domain}` with `secure`, `us`, or `eu`. **Resolution order:** 1. URL path, if specified and the object is in the payload 2. `initial_object` in the [Embed Portal](/embedded/embed-portal/) definition, if you're using one 3. The first dashboard in `objects.dashboards` (or in the portal's `objects`) ### Query parameters Fine-tune the UI with query parameters appended to the embed URL. | Parameter | Values | Default | Description | | ---------------------- | ----------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `left_panel_state` | `expanded`, `collapsed` | `collapsed` | Controls the left navigation panel's expand/collapse state. The panel only appears when the embed has more than one dashboard, dataset, or workspace. | | `{filter_block_uname}` | Any valid filter value | none | Pre-fill a filter on the dashboard the URL opens to, using `is` / `equal to` / `matches`-style conditions. See [Default filter values](#default-filter-values) below, and [Passing filter parameters via URL](/docs/url-parameters) for syntax and [Supported operators](/docs/url-parameters#supported-operators). | ### Default filter values Default filter values set the filters a dashboard opens with. They're useful for showing contextual data on load: a user clicks "Europe" in your app, so the region filter starts on Europe. You set them through URL query parameters, not in the signed payload. Add each filter's unique name as a query parameter on the embed URL, with the value to apply: ``` https://{region_domain}.holistics.io/embed/{embed_key_id}/objects/sales_dashboard?_token=...®ion_filter=Europe ``` The values apply to the dashboard the URL opens to. Query parameters support `is`, `equal to`, and `matches`-style conditions only: relative dates (such as "last 6 months") and other custom operators aren't supported. For those, change the filter with [embed events](/embedded/embed-events#sync-filters-between-your-app-and-the-dashboard) once the dashboard loads. See [Passing filter parameters via URL](/docs/url-parameters) for the full syntax and [Supported operators](/docs/url-parameters#supported-operators). :::danger Not a data security feature Default filter values only set the starting state. URL parameters aren't signed, so viewers can change them, and they can change the filter in the dashboard too. To restrict what data a viewer can see, use [row-level permissions](/embedded/row-level-permissions). See [Enforcing data access control](/embedded/security#enforcing-data-access-control-the-right-way) for the difference. ::: ### URL examples Common ways to combine paths and query parameters: | Use case | URL | | --------------------------- | ------------------------------------------------------------------------------------------------ | | Basic embed | `https://{region_domain}.holistics.io/embed/abc123?_token=...` | | Open a specific dashboard | `https://{region_domain}.holistics.io/embed/abc123/objects/sales_dashboard?_token=...` | | Open the Ask AI page | `https://{region_domain}.holistics.io/embed/abc123/ai?_token=...` | | Expanded navigation panel | `https://{region_domain}.holistics.io/embed/abc123?_token=...&left_panel_state=expanded` | | Open a dashboard pre-filtered | `https://{region_domain}.holistics.io/embed/abc123/objects/sales_dashboard?_token=...®ion=US` | ## Legacy per-dashboard embed links If you embedded a dashboard before the new embed payload, your setup uses a per-dashboard **embed code** and secret, with `filters`, `permissions`, `settings`, and `drillthroughs` at the top level of the payload. Those links keep working, and [Legacy single-dashboard embedding](/embedded/single-dashboard/) documents them. To adopt the parameters on this page (multiple dashboards, datasets, identity, Ask AI), switch to your shared embed credentials and move the dashboard into `objects.dashboards`. The [migration guide](/embedded/single-dashboard/migrate-to-new-embed-payload) covers this step by step. ## Related documentation - [Quickstart](/embedded/quickstart): embed your first dashboard end to end - [Row-level permissions](/embedded/row-level-permissions): restrict data per viewer - [Identity & Workspace](/embedded/identity-workspace): user and organization setup - [Embed Portal](/embedded/embed-portal/): persist embedded objects as code - [Ask AI](/embedded/ask-ai): enable AI features - [Email subscriptions](/embedded/email-subscriptions): schedule email reports