diff --git a/modules/ROOT/pages/api-changelog.adoc b/modules/ROOT/pages/api-changelog.adoc index dbee4d36f..c18283a48 100644 --- a/modules/ROOT/pages/api-changelog.adoc +++ b/modules/ROOT/pages/api-changelog.adoc @@ -8,6 +8,125 @@ This page documents the changes introduced in each release of the Visual Embed SDK. For information about the REST API v2.0 changes, see the xref:rest-apiv2-changelog.adoc[REST API v2.0 changelog]. +== Version 1.53.0, October 2026 + +[width="100%", cols="1,4"] +|==== +|[tag greenBackground]#NEW# +a| +[discrete] +===== Spotter Analyst embed (`spotterAnalystConfig`) + +You can now embed a single, pinned Spotter Analyst using `spotterAnalystConfig.analystId` in `SpotterEmbed`. Setting this property locks the embed to one governed Analyst and prevents users from navigating to other Analysts or to the default Spotter. + +New and updated configuration properties: + +`SpotterAnalystConfig.analystId` (string):: +Pins the embed to the Analyst with this GUID. Available from cluster version 26.10.0.cl. + +`spotterChatPinConfig` (on `SpotterSidebarViewConfig`):: +Enables pinning and unpinning of conversations in the sidebar. Contains `enabled` (boolean, default `false`), `pinLabel` (string), and `unpinLabel` (string). Available from cluster version 26.10.0.cl. + +`isScopedLiveboardFilteringEnabled` (on `LiveboardViewConfig` and `AppViewConfig`):: +Enables group-level and tab-level filters and parameter scoping on Liveboards, in addition to existing Liveboard level filters. + +`starterPrompts` (on `SpotterChatViewConfig`):: +Configures which starter prompt pills are shown above the Spotter chat input. Contains keys: `enable`, `quick`, `research`, `previewData`, and `liveboard`. Available from cluster version 26.10.0.cl. + +`openSpotterOnLiveboardByDefault` (on `SpotterChatViewConfig`):: +Opens the Spotter chat panel automatically when a Liveboard loads. Default: `true`. Supported on `LiveboardEmbed` and `AppEmbed`. Available from cluster version 26.10.0.cl. + +For more information, see xref:embed-spotter-analyst.adoc[Embed Spotter Analyst]. + +|[tag greenBackground]#NEW# +a| +[discrete] +===== New `Action` enum members + +The following `Action` enum members are added in this release: + +[cols="2,3"] +!=== +! Action ! Description + +! `Action.SpotterChatPin` +! Controls the visibility and disabled state of the pin and unpin action in the Spotter conversation edit menu. + +! `Action.SpotterAnalystList` +! Controls the visibility and disabled state of the Show all Analysts row in the Analyst interface. + +! `Action.SpotterDefaultAnalyst` +! Controls the visibility and disabled state of the default Spotter analyst entry in the Analyst interface. + +! `Action.SpotterOnLiveboard` +! Controls the Spotter button in the Liveboard header. + +! `Action.AllLiveboardFilters` +! Shows, hides, or disables all filter surfaces on a Liveboard: filter chips, parameter chips, and cross-filter chips at the Liveboard, tab, and group levels. Parameter and cross-filter chips support hide only and cannot be disabled. + +! `Action.EditInputTable` +! Edits an input table used by an Answer directly from the Liveboard. + +! `Action.QuickSearchPill` +! Controls the Basic Search starter-prompt pill in the Spotter interface. + +! `Action.DeepAnalysisPill` +! Controls the Deep Analysis starter-prompt pill in the Spotter interface. + +! `Action.DataLiteracyPill` +! Controls the Data Literacy starter-prompt pill in the Spotter interface. +!=== + +|[tag greenBackground]#NEW# +a| +[discrete] +===== New `EmbedEvent` members + +`EmbedEvent.SpotterConversationPinned`:: +Emitted when a user pins a Spotter conversation. Payload: `{ conversationId, pinnedAt }`. Requires `spotterChatPinConfig.enabled: true` and `enablePastConversationsSidebar: true`. + +`EmbedEvent.SpotterConversationUnpinned`:: +Emitted when a user unpins a Spotter conversation. Payload: `{ conversationId, unpinnedAt }`. Requires `spotterChatPinConfig.enabled: true` and `enablePastConversationsSidebar: true`. + +The following existing `EmbedEvent` members gained an optional `applicability` attribute for scoped filter and parameter operations: + +* `EmbedEvent.FilterChanged` +* `EmbedEvent.ParameterChanged` + +|[tag greenBackground]#NEW# +a| +[discrete] +===== New `HostEvent` members + +`HostEvent.PinSpotterConversation`:: +Pins a saved Spotter conversation. Accepts `{ conversationId }`. Requires `enablePastConversationsSidebar: true` on the instance. + +`HostEvent.UnpinSpotterConversation`:: +Unpins a previously pinned Spotter conversation. Accepts `{ conversationId }`. Requires `enablePastConversationsSidebar: true` on the instance. + +`HostEvent.GetGroups`:: +Returns filter and parameter group details for the current Liveboard. Response includes `orderedGroupIds`, `numberOfGroups`, and `Groups`. + +`HostEvent.OpenParameter`:: +Opens the parameter panel for a specific parameter on the Liveboard. Accepts an optional `applicability` object to scope the action to a tab or group. + +The following existing `HostEvent` members gained an optional `applicability` attribute for scoping to a Liveboard tab or group: + +* `HostEvent.OpenFilter` +* `HostEvent.GetFilters` +* `HostEvent.UpdateFilters` +* `HostEvent.UpdateParameters` +* `HostEvent.GetParameters` + +|[tag yellowBackground]#DEPRECATED# +a| +[discrete] +===== `HostEvent.UpdatePersonalizedView` deprecated + +`HostEvent.UpdatePersonalizedView` is deprecated in this release. Use `HostEvent.SelectPersonalizedView` instead. The replacement accepts an optional `viewName` to select a view by name, resets to the original view when the payload is empty, and reports an error when the named view is not found. + +|==== + == Version 1.52.x, September 2026 [width="100%" cols="1,4"] diff --git a/modules/ROOT/pages/common/nav-rest-api.adoc b/modules/ROOT/pages/common/nav-rest-api.adoc index 0251c0f31..e74ec5297 100644 --- a/modules/ROOT/pages/common/nav-rest-api.adoc +++ b/modules/ROOT/pages/common/nav-rest-api.adoc @@ -21,6 +21,7 @@ REST API endpoints ** link:{{navprefix}}/api-user-management[Users and group privileges] ** link:{{navprefix}}/rbac[Role-based access control] ** link:{{navprefix}}/audit-logs[Audit logs] +** link:{{navprefix}}/feature-management[Feature Management] * Multi-tenancy and Orgs ** link:{{navprefix}}/orgs-api-op[Orgs APIs] diff --git a/modules/ROOT/pages/data-security.adoc b/modules/ROOT/pages/data-security.adoc index ae6adf312..b10d14e9f 100644 --- a/modules/ROOT/pages/data-security.adoc +++ b/modules/ROOT/pages/data-security.adoc @@ -26,3 +26,14 @@ The OAuth workflow requires opening a new window or redirecting to the OAuth pro CLS restricts user access to specific columns of a table. When CLS is applied, users see only the columns that they are allowed to view. Object owners can configure CLS by sharing a relevant set of columns in a table with a specific user or user group. For more information on CLS, see link:https://docs.thoughtspot.com/cloud/latest/share-source-tables[Sharing tables and columns, window=_blank]. + +[#csr-liveboards] +=== #Column security rules on Liveboards# +#Starting with ThoughtSpot Cloud 26.10.0.cl, Liveboards that include columns restricted by Column Security Rules (CSR) open and work normally for users who cannot access those columns, including in embedded Liveboards. Previously, such Liveboards were blocked for these users. Column security remains fully enforced:# + +* #Filter values from columns that the user cannot access are masked instead of blocking the Liveboard.# +* #Scheduled Liveboard deliveries apply CSR separately for each recipient.# + +#To control whether masked filter chips are visible in an embedded Liveboard, use the `showMaskedFilterChip` SDK property. For more information, see xref:embed-pinboard.adoc#masked-filter-chips[Masked filter chips].# + +#For more information, see link:https://docs.thoughtspot.com/cloud/latest/security-data-object#csr-liveboard[Column security rules on Liveboards, window=_blank].# diff --git a/modules/ROOT/pages/embed-pinboard.adoc b/modules/ROOT/pages/embed-pinboard.adoc index 3d1618160..860f70f88 100644 --- a/modules/ROOT/pages/embed-pinboard.adoc +++ b/modules/ROOT/pages/embed-pinboard.adoc @@ -264,6 +264,23 @@ When `hideIrrelevantChipsInLiveboardTabs` is `true`: * A *Show irrelevant filters* toggle button appears in the filter row when at least one chip is hidden, allowing users to temporarily reveal all chips. * When the user clicks *Show irrelevant filters*, a complementary *Hide irrelevant filters* button appears to restore the filtered view. +[#masked-filter-chips] +==== #Masked filter chips# +#If a Liveboard includes filters on columns that a user cannot access because of column-level security, the filter values are masked for that user. Use the `showMaskedFilterChip` property to control whether these masked filter chips are visible:# + +* #`true`: the filter chips for inaccessible columns are displayed as masked.# +* #`false`: the filter chips for inaccessible columns are hidden.# + +[source,JavaScript] +---- +const liveboardEmbed = new LiveboardEmbed(document.getElementById('ts-embed'), { + //... other embed config properties + showMaskedFilterChip: true, +}); +---- + +#The `showMaskedFilterChip` property is also available in full application embedding. For more information, see xref:data-security.adoc#csr-liveboards[Column security rules on Liveboards].# + [#noteTiles] === Add Note tiles You can add a link:https://docs.thoughtspot.com/cloud/latest/liveboard-notes[Liveboard Note tile, window=_blank] with custom text, images, and links on an embedded Liveboard. @@ -384,6 +401,56 @@ limit are silently dropped without an error or warning. For more information, se xref:runtime-filters.adoc#_maximum_filter_count[Runtime filter limit]. ==== +[#contextual-liveboard-filtering] +==== #Contextual filtering in Liveboards# [earlyAccess eaBackground]#Early Access# +Starting with ThoughtSpot Cloud 26.10.0.cl release, Liveboard filters and parameters can be scoped at three levels: + +* *Liveboard*: applies to all visualizations on the Liveboard. +* *Tab*: applies only to visualizations on a specific tab. +* *Group*: applies only to visualizations in a specific group on a tab. + +With contextual filtering, you can add the same filter at more than one of these levels on a Liveboard. For example, a Liveboard can have a `Region` filter at the Liveboard level and another independent `Region` filter on a specific tab or group. + +[NOTE] +==== +Contextual filtering in Liveboards is an Early Access feature and is disabled by default on ThoughtSpot instances. To enable this feature on your instance, set `isScopedLiveboardFilteringEnabled` to `true`. +==== + + +[source,JavaScript] +---- +const liveboardEmbed = new LiveboardEmbed(document.getElementById('ts-embed'), { + //... other embed config properties + liveboardId: "d7a5a08e-a1f7-4850-aeb7-0764692855b8", + isScopedLiveboardFilteringEnabled: true, +}); +---- + +The `isScopedLiveboardFilteringEnabled` property is also available in `AppViewConfig` for full application embedding. + +To get the groups on a Liveboard, use `HostEvent.GetGroups`. To scope a filter or parameter update to a specific tab or group, pass the `applicability` attribute with `HostEvent.UpdateFilters` or `HostEvent.UpdateParameters`: + +[source,javascript] +---- +liveboardEmbed.trigger(HostEvent.UpdateFilters, { + filters: [ + { + column: 'Region', + oper: 'IN', + values: ['West'], + applicability: { + level: 'GROUP', + targetId: '{group-id}', + }, + }, + ], +}); +---- + +To listen for filter and parameter changes, use `EmbedEvent.FilterChanged` and `EmbedEvent.ParameterChanged`. Starting with SDK 1.53.0, both events include an optional `applicability` field in their response payload that indicates the scope of the change. + +For more information, see xref:events-hostEvents.adoc#liveboard-group-events[Liveboard group and parameter events] and xref:events-hostEvents.adoc#applicability-host-events[Scoped filter and parameter host events]. + ==== Updating filters Use the following host events in the Visual Embed SDK to update filters: diff --git a/modules/ROOT/pages/embed-spotter-analyst.adoc b/modules/ROOT/pages/embed-spotter-analyst.adoc new file mode 100644 index 000000000..badd322a1 --- /dev/null +++ b/modules/ROOT/pages/embed-spotter-analyst.adoc @@ -0,0 +1,300 @@ += Embed Spotter Analyst +:toc: true +:toclevels: 2 + +:page-title: Embed Spotter Analyst +:page-pageid: embed-spotter-analyst +:page-description: Embed a single, pinned Spotter Analyst in your application using the Visual Embed SDK + +// SOURCE: SCAL-317811, SDK-1.53.0-changelog.md, Spotter embed developer cheatsheet + +ThoughtSpot Spotter Analysts are governed AI agents configured with specific data sources, instructions, and starter prompts. Using the Visual Embed SDK, you can embed a single, pinned Analyst in your application. This locks the embed to one governed experience and prevents users from switching to other Analysts or to the default Spotter. + +== Version requirements + +[cols="1,2"] +|=== +| Component | Minimum version + +| Visual Embed SDK | 1.51.2 +| ThoughtSpot cluster | 26.10.0.cl +|=== + +[NOTE] +==== +Some controls described in this page are available on earlier cluster versions (26.3 through 26.9). The `spotterAnalystConfig.analystId` property itself requires cluster version 26.10.0.cl. Use 26.10.0.cl as the minimum version requirement when setting up the single-Analyst embed configuration. +==== + +== How it works + +Use `spotterAnalystConfig.analystId` in `SpotterEmbed` to pin the embed to one Analyst. By default, with no additional configuration, the Analyst panel and a switcher rail remain visible and users can navigate to other Analysts. To create a fully locked experience, you must also hide the switcher actions. + +== Minimal configuration + +The following example embeds one Analyst with the chat history sidebar disabled and the switcher hidden: + +[source,javascript] +---- +// In server-side rendered frameworks (Next.js, Nuxt, SvelteKit), +// import the SDK dynamically to avoid window reference errors. +const { init, SpotterEmbed, AuthType } = + await import('@thoughtspot/visual-embed-sdk'); + +init({ + thoughtSpotHost: 'https://{cluster}', + authType: AuthType.None, // uses the browser's existing session +}); + +new SpotterEmbed(container, { + frameParams: { width: '100%', height: '100%' }, + worksheetId: '{model-guid}', + + // Pin to one Analyst. + spotterAnalystConfig: { analystId: '{analyst-guid}' }, + + // Disable the chat history sidebar. + spotterSidebarConfig: { enablePastConversationsSidebar: false }, + + // Hide the switcher so users cannot navigate to a different Analyst. + hiddenActions: [ + 'spotterAnalystSidebar', + 'spotterDefaultAnalyst', + 'spotterAnalystList', + ], + + hideSourceSelection: true, + disableSourceSelection: true, +}).render(); +---- + +== Configuration reference + +=== `spotterAnalystConfig` + +Type: `SpotterAnalystConfig`. Available from SDK 1.53.0 and ThoughtSpot Cloud 26.10.0.cl. + +Available on `SpotterEmbedViewConfig`. Pins the embed to a single Analyst. + +[cols="1,1,1,3"] +|=== +| Property | Type | Cluster version | Description + +| `analystId` +| string +| 26.10.0.cl +| GUID of the Analyst to display. Obtain this value from the xref:spotter-analyst-api.adoc[Spotter Analyst API] or from the ThoughtSpot UI. +|=== + +=== `spotterSidebarConfig` + +Type: `SpotterSidebarViewConfig`. + +[cols="1,1,1,3"] +|=== +| Property | Type | Cluster version | Description + +| `enablePastConversationsSidebar` +| boolean +| 26.4.0.cl +| Shows or hides the chat history sidebar. Set this property explicitly. Leaving it unset applies the cluster default, which may be `true`. + +| `spotterChatPinConfig` +| `SpotterChatPinConfig` +| 26.10.0.cl +| Enables pinning and unpinning conversations in the sidebar. See xref:embed-spotter-analyst.adoc#pinning-conversations[Pinning conversations]. +|=== + +=== `worksheetId` and `dataSources` + +[cols="1,1,3"] +|=== +| Property | Cluster version | Description + +| `worksheetId` +| All +| GUID of the single model Spotter queries. Include this property alongside `spotterAnalystConfig`. Omitting it can prevent host-triggered questions from executing. + +| `dataSources` +| 26.9.0.cl +| Array of model GUIDs when the Analyst spans multiple models. If both `dataSources` and `worksheetId` are set, `dataSources` takes precedence. +|=== + +=== Locking the embed with `hiddenActions` + +Pinning an Analyst without hiding the switcher only changes the default selection. Users can still navigate to a different Analyst. Use the following three action IDs together to prevent this: + +[cols="1,1,1"] +|=== +| Action ID | What it hides | Cluster version + +| `spotterAnalystSidebar` +| The Analyst selection panel +| 26.8.0.cl + +| `spotterDefaultAnalyst` +| The default Spotter row +| 26.10.0.cl + +| `spotterAnalystList` +| The Show all Analysts row +| 26.10.0.cl +|=== + +[NOTE] +==== +An action ID not recognized by the cluster is silently dropped and does not cause an error. You can include all three action IDs even when targeting a cluster that does not yet support one of them. +==== + +If a narrow sidebar rail (expand toggle, New chat icon, or footer gear icon) remains visible after hiding these three actions, add the following shell-level action IDs. These are supported from cluster version 26.3.0.cl: + +[source,javascript] +---- +hiddenActions: [ + 'spotterAnalystSidebar', + 'spotterDefaultAnalyst', + 'spotterAnalystList', + 'spotterSidebarOpen', + 'spotterSidebarClose', + 'spotterNewConversation', + 'spotterSidebarSettings', +], +---- + +=== Starter prompts + +Use `starterPrompts` in `SpotterChatViewConfig` to customize the starter prompt pills displayed above the chat input. + +[cols="1,1,1,3"] +|=== +| Property | Type | Cluster version | Description + +| `starterPrompts` +| `StarterPromptsConfig` +| 26.10.0.cl +| Top-level configuration object for Spotter starter prompts. Contains keys: `enable`, `quick`, `research`, `previewData`, and `liveboard`. + +| `openSpotterOnLiveboardByDefault` +| boolean +| 26.10.0.cl +| Opens the Spotter chat panel automatically when a Liveboard loads. Default: `true`. Supported in `LiveboardEmbed` and `AppEmbed`. +|=== + +To show or hide individual starter prompt pills, use the `Action` enum: + +[cols="1,3"] +|=== +| Action | Description + +| `Action.QuickSearchPill` +| The Basic Search starter-prompt pill. Opens a card of suggested questions that submit on click. + +| `Action.DeepAnalysisPill` +| The Deep Analysis pill. Fills the chat input with a suggested question without auto-submitting. + +| `Action.DataLiteracyPill` +| The Data Literacy pill. Submits a backend-generated prompt describing the data source. Only its label is customizable. +|=== + +[source,javascript] +---- +hiddenActions: [ + Action.QuickSearchPill, + Action.DeepAnalysisPill, + Action.DataLiteracyPill, +], +---- + +[NOTE] +==== +Setting `hideSampleQuestions: true` hides both the generic sample questions and the Analyst's own starter prompts, as they share the same block. This is generally not the intended behavior when embedding a governed Analyst. +==== + +=== Pre-filling the chat input + +Use `searchOptions.searchQuery` to pre-fill the prompt. This does not submit the question. To submit it, also fire `HostEvent.SpotterSearch` with `executeSearch: true`. + +[source,javascript] +---- +new SpotterEmbed(container, { + searchOptions: { + searchQuery: 'What was total revenue last quarter?', + }, + // ... +}).render(); +---- + +[#pinning-conversations] +== Pinning conversations + +`SpotterChatPinConfig` lets users pin Spotter conversations so they appear at the top of the sidebar for quick access. Pinning is disabled by default in embedded deployments and must be explicitly enabled. + +[cols="1,1,1,3"] +|=== +| Property | Type | Default | Description + +| `enabled` +| boolean +| `false` +| Enables the pin and unpin actions in the conversation edit menu. Set to `true` to allow users to pin conversations. + +| `pinLabel` +| string +| System default +| Custom label for the pin action in the conversation edit menu. + +| `unpinLabel` +| string +| System default +| Custom label for the unpin action in the conversation edit menu. +|=== + +[source,javascript] +---- +new SpotterEmbed(container, { + spotterSidebarConfig: { + enablePastConversationsSidebar: true, + spotterChatPinConfig: { + enabled: true, + pinLabel: 'Save to top', + unpinLabel: 'Remove from top', + }, + }, + // ... +}).render(); +---- + +To listen for pin and unpin events, or to trigger pin state programmatically from the host application, see xref:event-embedEvents.adoc#pin-events[Spotter pin and unpin events] and xref:events-hostEvents.adoc#spotter-pin-host-events[Spotter conversation pin and unpin]. + +== New actions in SDK 1.53.0 + +The following `Action` enum members are new in SDK 1.53.0 and are relevant to Analyst embed: + +[cols="1,3"] +|=== +| Action | Description + +| `Action.SpotterChatPin` +| Controls visibility and disabled state of the pin and unpin action in the Spotter conversation edit menu. + +| `Action.SpotterAnalystList` +| Controls visibility and disabled state of the Show all Analysts row in the Analyst interface. + +| `Action.SpotterDefaultAnalyst` +| Controls visibility and disabled state of the default Spotter analyst entry in the Analyst interface. + +| `Action.SpotterOnLiveboard` +| The Spotter button in the Liveboard header. + +| `Action.AllLiveboardFilters` +| Shows, hides, or disables all filter surfaces on a Liveboard: filter chips, parameter chips, and cross-filter chips at the Liveboard, tab, and group levels. Parameter and cross-filter chips support hide only and cannot be disabled. + +| `Action.EditInputTable` +| Edits an input table used by an Answer directly from the Liveboard. +|=== + +== Related resources + +* xref:spotter-analyst-api.adoc[Spotter Analyst API] +* xref:event-embedEvents.adoc[Embed events reference] +* xref:events-hostEvents.adoc[Host events reference] +* xref:customize-spotter-embed.adoc[Customize Spotter embed] diff --git a/modules/ROOT/pages/event-embedEvents.adoc b/modules/ROOT/pages/event-embedEvents.adoc index 6b7655f0f..d8162285c 100644 --- a/modules/ROOT/pages/event-embedEvents.adoc +++ b/modules/ROOT/pages/event-embedEvents.adoc @@ -290,8 +290,78 @@ image::./images/embed-event-playground.png[Try Embed event in Playground] == Event enumerations and examples For information about the supported event objects and examples, see xref:EmbedEvent.adoc[EmbedEvent]. +[#pin-events] +=== Spotter conversation pin events + +The following `EmbedEvent` members are available from ThoughtSpot Cloud 26.10.0.cl and Visual Embed SDK 1.53.0. Both events require `spotterChatPinConfig.enabled: true` and `enablePastConversationsSidebar: true` in the embed configuration. + +[cols="1,1,3"] +|=== +| Event | Cluster version | Description + +| `EmbedEvent.SpotterConversationPinned` +| 26.10.0.cl +| Emitted when a user pins a Spotter conversation. Payload: `{ conversationId, pinnedAt }`. + +| `EmbedEvent.SpotterConversationUnpinned` +| 26.10.0.cl +| Emitted when a user unpins a Spotter conversation. Payload: `{ conversationId, unpinnedAt }`. +|=== + +.Listen for pin and unpin events +[source,javascript] +---- +const embed = new SpotterEmbed(container, { + spotterSidebarConfig: { + enablePastConversationsSidebar: true, + spotterChatPinConfig: { enabled: true }, + }, + // ... +}); + +embed.on(EmbedEvent.SpotterConversationPinned, (event) => { + const { conversationId, pinnedAt } = event.data; + console.log(`Conversation ${conversationId} pinned at ${pinnedAt}`); +}); + +embed.on(EmbedEvent.SpotterConversationUnpinned, (event) => { + const { conversationId, unpinnedAt } = event.data; + console.log(`Conversation ${conversationId} unpinned at ${unpinnedAt}`); +}); + +embed.render(); +---- + +[#applicability-scope] +=== Scoped filter and parameter events + +The following `EmbedEvent` members gained an optional `applicability` attribute in SDK 1.53.0. This attribute scopes a filter or parameter change notification to a specific Liveboard tab or group. + +[cols="1,3"] +|=== +| Event | Change in SDK 1.53.0 + +| `EmbedEvent.FilterChanged` +| Payload gains an optional `applicability` object describing the scope of the changed filter. + +| `EmbedEvent.ParameterChanged` +| Payload gains an optional `applicability` object describing the scope of the changed parameter. +|=== + +The `applicability` object has the following shape: + +[source,json] +---- +{ + "level": "LIVEBOARD" | "TAB" | "GROUP", + "targetId": "{tab-or-group-id}" +} +---- + +`targetId` is optional. Omit it when `level` is `LIVEBOARD`. + + == Additional resources * See the xref:EmbedEvent.adoc[EmbedEvent] and xref:HostEvent.adoc[HostEvent] SDK documentation. * For information about triggering events on React components, see xref:react-components_lesson-04.adoc[Event listeners for React components]. - diff --git a/modules/ROOT/pages/events-hostEvents.adoc b/modules/ROOT/pages/events-hostEvents.adoc index 3016a3500..20272105c 100644 --- a/modules/ROOT/pages/events-hostEvents.adoc +++ b/modules/ROOT/pages/events-hostEvents.adoc @@ -184,6 +184,11 @@ Updates the filters applied on an embedded Liveboard. For more information and e ==== HostEvent.OpenFilter Opens the filter panel for the specified column. For more information and examples, see xref:HostEvent.adoc#_openfilter[HostEvent reference documentation]. +[NOTE] +==== +Starting with SDK 1.53.0, the `EmbedEvent.FilterChanged` and `EmbedEvent.ParameterChanged` events include an optional `applicability` field in their response payload. This field describes the scope (Liveboard, tab, or group) of the filter or parameter change that triggered the event. +==== + ==== HostEvent.UpdateRuntimeFilters xref:runtime-filters.adoc[Runtime filters] are applied at runtime, that is, when loading the embedded ThoughtSpot content. Runtime filters can also be updated after the load time using `HostEvent.UpdateRuntimeFilters`. You can add a UI option or button in your embedding app and assign `HostEvent.UpdateRuntimeFilters` to a button to trigger the event when that button is clicked. @@ -351,9 +356,124 @@ liveboardEmbed.trigger(HostEvent.OpenAddFilterModal); ---- When `AddFilter` is in `disabledActions`, `HostEvent.OpenAddFilterModal` is blocked. +[#spotter-pin-host-events] +=== Spotter conversation pin and unpin + +The following `HostEvent` members are available from ThoughtSpot Cloud 26.10.0.cl and Visual Embed SDK 1.53.0. Both events require `enablePastConversationsSidebar: true` in the embed configuration. + +[cols="1,1,3"] +|=== +| Event | Cluster version | Description + +| `HostEvent.PinSpotterConversation` +| 26.10.0.cl +| Pins a saved Spotter conversation. Accepts `{ conversationId }`. + +| `HostEvent.UnpinSpotterConversation` +| 26.10.0.cl +| Unpins a previously pinned Spotter conversation. Accepts `{ conversationId }`. +|=== + +.Programmatically pin a conversation +[source,javascript] +---- +embed.trigger(HostEvent.PinSpotterConversation, { + conversationId: '{conversation-id}', +}); +---- + +[#liveboard-group-events] +=== #Liveboard group and parameter events# + +The following `HostEvent` members are new in SDK 1.53.0 and support the scoped Liveboard filtering feature introduced in ThoughtSpot Cloud 26.10.0.cl. + +[cols="1,3"] +|=== +| Event | Description + +| `HostEvent.GetGroups` +| Returns filter and parameter group details for the current Liveboard. Response includes `orderedGroupIds`, `numberOfGroups`, and `Groups`. + +| `HostEvent.OpenParameter` +| Opens the parameter panel for a specific parameter on the Liveboard. Accepts an optional `applicability` object to scope the action to a tab or group. +|=== + +Use `HostEvent.GetGroups` to retrieve the group IDs needed before scoping a filter or parameter update. The response payload has the following shape: + +[source,json] +---- +{ + "orderedGroupIds": ["{group-id-1}", "{group-id-2}"], + "numberOfGroups": 2, + "Groups": { + "{group-id-1}": { "name": "Sales Overview" }, + "{group-id-2}": { "name": "Regional Breakdown" } + } +} +---- + +[#applicability-host-events] +=== #Scoped filter and parameter host events# + +The following existing `HostEvent` members gained an optional `applicability` attribute in Visual Embed SDK 1.53.0. This attribute scopes a filter or parameter operation to a specific Liveboard tab or group. + +[cols="1,3"] +|=== +| Event | Change in SDK 1.53.0 + +| `HostEvent.OpenFilter` +| Accepts an optional `applicability` parameter to scope which filter panel opens. + +| `HostEvent.GetFilters` +| Returned Liveboard filter objects now include an optional `applicability` field. + +| `HostEvent.UpdateFilters` +| Accepts an optional `applicability` value per filter to scope the update to a tab or group. + +| `HostEvent.UpdateParameters` +| Accepts an optional `applicability` value per parameter to scope the update to a tab or group. + +| `HostEvent.GetParameters` +| Returned parameter objects now include an optional `applicability` field. +|=== + +The `applicability` object has the following shape: + +[source,json] +---- +{ + "level": "LIVEBOARD" | "TAB" | "GROUP", + "targetId": "{tab-or-group-id}" +} +---- + +`targetId` is optional. Omit it when `level` is `LIVEBOARD`. + +The following example shows the typical workflow: retrieve group IDs using `HostEvent.GetGroups`, then pass a group ID in the `applicability` attribute of `HostEvent.UpdateFilters` to scope the filter update to that group only. + +[source,javascript] +---- +// Step 1: retrieve group details for the Liveboard +const groupsResponse = await liveboardEmbed.trigger(HostEvent.GetGroups); +const targetGroupId = groupsResponse.orderedGroupIds[0]; + +// Step 2: apply a filter scoped to that group +liveboardEmbed.trigger(HostEvent.UpdateFilters, { + filters: [ + { + column: 'Region', + oper: 'IN', + values: ['West'], + applicability: { + level: 'GROUP', + targetId: targetGroupId, + }, + }, + ], +}); +---- == Related resources * See xref:EmbedEvent.adoc[EmbedEvent] and xref:HostEvent.adoc[HostEvent] SDK documentation. * For information about triggering events on React components, see xref:react-components_lesson-04.adoc[Event listeners for React components]. - diff --git a/modules/ROOT/pages/feature-management-api.adoc b/modules/ROOT/pages/feature-management-api.adoc new file mode 100644 index 000000000..ac0b50e40 --- /dev/null +++ b/modules/ROOT/pages/feature-management-api.adoc @@ -0,0 +1,349 @@ += Feature Management +:toc: true +:toclevels: 2 +:page-title: Feature Management API +:page-pageid: feature-management +:page-description: Search feature configurations, assign features to Orgs, and set feature values using the REST API + +The Feature Management API lets cluster and Org admins retrieve feature configurations, assign features to Orgs, and set feature values programmatically. These endpoints replicate the feature management capabilities available in the link:https://docs.thoughtspot.com/cloud/latest/admin-portal-2#_feature_management[new Admin portal UI, window=_blank]. + +All endpoints are under `/api/rest/2.0/configurations/features/` and are available from ThoughtSpot Cloud 26.10.0.cl. + +== Before you begin + +=== Required privileges + +All Feature Management API endpoints require the `ADMINISTRATION` or `ORG_ADMINISTRATION` privilege. The `ORG_ADMINISTRATION` privilege applies only to Org admins. +If xref:roles.adoc[Role-Based Access Control (RBAC)] is enabled on your instance, these privileges are granted through roles. + +=== Prerequisites + +* Feature Management must be enabled on your ThoughtSpot instance. If it is not enabled, the API returns a `404` error. +* To set a feature value at `ORG` scope, the Org must be assigned to that feature. Otherwise, the API returns a `403` error. To assign Orgs to a feature, see <<_update_feature_assignments,Update feature assignments>>. + +=== Feature scope + +Feature configurations exist at two levels: + +Cluster scope:: The cluster-level default, visible to cluster admins. Returns `assigned_orgs` and `is_org_aware` for each feature. +Org scope:: A per-Org value override, visible to Org admins. Returns `element_type`, `element_config`, and `element_value` for each feature. + +=== Feature identifiers + +Each feature can be referenced by its: + +* `feature_name`: a human-readable name, such as `index_columns`. +* `feature_id`: the underlying system identifier, such as `feature.search.columnIndexing`. + +Both forms are accepted in requests to any endpoint that takes a `feature_identifier`. + +=== Feature categories + +Features are grouped into availability categories: + +* `GENERAL_ACCESS`: generally available features. This is the default. +* `EARLY_ACCESS`: features in early access. + +== Search features + +The `POST /api/rest/2.0/configurations/features/search` API endpoint returns the feature configurations available on the ThoughtSpot instance. Requires the `ADMINISTRATION` or `ORG_ADMINISTRATION` privilege. Org admins with the `ORG_ADMINISTRATION` privilege can call this endpoint only with `scope` set to `ORG`. + +A successful request returns `200 OK` and an array of feature groups. Each group contains a `feature_group` name and a `features` array. The fields returned for each feature depend on the `scope` of the request. For more information, see <<_feature_scope,Feature scope>>. + +=== Request parameters + +[cols="1,1,1,3"] +|=== +| Parameter | Type | Required | Description + +| `scope` +| string +| Required +| `CLUSTER` returns the cluster-admin view, including `assigned_orgs` per feature, and requires the `ADMINISTRATION` privilege. `ORG` returns the Org-admin view, including `element_value` per feature. + +| `org_identifier` +| integer +| Conditional +| Numeric ID of the Org to scope the search to. Required when `scope` is `ORG`; ignored when `scope` is `CLUSTER`. + +| `category` +| string +| Optional +| Feature availability category: `GENERAL_ACCESS` (default) or `EARLY_ACCESS`. +|=== + +=== Example request: cluster view + +[source,bash] +---- +curl -X POST \ + --url 'https://{cluster}/api/rest/2.0/configurations/features/search' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {token}' \ + --data-raw '{ + "scope": "CLUSTER", + "category": "GENERAL_ACCESS" +}' +---- + +=== API response: cluster view + +[source,json] +---- +[ + { + "feature_group": "search", + "docs_url": null, + "features": [ + { + "feature_id": "feature.search.columnIndexing", + "feature_name": "index_columns", + "assigned_orgs": [ + { + "org_id": 0, + "org_name": "Primary" + } + ], + "is_org_aware": true, + "feature_value": null, + "docs_url": null + } + ] + } +] +---- + +=== Example request: Org view + +[source,bash] +---- +curl -X POST \ + --url 'https://{cluster}/api/rest/2.0/configurations/features/search' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {token}' \ + --data-raw '{ + "scope": "ORG", + "org_identifier": 1, + "category": "GENERAL_ACCESS" +}' +---- + +=== API response: Org view + +[source,json] +---- +[ + { + "feature_group": "spotter", + "docs_url": null, + "features": [ + { + "feature_id": "feature.spotter.liveboardAssist", + "feature_name": "spotter_on_liveboard", + "assigned_orgs": null, + "is_org_aware": null, + "feature_value": null, + "element_type": "toggle", + "element_config": null, + "element_value": "true", + "docs_url": null + } + ] + }, + { + "feature_group": "downloads", + "docs_url": null, + "features": [ + { + "feature_id": "feature.export.fileInstructions", + "feature_name": "downloaded_file_instructions", + "assigned_orgs": null, + "is_org_aware": null, + "feature_value": null, + "element_type": "input", + "element_config": { + "type": "textarea" + }, + "element_value": "Internal use only", + "docs_url": null + } + ] + } +] +---- + +== Update feature assignments + +The `POST /api/rest/2.0/configurations/features/assignments/update` API endpoint updates the Org assignments for a feature. Available to cluster admins only. Org admins cannot call this endpoint. Requires the `ADMINISTRATION` privilege. + +A successful request returns `200 OK` and a `FeatureAssignmentResponse` object with `feature_id`, `feature_name`, and the updated `assigned_orgs` list. + +=== Request parameters + +[cols="1,1,1,3"] +|=== +| Parameter | Type | Required | Description + +| `feature_identifier` +| string +| Required +| Feature name (`feature_name`) or feature ID (`feature_id`) of the feature to update. + +| `org_identifiers` +| array of integers +| Required +| Numeric IDs of the Orgs to assign. Send an empty array with `operation` set to `REPLACE` to remove all Org assignments for this feature. + +| `operation` +| string +| Optional +| Type of assignment update: `ADD` assigns the given Orgs in addition to existing assignments, `REMOVE` unassigns the given Orgs, or `REPLACE` sets the assignment to exactly the given Orgs. Defaults to `REPLACE`. +|=== + +[CAUTION] +==== +If you omit `operation`, the API uses `REPLACE`. Any Orgs currently assigned to the feature that are not in `org_identifiers` are unassigned. To add Orgs without affecting existing assignments, set `operation` to `ADD`. +==== + +=== Example request: add Org assignments + +[source,bash] +---- +curl -X POST \ + --url 'https://{cluster}/api/rest/2.0/configurations/features/assignments/update' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {token}' \ + --data-raw '{ + "feature_identifier": "index_columns", + "org_identifiers": [1, 2], + "operation": "ADD" +}' +---- + +=== API response: add Org assignments + +[source,json] +---- +{ + "feature_id": "feature.search.columnIndexing", + "feature_name": "index_columns", + "assigned_orgs": [ + { "org_id": 1, "org_name": "Acme" }, + { "org_id": 2, "org_name": "Beta" } + ] +} +---- + +=== Example request: remove all Org assignments + +[source,bash] +---- +curl -X POST \ + --url 'https://{cluster}/api/rest/2.0/configurations/features/assignments/update' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {token}' \ + --data-raw '{ + "feature_identifier": "index_columns", + "org_identifiers": [], + "operation": "REPLACE" +}' +---- + +== Update feature value + +The `POST /api/rest/2.0/configurations/features/values/update` API endpoint sets the value of a feature at the cluster or Org scope. Requires the `ADMINISTRATION` or `ORG_ADMINISTRATION` privilege. The `ORG_ADMINISTRATION` privilege applies only to Org admins. + +A successful request returns `200 OK` and a `FeatureValueResponse` object with `feature_id`, `feature_name`, and the updated `feature_value`. + +[WARNING] +==== +Setting `reset_org_overrides` to `true` at `CLUSTER` scope removes all per-Org value overrides for this feature. All Orgs then inherit the new cluster-level value. This operation cannot be undone through the API. +==== + +=== Request parameters + +[cols="1,1,1,3"] +|=== +| Parameter | Type | Required | Description + +| `scope` +| string +| Required +| Scope at which to set the value: `CLUSTER` or `ORG`. + +| `org_identifier` +| integer +| Conditional +| Numeric ID of the Org for which to set the value. Required when `scope` is `ORG`. Ignored when `scope` is `CLUSTER`. + +| `feature_identifier` +| string +| Required +| Feature name (`feature_name`) or feature ID (`feature_id`) of the feature to update. + +| `feature_value` +| string +| Required +| New value to assign to the feature, as a string. For toggle features, use `"true"` or `"false"`. + +| `reset_org_overrides` +| boolean +| Conditional +| Applicable only when `scope` is `CLUSTER`. When `true`, any existing per-Org value overrides for this feature are also removed so that all Orgs inherit the new cluster-level value. When `false`, existing per-Org value overrides are retained. Required when `scope` is `CLUSTER` for an Org-aware feature. Must be omitted when `scope` is `ORG`; passing it at `ORG` scope returns a `400` error. +|=== + +=== Example request: set an Org-level override + +[source,bash] +---- +curl -X POST \ + --url 'https://{cluster}/api/rest/2.0/configurations/features/values/update' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {token}' \ + --data-raw '{ + "scope": "ORG", + "org_identifier": 1, + "feature_identifier": "index_columns", + "feature_value": "true" +}' +---- + +=== Example request: set cluster value and reset all Org overrides + +[source,bash] +---- +curl -X POST \ + --url 'https://{cluster}/api/rest/2.0/configurations/features/values/update' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {token}' \ + --data-raw '{ + "scope": "CLUSTER", + "feature_identifier": "index_columns", + "feature_value": "true", + "reset_org_overrides": true +}' +---- + +=== API response: set cluster value and reset all Org overrides + +[source,json] +---- +{ + "feature_id": "feature.search.columnIndexing", + "feature_name": "index_columns", + "feature_value": "true" +} +---- + +== Related resources + +* xref:rest-api-v2-reference.adoc[REST API v2 reference] +* xref:org-manage-api.adoc[Org administration] +* xref:privileges-and-roles.adoc[Privileges and roles] +* xref:roles.adoc[Role-based access control] diff --git a/modules/ROOT/pages/filters_overview.adoc b/modules/ROOT/pages/filters_overview.adoc index fe4672d0d..f618a328f 100644 --- a/modules/ROOT/pages/filters_overview.adoc +++ b/modules/ROOT/pages/filters_overview.adoc @@ -36,7 +36,7 @@ xref:runtime-filters.adoc#_maximum_filter_count[Runtime filter limit] for more i ==== 4. link:https://docs.thoughtspot.com/cloud/latest/liveboard-filters[Liveboard filters, window=_blank] + -Liveboard filters apply to all visualizations on the Liveboard and are visible as UI components at the top of a Liveboard page. When a filter is clicked, a modal with filter options appropriate for the data type is displayed. + +Liveboard filters are visible as UI components at the top of a Liveboard page. #By default, a Liveboard filter applies to all visualizations on the Liveboard. Starting with ThoughtSpot Cloud 26.10.0.cl, a filter can also be scoped to a specific tab or group. For more information, see <>.# When a filter is clicked, a modal with filter options appropriate for the data type is displayed. + Liveboard users can add or modify filters as needed. If you are embedding a Liveboard that includes preset filters, you can programmatically update, reset, or remove filters using `HostEvent.UpdateFilters`. 5. link:https://docs.thoughtspot.com/cloud/latest/liveboard-filters-cross[Liveboard cross filters, window=_blank] + @@ -222,6 +222,37 @@ liveboardEmbed.trigger(HostEvent.UpdateFilters, { }); ---- +[#scoped-filter-updates] +=== #Scoped filter and parameter updates# +#Starting with ThoughtSpot Cloud 26.10.0.cl release, Liveboard filters and parameters can be scoped at three levels:# + +* #*Liveboard*: applies to all visualizations on the Liveboard.# +* #*Tab*: applies only to visualizations on a specific tab.# +* #*Group*: applies only to visualizations in a specific group on a tab.# + +#To enable group-level scoping in an embedded Liveboard, set `isScopedLiveboardFilteringEnabled` to `true` in the embed configuration. For more information, see xref:embed-pinboard.adoc#scoped-liveboard-filtering[Scoped Liveboard filtering].# + +#To scope an update to a tab or group, pass the `applicability` attribute with `HostEvent.UpdateFilters` or `HostEvent.UpdateParameters`. Set `level` to `TAB` or `GROUP`, and set `targetId` to the ID of the tab or group. To get the group IDs on a Liveboard, use `HostEvent.GetGroups`.# + +[source,JavaScript] +---- +const groups = await liveboardEmbed.trigger(HostEvent.GetGroups); + +liveboardEmbed.trigger(HostEvent.UpdateFilters, { + filter: { + column: "Region", + oper: "IN", + values: ["West"], + applicability: { + level: "GROUP", + targetId: groups.orderedGroupIds[0], + }, + }, +}); +---- + +#For more information, see xref:events-hostEvents.adoc#applicability-host-events[Scoped filter and parameter host events].# + === GetFilters and GetParameters events If you want to build your own filter UI within the embedding app, you can find out details of the Liveboard and runtime filters that are defined using `HostEvent.GetFilters`. @@ -238,6 +269,8 @@ Each filter object in the `HostEvent.GetFilters` response includes two additiona * `applicable_viz`: indicates whether the filter applies to `ALL` visualizations or only `SPECIFIC` ones (with a `viz_ids` array). * `linking`: indicates whether the filter is linked to other filters, and which columns it is linked to (`is_linked`, `linked_columns`). +#Starting with Visual Embed SDK 1.53.0, the filter objects returned by `HostEvent.GetFilters` and the parameter objects returned by `HostEvent.GetParameters` also include an optional `applicability` field that indicates whether the filter or parameter is scoped to the Liveboard, a tab, or a group.# + For more information, see xref:events-hostEvents.adoc#_hostevent_getfilters[HostEvent.GetFilters] and xref:HostEvent.adoc#_getfilters[HostEvent reference documentation]. @@ -261,6 +294,8 @@ You can also listen for the user's interactions with the filters using the link: There is an equivalent EmbedEvent for Parameters called link:https://developers.thoughtspot.com/docs/Enumeration_EmbedEvent#_parameterchanged[EmbedEvent.ParameterChanged]. +#Starting with Visual Embed SDK 1.53.0, the `EmbedEvent.FilterChanged` and `EmbedEvent.ParameterChanged` payloads include an optional `applicability` object that describes the scope of the changed filter or parameter. For more information, see xref:event-embedEvents.adoc#applicability-scope[Scoped filter and parameter events].# + === UpdateCrossFilter event You can programmatically trigger an action to update a cross filter using link:https://developers.thoughtspot.com/docs/Enumeration_HostEvent#_updatecrossfilter[HostEvent.UpdateCrossFilter]: diff --git a/modules/ROOT/pages/rest-apiv2-changelog.adoc b/modules/ROOT/pages/rest-apiv2-changelog.adoc index 7e201fe2f..ddb60fd15 100644 --- a/modules/ROOT/pages/rest-apiv2-changelog.adoc +++ b/modules/ROOT/pages/rest-apiv2-changelog.adoc @@ -8,6 +8,62 @@ This changelog lists the features and enhancements introduced in REST API v2.0. For information about new features and enhancements available for embedded analytics, see xref:whats-new.adoc[What's New]. +== Version 26.10.0.cl, October 2026 + +=== Spotter Analyst API + +Four new endpoints are available for managing Spotter Analysts programmatically. All endpoints are under `/api/rest/2.0/ai/agent/analysts/`. + +[cols="2,4"] +|=== +| Endpoint | Description + +| `POST /api/rest/2.0/ai/agent/analysts/create` +| Creates a Spotter Analyst with a name, description, data sources, and optional instructions, MCP connectors, and starter prompts. Requires `ADMINISTRATION`, `CAN_MANAGE_SPOTTER`, or `CAN_USE_SPOTTER` privilege, plus view access to all referenced sources. Returns the created `Analyst` object including the server-assigned `id`. + +| `POST /api/rest/2.0/ai/agent/analysts/search` +| Returns Analysts visible to the caller. Operates in fetch mode (single Analyst by `analyst_identifier`) or list mode (paginated, ordered by most recently accessed). Supports filtering by ownership type: `ALL`, `CREATED_BY_ME`, or `SHARED_TO_ME`. Requires `ADMINISTRATION`, `CAN_MANAGE_SPOTTER`, or `CAN_USE_SPOTTER`. + +| `POST /api/rest/2.0/ai/agent/analysts/{analyst_identifier}/update` +| Full-replace update of a Spotter Analyst. Omitted optional fields are cleared. Requires ownership or `ADMINISTRATION`/`CAN_MANAGE_SPOTTER` privilege. When new sources are added, they are automatically shared with existing users of the Analyst. + +| `POST /api/rest/2.0/ai/agent/analysts/{analyst_identifier}/delete` +| Permanently deletes a Spotter Analyst. This operation is irreversible. Requires ownership or `ADMINISTRATION`/`CAN_MANAGE_SPOTTER` privilege. +|=== + +For full parameter details, request and response schemas, and code examples, see xref:spotter-analyst-api.adoc[Spotter Analyst API]. + +=== Feature Management API +This release introduces the following new REST API v2.0 endpoints for programmatic feature management. All endpoints are under `/api/rest/2.0/configurations/features/`. + +[cols="2,4"] +|=== +| Endpoint | Description + +| `POST /api/rest/2.0/configurations/features/search` +| Returns feature configurations grouped by feature group. + +| `POST /api/rest/2.0/configurations/features/assignments/update` +| Updates Org assignments for a feature using `ADD`, `REMOVE`, or `REPLACE` operations. + +| `POST /api/rest/2.0/configurations/features/values/update` +| Sets feature value at `CLUSTER` or `ORG` scope. +|=== + +For full parameter details, request and response schemas, and code examples, see xref:feature-management-api.adoc[Feature Management API]. + +=== Update Conversation — `is_pinned` field added + +The `POST /api/rest/2.0/ai/agent/conversations/{conversation_identifier}/update` endpoint now accepts an `is_pinned` boolean field. + +* Set `is_pinned: true` to pin the conversation to the top of the conversation list. +* Set `is_pinned: false` to unpin a previously pinned conversation. +* The operation is idempotent: pinning an already-pinned conversation or unpinning an already-unpinned one succeeds with no side effects. +* Only conversations created with `enable_save_chat: true` can be pinned. +* Both `title` and `is_pinned` can be updated in a single request. + +NOTE: The `title` field has been available since version 26.7.0.cl. The `is_pinned` field is new in version 26.10.0.cl. + == Version 26.9.0.cl, September 2026 === Answer Export API diff --git a/modules/ROOT/pages/spotter-analyst-api.adoc b/modules/ROOT/pages/spotter-analyst-api.adoc new file mode 100644 index 000000000..5375e876f --- /dev/null +++ b/modules/ROOT/pages/spotter-analyst-api.adoc @@ -0,0 +1,389 @@ += Spotter Analyst API +:toc: true +:toclevels: 2 + +:page-title: Spotter Analyst API +:page-pageid: spotter-analyst-api +:page-description: Create, search, update, and delete Spotter Analysts using the REST API + +// SOURCE: SCAL-317811; create-analyst.md, search-analyst.md, update-analyst.md, delete-analyst.md + +ThoughtSpot Spotter Analysts are governed AI agents, each configured with a name, description, one or more data sources, and optional instructions, MCP connectors, and starter prompts. Users converse with an Analyst directly in the Spotter interface. + +The Spotter Analyst REST API lets you create, search, update, and delete Analysts programmatically. +All endpoints are under `/api/rest/2.0/ai/agent/analysts/` and are available from ThoughtSpot Cloud 26.10.0.cl. + +== Prerequisites + +* Spotter must be enabled on your ThoughtSpot instance. Contact ThoughtSpot Support to enable it. +* All requests require a Bearer token. Use a token scoped to the Org in which the Analyst exists or should be created. +* Privilege requirements vary by operation. See each endpoint section for details. + +== Analyst object + +Each Analyst has the following fields: + +[cols="1,1,3"] +|=== +| Field | Type | Description + +| `id` +| string +| Server-assigned unique identifier. + +| `name` +| string +| Display name of the Analyst. + +| `description` +| string +| Description of the Analyst. Maximum 200 characters. + +| `instructions` +| string +| Optional natural-language behavior guidelines for the agent. + +| `sources` +| array +| Data sources the Analyst can query. Each source includes an `id`, `type`, and display `name`. Supported types: `MODEL`, `ANSWER`, `LIVEBOARD`, `CONVERSATION`. + +| `mcp_connectors` +| array +| Linked MCP connectors. Each connector includes `id`, `name`, and `icon_url`. + +| `starter_prompts` +| array +| Up to 4 suggested prompts shown on the Analyst landing page. Each entry includes `label`, `text`, `order`, and `is_ai_generated`. + +| `icon_id` +| string +| Analyst icon identifier. Analysts created via the API use the default icon until one is set in the UI. + +| `updated_time_in_millis` +| integer +| Epoch timestamp in milliseconds of the last update. + +| `last_accessed_time_in_millis` +| integer +| Epoch timestamp in milliseconds of the last access. + +| `created_by` +| object +| User who created the Analyst. Includes `id`, `name`, and `display_name`. + +| `updated_by` +| object +| User who last updated the Analyst. Includes `id`, `name`, and `display_name`. +|=== + +== Create Analyst + +`POST /api/rest/2.0/ai/agent/analysts/create` + +Creates a Spotter Analyst. Analysts created via the API use the default icon until one is set in the ThoughtSpot UI. + +=== Privileges required + +At least one of the following: `ADMINISTRATION`, `CAN_MANAGE_SPOTTER`, or `CAN_USE_SPOTTER`. The caller must also have view access to every data source listed in `sources`. + +=== Request parameters + +[cols="1,1,1,3"] +|=== +| Parameter | Type | Required | Description + +| `name` +| string +| Required +| Display name of the Analyst. + +| `description` +| string +| Required +| Description of the Analyst. Maximum 200 characters. + +| `sources` +| array +| Required +| At least one data source. Each entry requires an `identifier` and a `type` (`MODEL`, `ANSWER`, `LIVEBOARD`, or `CONVERSATION`). The `name` field is optional. The caller must have view access to every referenced source. + +| `instructions` +| string +| Optional +| Natural-language instructions that guide the agent's behavior. Instructions that conflict with system guardrails are rejected with a `409` error. + +| `mcp_connector_identifiers` +| array +| Optional +| Identifiers of MCP connectors to link to the Analyst. + +| `starter_prompts` +| array +| Optional +| Up to 4 plain-text prompts, each between 10 and 250 characters. Display order follows list position. +|=== + +=== Response + +Returns `200 OK` and the created `Analyst` object, including the server-assigned `id`. + +=== Example + +[source,bash] +---- +curl -X POST \ + --url 'https://{cluster}/api/rest/2.0/ai/agent/analysts/create' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {token}' \ + --data-raw '{ + "name": "Revenue Analyst", + "description": "Answers revenue questions using the Sales data model.", + "sources": [ + { + "identifier": "{model-guid}", + "type": "MODEL" + } + ], + "instructions": "Focus on year-over-year comparisons. Do not surface raw transaction data.", + "starter_prompts": [ + "What was total revenue last quarter?", + "Compare revenue by region for the past 12 months." + ] +}' +---- + +=== Error responses + +[cols="1,3"] +|=== +| HTTP status code | Description + +| 400 | Malformed request. +| 401 | Bearer token is missing, expired, or invalid. +| 403 | Insufficient privileges, or the caller does not have view access to a referenced data source. +| 409 | The `instructions` value conflicts with system guardrails. +| 422 | Validation failure: a required field is missing, `sources` is empty, the starter prompt count exceeds 4, or a field-length limit is violated. +| 429 | Rate limit exceeded. +| 500 | Unexpected server error. +|=== + +== Search Analysts + +`POST /api/rest/2.0/ai/agent/analysts/search` + +Returns Analysts visible to the caller. This endpoint operates in two modes: + +Fetch mode:: Provide `analyst_identifier` to retrieve a single Analyst. All other filters are ignored and `total_size` is `1`. +List mode:: Omit `analyst_identifier` to get a paginated list of Analysts, ordered by most recently accessed. + +=== Privileges required + +At least one of the following: `ADMINISTRATION`, `CAN_MANAGE_SPOTTER`, or `CAN_USE_SPOTTER`. + +=== Request parameters + +[cols="1,1,1,3"] +|=== +| Parameter | Type | Required | Description + +| `analyst_identifier` +| string +| Optional +| When provided, returns exactly this Analyst. All other filters are ignored. + +| `record_size` +| integer +| Optional +| Number of records per page. Default: `50`. Range: 1 to 500. + +| `record_offset` +| integer +| Optional +| Zero-based index of the first record. Default: `0`. Maximum: `10000`. + +| `query` +| string +| Optional +| Case-insensitive substring match on Analyst name. + +| `type` +| string +| Optional +| Ownership filter. Accepted values: `ALL` (default, returns Analysts created by or shared with the caller), `CREATED_BY_ME`, or `SHARED_TO_ME`. +|=== + +=== Response + +Returns `200 OK` and an `AnalystSearchResponse` object with: + +* `analysts`: the current page of matching `Analyst` objects. +* `total_size`: total count of matching Analysts before pagination. + +=== Example: list all Analysts + +[source,bash] +---- +curl -X POST \ + --url 'https://{cluster}/api/rest/2.0/ai/agent/analysts/search' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {token}' \ + --data-raw '{ + "record_size": 50, + "record_offset": 0, + "type": "ALL" +}' +---- + +=== Example: fetch a single Analyst + +[source,bash] +---- +curl -X POST \ + --url 'https://{cluster}/api/rest/2.0/ai/agent/analysts/search' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {token}' \ + --data-raw '{ + "analyst_identifier": "{analyst-guid}" +}' +---- + +=== Error responses + +[cols="1,3"] +|=== +| HTTP status code | Description + +| 403 | Missing privileges, or (fetch mode) the caller does not have access to the requested Analyst. +| 404 | (Fetch mode) No Analyst with the given identifier exists in the caller's Org. +| 422 | `record_size` or `record_offset` is out of the permitted range. +|=== + +== Update Analyst + +`POST /api/rest/2.0/ai/agent/analysts/{analyst_identifier}/update` + +Updates a Spotter Analyst. The update is a full replace: the Analyst is rewritten from the request body. Any optional field omitted from the request is cleared. Include all fields you want to retain. + +When new sources are added, they are automatically shared with users the Analyst was previously shared with. Those users retain access to a working Analyst. + +=== Privileges required + +The caller must be the owner of the Analyst, or hold `ADMINISTRATION` or `CAN_MANAGE_SPOTTER` privileges. Users the Analyst is shared with can use it but cannot edit it. + +=== Path parameter + +`analyst_identifier`: unique ID of the Analyst to update, as returned by the Create Analyst or Search Analysts endpoint. + +=== Request parameters + +The request body uses the same shape as Create Analyst: `name`, `description`, `sources`, `instructions`, `mcp_connector_identifiers`, and `starter_prompts`. + +=== Response + +Returns `200 OK` and the updated `Analyst` object, including the refreshed `updated_time_in_millis` and `updated_by` fields. + +=== Example + +[source,bash] +---- +curl -X POST \ + --url 'https://{cluster}/api/rest/2.0/ai/agent/analysts/{analyst_identifier}/update' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {token}' \ + --data-raw '{ + "name": "Revenue Analyst v2", + "description": "Updated to include APAC data model.", + "sources": [ + { + "identifier": "{model-guid}", + "type": "MODEL" + }, + { + "identifier": "{apac-model-guid}", + "type": "MODEL" + } + ], + "starter_prompts": [ + "What was total revenue last quarter?", + "Compare revenue by region for the past 12 months.", + "Show top 10 products by APAC revenue." + ] +}' +---- + +[NOTE] +==== +The update is a full replace. Omitting `instructions`, `mcp_connector_identifiers`, or `starter_prompts` clears those fields on the Analyst. Include every field you want to keep. +==== + +=== Error responses + +[cols="1,3"] +|=== +| HTTP status code | Description + +| 400 | Malformed `analyst_identifier`. +| 401 | Bearer token is missing, expired, or invalid. +| 403 | The caller is not the Analyst owner and does not hold admin or Spotter-management privileges. +| 404 | No Analyst with the given identifier exists in the caller's Org. +| 409 | The `instructions` value conflicts with system guardrails. +| 422 | Validation failure: a required field is missing, `sources` is empty, the starter prompt count exceeds 4, or a field-length limit is violated. +| 429 | Rate limit exceeded. +| 500 | Unexpected server error. +|=== + +== Delete Analyst + +`POST /api/rest/2.0/ai/agent/analysts/{analyst_identifier}/delete` + +Permanently deletes a Spotter Analyst. This operation is irreversible. Deleted Analysts cannot be recovered. + +=== Privileges required + +The caller must be the owner of the Analyst, or hold `ADMINISTRATION` or `CAN_MANAGE_SPOTTER` privileges. Users the Analyst is shared with cannot delete it. + +=== Path parameter + +`analyst_identifier`: unique ID of the Analyst to delete, as returned by the Create Analyst or Search Analysts endpoint. + +=== Request body + +None. + +=== Response + +Returns `200 OK` and an `AnalystDeleteResponse` object containing the `id` of the deleted Analyst. + +=== Example + +[source,bash] +---- +curl -X POST \ + --url 'https://{cluster}/api/rest/2.0/ai/agent/analysts/{analyst_identifier}/delete' \ + -H 'Accept: application/json' \ + -H 'Authorization: Bearer {token}' +---- + +=== Error responses + +[cols="1,3"] +|=== +| HTTP status code | Description + +| 400 | Malformed `analyst_identifier`. +| 401 | Bearer token is missing, expired, or invalid. +| 403 | The caller is not the Analyst owner and does not hold admin or Spotter-management privileges. +| 404 | No Analyst with the given identifier exists in the caller's Org. +| 429 | Rate limit exceeded. +| 500 | Unexpected server error. +|=== + +== Related resources + +* xref:embed-spotter-analyst.adoc[Embed Spotter Analyst] +* xref:rest-api-v2-reference.adoc[REST API v2 reference] +* xref:privileges-and-roles.adoc[Privileges and roles] diff --git a/modules/ROOT/pages/whats-new.adoc b/modules/ROOT/pages/whats-new.adoc index d9fc73c1f..1fb18e386 100644 --- a/modules/ROOT/pages/whats-new.adoc +++ b/modules/ROOT/pages/whats-new.adoc @@ -1,7 +1,6 @@ = What's new :toc: true :toclevels: 1 - :page-title: What's new :page-pageid: whats-new :page-description: New features and enhancements @@ -22,6 +21,83 @@ This page lists new features, enhancements, and deprecated functionality introdu // *Status:* Current / Supported / Deprecated // *Affects:* Developers, Administrators, End Users // ============================================================ + + +== October 2026 + +**Release version**: ThoughtSpot Cloud 26.10.0.cl + +*Upgrade notes*: No breaking changes in this release. + +*Recommended SDK versions*: Visual Embed SDK v1.53.0 or later + +[.cl-table, cols="2,4", frame=none, grid=none] +|=== +a| +[.cl-label] +*Version 26.10.0.cl* + +a| + +[discrete] +==== Spotter Analyst API + +Spotter Analysts are governed AI agents you can create, configure, and manage via the REST API. Four new endpoints are available under `/api/rest/2.0/ai/agent/analysts/` to create, search, update, and delete Analysts programmatically. Each Analyst is configured with a name, description, one or more data sources, and optional instructions, MCP connectors, and starter prompts. For more information, see xref:spotter-analyst-api.adoc[Spotter Analyst API]. + +--- + +[discrete] +==== Embed Spotter Analyst + +You can now embed a single, pinned Spotter Analyst in your application using the Visual Embed SDK. The `spotterAnalystConfig.analystId` property in `SpotterEmbed` locks the embed to one governed Analyst experience. Combined with the updated `hiddenActions` list, you can prevent users from switching to other Analysts or to the default Spotter. For more information, see xref:embed-spotter-analyst.adoc[Embed Spotter Analyst]. + +--- + +[discrete] +==== Spotter conversation pinning + +Users can now pin Spotter conversations so they appear at the top of the conversation list for quick access. Pinning is disabled by default in embedded deployments and must be explicitly enabled using `spotterChatPinConfig` in `spotterSidebarConfig`. The SDK emits `EmbedEvent.SpotterConversationPinned` and `EmbedEvent.SpotterConversationUnpinned` when pin state changes. Use `HostEvent.PinSpotterConversation` and `HostEvent.UnpinSpotterConversation` to trigger pin state from the host application. For REST API access, the `is_pinned` field is now available on the Update Conversation endpoint. For more information, see xref:embed-spotter-analyst.adoc[Embed Spotter Analyst] and xref:rest-apiv2-changelog.adoc[REST API v2.0 changelog]. + +--- + +[discrete] +==== Feature management through APIs + +ThoughtSpot now supports programmatic feature management with new REST APIv2 endpoints available under `/api/rest/2.0/configurations/features/`. Cluster and Org admins can search feature configurations, assign features to Orgs, and set feature values without using the link:https://docs.thoughtspot.com/cloud/latest/admin-portal-2#_feature_management[new Admin portal, window=_blank]. For more information, see xref:feature-management-api.adoc[Feature Management]. + +--- + +[discrete] +==== Liveboard enhancements +* *Contextual filtering in Liveboards* [earlyAccess eaBackground]#Early Access# ++ +Liveboard filters now have a three-tier filter hierarchy : Liveboard level, tab level, and group level. You can enable this feature in embedded Liveboards using the `isScopedLiveboardFilteringEnabled` parameter in the SDK. For more information, see xref:embed-pinboard.adoc#contextual-liveboard-filtering[Embed a Liveboard]. + +* *Host Events* ++ +** The `HostEvent.GetGroups` event returns group details for the Liveboard, and the `applicability` attribute on `HostEvent.UpdateFilters` and `HostEvent.UpdateParameters` scopes filter updates to a specific tab or group. For more information, see xref:embed-events.adoc[Events and app interactions]. +** The `HostEvent.OpenParameter` event opens the parameter panel for a specific parameter on the Liveboard. Accepts an optional `applicability` object to scope the action to a tab or group. + +* *Centralized filter modal* in Liveboards is now generally available and enabled by default on ThoughtSpot embedded instances. + +* *Column security rules on Liveboards* ++ +Liveboards that were previously blocked by Column Security Rules (CSR) now open and work normally, with column security fully enforced, including in embedded Liveboards. Filter values from inaccessible columns are masked instead of blocking the Liveboard, and scheduled Liveboard deliveries apply CSR separately for each recipient. For more information, see xref:data-security.adoc#csr-liveboards[Column security rules on Liveboards]. + + +--- + +[discrete] +==== Visual Embed SDK +For information about the new features and enhancements introduced in Visual Embed SDK version 1.53.0, see xref:api-changelog.adoc[Visual Embed SDK changelog]. + +--- + +[discrete] +==== REST API +For information about REST API v2.0 enhancements in this release, see xref:rest-apiv2-changelog.adoc[REST API v2.0 changelog]. + +|=== + + == September 2026 **Release version**: ThoughtSpot Cloud 26.9.0.cl + @@ -866,4 +942,4 @@ For information about the new features and enhancements introduced in Visual Emb ==== REST API For information about REST API v2 enhancements, see xref:rest-apiv2-changelog.adoc[REST API v2.0 changelog]. -|=== +|=== \ No newline at end of file