diff --git a/modules/ROOT/pages/api-changelog.adoc b/modules/ROOT/pages/api-changelog.adoc index 08d32656a..dc9dd2bec 100644 --- a/modules/ROOT/pages/api-changelog.adoc +++ b/modules/ROOT/pages/api-changelog.adoc @@ -8,10 +8,92 @@ 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.54.0, November 2026 + +[width="100%", cols="1,4"] +|==== +|[tag greenBackground]#NEW# +a| +[discrete] +===== Spotter file upload in SpotterViz +The following `SpotterVizConfig` options control file upload in the SpotterViz chat input: + +* `fileUploadEnabled` + +Turns file upload on or off. The default value is `true`. +* `fileUploadFileTypes` + +Restricts uploads to a subset of the supported file types, for example, `['csv', 'pdf']`. + +For more information, see xref:embed-spotterViz.adoc[SpotterViz in embedded Liveboards]. + +|[tag greenBackground]#NEW# +a| +[discrete] +===== Separate Edit controls for Liveboards and visualizations +The SDK now lets you control the *Edit* action on Liveboards and visualizations independently: + +* `EmbedEvent.EditLiveboard` and `EmbedEvent.EditVisualization` + +Fire when a user selects *Edit* on a Liveboard or on a visualization. These events fire alongside `EmbedEvent.Edit`, so existing listeners continue to work. +* `HostEvent.EditLiveboard` and `HostEvent.EditVisualization` + +Trigger Edit on one surface only. `HostEvent.EditVisualization` requires a `vizId`. `HostEvent.Edit` is unchanged. +* `Action.EditLiveboard` and `Action.EditVisualization` + +Hide or turn off Edit on one surface only. `Action.Edit` continues to control both. + +For more information, see xref:EmbedEvent.adoc[EmbedEvent], xref:HostEvent.adoc[HostEvent], and xref:Action.adoc[Action]. + +|[tag greenBackground]#NEW# +a| +[discrete] +===== Chart settings in answer pages + +Chart edit panel:: +see xref:SearchViewConfig.adoc#_hideanswereditpanel[hideAnswerEditPanel]: Hides the chart edit panel in an answer page when set to `true`. + +Action IDs for chart settings:: +The following action IDs are available to hide or turn off individual menu items in the chart settings panel in the answer page: + +* `Action.ChartTypeSettings` for the *Chart Type* menu item +* `Action.LayoutSettings` for the *Layout* menu item +* `Action.ColumnSettings` for the *Column* menu item +* `Action.AxisSettings` for the *Axis* menu item +* `Action.DataLabelSettings` for the *Data Label* menu item +* `Action.TooltipSettings` for the *Tooltip* menu item +* `Action.LegendSettings` for the *Legend* menu item +* `Action.DisplaySettings` for the *Display* menu item +* `Action.QuerySettings` for the *Query Details* menu item +* `Action.CustomSettings` for the *Custom Action* menu item +* `Action.MuzeAiSettings` for the *Muze AI* menu item +* `Action.RAnalysisSettings` for the *R Analysis* menu item + +For more information, see xref:Action.adoc[Action]. + +|[tag greenBackground]#NEW# +a| +[discrete] +===== Liveboard load-time overrides +Use the new `liveboardOverride` option in `LiveboardEmbed` to apply filters and Parameters when the Liveboard loads. + +In an embedded Liveboard, this option is the only way to set filters and Parameters at load time, because the `filter` and `parameter` URL query parameters are ignored. Clauses without a query token are dropped. + +The SDK also exports the following types: `LiveboardOverride`, `LiveboardDataSourceOverride`, `LiveboardFilterQuery`, and `LiveboardParameterQuery`. + +For more information, see xref:LiveboardViewConfig.adoc[LiveboardViewConfig]. + +|==== + == Version 1.53.0, October 2026 [width="100%", cols="1,4"] |==== +|[tag greenBackground]#NEW# +a| +[discrete] +===== New Spotter experience +You can now enable the new Spotter experience, including Spotter on Liveboards, in your embedded application. Set `spotterExperienceVersion` to `SpotterExperienceVersion.SPOTTER_2026_11` in your `SpotterEmbed`, `LiveboardEmbed`, or `AppEmbed` configuration. The `SpotterExperienceVersion` enum is exported from the SDK. The new experience is opt-in; existing Spotter embeds remain unchanged unless explicitly opted in. The property requires ThoughtSpot Cloud 26.11.0.cl or later. + +If you set `spotterExperienceVersion` to a value that the SDK doesn't recognize, the embed falls back to the standard Spotter experience without an error. + +For more information, see xref:embed-new-spotter.adoc[Embed the new Spotter experience]. + |[tag greenBackground]#NEW# a| [discrete] @@ -33,6 +115,17 @@ You can now customize the starter prompt pills in the embedded Spotter interface |[tag greenBackground]#NEW# a| [discrete] +===== Spotter usage limits +You can now show and customize Spotter usage limits in `SpotterEmbed` and `AppEmbed`: + +* `spotterUsageLimitConfig` + +Enables usage limits and controls the usage counter (`usageCounterDisplayMode`), the warning and limit banners, and the *Upgrade* button. +* `EmbedEvent.SpotterUsageLimitUpgrade` + +Fires when a user clicks *Upgrade*. +* `HostEvent.SpotterRefreshUsageLimit` + +Refreshes the usage data in the embed. + +For more information, see xref:spotter-usage-limits.adoc[Manage Spotter usage limits]. ===== Spotter sidebar controls `enableConnectorMarketplace`:: diff --git a/modules/ROOT/pages/common/nav-embedding.adoc b/modules/ROOT/pages/common/nav-embedding.adoc index 8b6bac6c7..224e2beb0 100644 --- a/modules/ROOT/pages/common/nav-embedding.adoc +++ b/modules/ROOT/pages/common/nav-embedding.adoc @@ -11,11 +11,13 @@ Embed ThoughtSpot in a web app * link:{{navprefix}}/getting-started[Get started] * link:{{navprefix}}/embed-ai-search-analytics[Embed Spotter AI Analytics] ** link:{{navprefix}}/embed-spotter[Embed full Spotter experience] +** link:{{navprefix}}/embed-new-spotter[Embed the new Spotter experience] ** link:{{navprefix}}/embed-spotter-analyst[Embed a Spotter Analyst] ** link:{{navprefix}}/customize-spotter-embed[Customize Spotter interface] ** link:{{navprefix}}/customize-spotter-chat-experience[Customize chat experience] ** link:{{navprefix}}/customize-spotter-sidebar[Customize sidebar panel] ** link:{{navprefix}}/customize-spotter-sharing[Customize conversation sharing experience] +** link:{{navprefix}}/spotter-usage-limits[Manage Spotter usage limits] ** link:{{navprefix}}/customize-spotter-analysts[Configure Spotter Analysts] ** link:{{navprefix}}/embed-spotter-agent[Embed Spotter without ThoughtSpot UI] * Embed charts and Liveboards diff --git a/modules/ROOT/pages/common/nav-in-product-help.adoc b/modules/ROOT/pages/common/nav-in-product-help.adoc index be7f7993a..8509e5f2b 100644 --- a/modules/ROOT/pages/common/nav-in-product-help.adoc +++ b/modules/ROOT/pages/common/nav-in-product-help.adoc @@ -30,11 +30,13 @@ Embed ThoughtSpot in a web app * link:{{navprefix}}/tsembed[Quickstart guide] * link:{{navprefix}}/embed-ai-search-analytics[Embed Spotter AI Analytics] ** link:{{navprefix}}/embed-spotter[Embed full Spotter experience] +** link:{{navprefix}}/embed-new-spotter[Embed the new Spotter experience] ** link:{{navprefix}}/embed-spotter-analyst[Embed a Spotter Analyst] ** link:{{navprefix}}/customize-spotter-embed[Customize Spotter interface] ** link:{{navprefix}}/customize-spotter-chat-experience[Customize chat experience] ** link:{{navprefix}}/customize-spotter-sidebar[Customize sidebar panel] ** link:{{navprefix}}/customize-spotter-sharing[Customize conversation sharing experience] +** link:{{navprefix}}/spotter-usage-limits[Manage Spotter usage limits] ** link:{{navprefix}}/customize-spotter-analysts[Configure Spotter Analysts] ** link:{{navprefix}}/embed-spotter-agent[Embed Spotter AI without ThoughtSpot UI] * link:{{navprefix}}/embed-liveboard[Embed live analytics] @@ -186,6 +188,8 @@ Integration with external tools Build and deploy ** link:{{navprefix}}/thoughtspot-objects[ThoughtSpot objects] +*** link:{{navprefix}}/object-id[Object ID] +*** link:{{navprefix}}/object-id-urls[Object ID in URLs] ** link:{{navprefix}}/timezone-aware-filtering[Timezone-aware keywords and filters] ** link:{{navprefix}}/variables[Variables] ** link:{{navprefix}}/parameterize-metadata[Parameterize metadata] @@ -226,9 +230,11 @@ REST APIs *** link:{{navprefix}}/spotter-agent-conversation-mgmt-apis[APIs for managing saved conversations] *** link:{{navprefix}}/spotter-analyst-api[Spotter Analyst APIs] *** link:{{navprefix}}/spotter-memory-migration[Spotter memory migration API] +*** link:{{navprefix}}/spotter-usage-data-api[Spotter usage data APIs] *** link:{{navprefix}}/spotter-apis-classic[AI APIs (Spotter Classic) ^BETA^] *** link:{{navprefix}}/spotter-nl-instructions[Data model instructions APIs ^BETA^] ** link:{{navprefix}}/style-customization-apis[Style customization APIs] +** link:{{navprefix}}/link-customization-api[Link customization APIs] ** link:{{navprefix}}/audit-logs[Audit logs] ** link:{{navprefix}}/tml[TML] *** link:{{navprefix}}/tml-import[Import TML] @@ -237,6 +243,7 @@ REST APIs ** link:{{navprefix}}/connections[Connections] ** link:{{navprefix}}/connection-config[Connection configuration] ** link:{{navprefix}}/runtime-sort[Runtime sorting] +** link:{{navprefix}}/input-table-api[Input tables] * link:{{navprefix}}/manual-translation-api[Manual translations] * link:{{navprefix}}/webhooks-rest-api[Webhook APIs] diff --git a/modules/ROOT/pages/common/nav-rest-api.adoc b/modules/ROOT/pages/common/nav-rest-api.adoc index 60d009d8a..5910aed48 100644 --- a/modules/ROOT/pages/common/nav-rest-api.adoc +++ b/modules/ROOT/pages/common/nav-rest-api.adoc @@ -31,7 +31,7 @@ REST API endpoints ** link:{{navprefix}}/publish-to-orgs[Publish objects to Orgs] * link:{{navprefix}}/spotter-api[Spotter APIs] -** link:{{navprefix}}/spotter-agent-apis[Spotter AI agent APIs (Spotter Agent and Spotter 3)] +** link:{{navprefix}}/spotter-agent-apis[Spotter AI agent APIs] ** link:{{navprefix}}/spotter-agent-conversation-apis[Spotter agent conversation APIs] ** link:{{navprefix}}/spotter-agent-streaming-apis[Spotter agent streaming APIs] ** link:{{navprefix}}/spotter-agent-data-literacy-apis[Spotter agent data literacy APIs] @@ -40,9 +40,10 @@ REST API endpoints ** link:{{navprefix}}/spotter-agent-conversation-mgmt-apis[APIs for managing saved conversations] ** link:{{navprefix}}/spotter-analyst-api[Spotter Analyst APIs] ** link:{{navprefix}}/spotter-memory-migration[Spotter memory migration API] +** link:{{navprefix}}/spotter-usage-data-api[Spotter usage data APIs] ** link:{{navprefix}}/spotter-apis-classic[AI APIs (Spotter Classic)] -** link:{{navprefix}}/spotter-nl-instructions[Data model instructions APIs] -** link:{{navprefix}}/process-conversation-output[Export answers generated from a Spotter conversation] +** link:{{navprefix}}/spotter-nl-instructions[Data model instructions APIs (legacy)] +** link:{{navprefix}}/process-conversation-output[Export answers from a Spotter conversation] * Data and report APIs ** link:{{navprefix}}/fetch-data-and-report-apis[Data APIs] @@ -58,6 +59,7 @@ REST API endpoints ** link:{{navprefix}}/connections[Connections] ** link:{{navprefix}}/connection-config[Connection configuration] ** link:{{navprefix}}/manual-translation-api[Manual translations] +** link:{{navprefix}}/input-table-api[Input tables] * TML APIs ** link:{{navprefix}}/tml[TML] @@ -65,9 +67,10 @@ REST API endpoints *** link:{{navprefix}}/tml-export[Export TML] -* Style and email customization APIs +* Style, email, and link customization APIs ** link:{{navprefix}}/style-customization-apis[Style customization APIs] ** link:{{navprefix}}/customize-email-apis[Customize email template] +** link:{{navprefix}}/link-customization-api[Link customization APIs] * link:{{navprefix}}/collections[Collections] * link:{{navprefix}}/webhooks-rest-api[Webhook APIs] diff --git a/modules/ROOT/pages/common/nav.adoc b/modules/ROOT/pages/common/nav.adoc index 048ac0686..7f23dad91 100644 --- a/modules/ROOT/pages/common/nav.adoc +++ b/modules/ROOT/pages/common/nav.adoc @@ -55,6 +55,8 @@ Integration Guides Deployment guides * link:{{navprefix}}/thoughtspot-objects[ThoughtSpot objects overview] +** link:{{navprefix}}/object-id[Object ID] +** link:{{navprefix}}/object-id-urls[Object ID in URLs] * link:{{navprefix}}/timezone-aware-filtering[Timezone-aware keywords and filters] * link:{{navprefix}}/publish-data-overview[Publish content to Orgs] * link:{{navprefix}}/development-and-deployment[Development and deployment] diff --git a/modules/ROOT/pages/customize-email-apis.adoc b/modules/ROOT/pages/customize-email-apis.adoc index 67db22f91..9252798c9 100644 --- a/modules/ROOT/pages/customize-email-apis.adoc +++ b/modules/ROOT/pages/customize-email-apis.adoc @@ -1,4 +1,4 @@ -= Customize email template [earlyAccess eaBackground]#Early Access# += Customize email template :page-title: Customize notification email settings per Org :page-pageid: customize-email-apis diff --git a/modules/ROOT/pages/customize-links.adoc b/modules/ROOT/pages/customize-links.adoc index 7c92d9edb..6906d6c2d 100644 --- a/modules/ROOT/pages/customize-links.adoc +++ b/modules/ROOT/pages/customize-links.adoc @@ -7,6 +7,8 @@ ThoughtSpot users receive system-generated links in email notifications, which allow them to access objects such as Liveboards, visualizations or saved answers. +You can customize these links in the *Link settings* page of the *Develop* tab, or by using the xref:link-customization-api.adoc[link customization REST API v2 endpoints]. + ThoughtSpot generates the following types of links: Liveboards links:: @@ -69,11 +71,13 @@ xref:embed-search.adoc[SearchEmbed] component to an existing Answer: By default, ThoughtSpot generates these links with URL paths from the ThoughtSpot application context. If you have embedded ThoughtSpot in your application, you might want to generate links with the URL and resource paths from your host application context. For example, if your host app URL is `\https://www.mysite.com`, you may want to generate a Liveboard link with your host application URL instead of the standard ThoughtSpot portal URL. You can customize the format of system-generated links in the *Link settings* page of the *Develop* tab. -The *Link settings* page in the Developer portal displays the default link format for the system-generated links. You can either prefix your application domain URL to the default link format or customize the entire URL. ThoughtSpot recommends that you use the following variables in your link format: +The *Link settings* page in the Developer portal displays the default link format for the system-generated links. You can either prefix your application domain URL to the default link format or customize the entire URL. Each link type requires specific variables in its link format. ThoughtSpot rejects a link format that does not include them. The following variables are available: * `{object-id}` to represent the ID of a Liveboard, Answer, or the SpotIQ analyses. In the Liveboard, Answer, and SpotIQ analyses links, this variable is substituted by the GUID of the object. * `{sub-object-id}` to represent the ID of a visualization. In Liveboard visualization links, this variable is substituted by the GUID of the visualization. -* `{ts-query-params}` to allow ThoughtSpot to pass query parameters in the URL. + +* `{conversation-id}` to represent the ID of a shared Spotter conversation. +* `{path}` to represent the ThoughtSpot page path in the Generic link. +* `{ts-query-params}` to allow ThoughtSpot to pass query parameters in the URL. This variable is required for the Liveboard, Liveboard visualization, Answer, and Spotter conversation sharing links, and optional for the other link types. ThoughtSpot removes it from the link when there are no query parameters to pass. + For example, when a user subscribes to receive threshold-based alerts for a KPI chart, ThoughtSpot sends email notifications with a link to the KPI chart and also the *Unsubscribe* link to let the user unsubscribe from alerts at any time. When you include `{ts-query-params}` in the link string, ThoughtSpot passes the query parameters required for unsubscribing a user from the alert. + + @@ -95,20 +99,20 @@ To customize the link format, follow these steps: Liveboard sharing URL:: This URL provides a link to a ThoughtSpot Liveboard object. + -The default link format is `\https://{ThoughtSpot-Host}/#/pinboard/{object-id}`. You can customize this format to generate a link that represents the objects in your host application context. For example, if your host application is `www.mysite.com`, you can configure this link format as shown here: +The default link format is `\https://{ThoughtSpot-Host}/#/pinboard/{object-id}?{ts-query-params}`. The `{object-id}` and `{ts-query-params}` variables are required. You can customize this format to generate a link that represents the objects in your host application context. For example, if your host application is `www.mysite.com`, you can configure this link format as shown here: + ---- https://www.mysite.com/liveboard/{object-id}?{ts-query-params} ---- + ---- -https://www.mysite.com/?pinboard={object-id}?{ts-query-params} +https://www.mysite.com/?pinboard={object-id}&{ts-query-params} ---- Liveboard visualization URL:: This URL provides a link to a specific ThoughtSpot visualization in a Liveboard. + -The default link format is `\https://{ThoughtSpot-Host}/#/pinboard/{object-id}/{sub-object-id}?{ts-query-params}`.You can customize this format to represent the object attributes of your host application. For example, if your host application is `www.mysite.com`, you can configure this link format as shown here: +The default link format is `\https://{ThoughtSpot-Host}/#/pinboard/{object-id}/{sub-object-id}?{ts-query-params}`. The `{object-id}`, `{sub-object-id}`, and `{ts-query-params}` variables are required. You can customize this format to represent the object attributes of your host application. For example, if your host application is `www.mysite.com`, you can configure this link format as shown here: + ---- @@ -117,7 +121,7 @@ https://www.mysite.com/liveboard/{object-id}/{sub-object-id}?{ts-query-params} + ---- -https://www.mysite.com/?pinboard={object-id}/viz={sub-object-id} +https://www.mysite.com/?pinboard={object-id}&viz={sub-object-id}&{ts-query-params} ---- + @@ -139,7 +143,7 @@ https://www.mysite.com/liveboard/{object-id}/viz={sub-object-id}?{ts-query-param Answer sharing URL:: This URL provides a link to a shared Answer from a search query. -The default link format is `\https://{ThoughtSpot-Host}/#/saved-answer/{object-id}`. The customized link format also supports `{ts-query-params}`. For example, if a user has subscribed to receive monitor alerts for a saved Answer, ThoughtSpot replaces `{ts-query-params}` with query parameters to unsubscribe a user from the monitor alert. +The default link format is `\https://{ThoughtSpot-Host}/#/saved-answer/{object-id}?{ts-query-params}`. The `{object-id}` and `{ts-query-params}` variables are required. For example, if a user has subscribed to receive monitor alerts for a saved Answer, ThoughtSpot replaces `{ts-query-params}` with query parameters to unsubscribe a user from the monitor alert. If your host application is `www.mysite.com`, you can configure this link format as shown here: + @@ -148,7 +152,7 @@ https://www.mysite.com/saved-answer/{object-id}?{ts-query-params} ---- + ---- -https://www.mysite.com/?saved-answer={object-id} +https://www.mysite.com/?saved-answer={object-id}&{ts-query-params} ---- + @@ -168,7 +172,7 @@ SpotIQ analytics page:: This URL provides a link to the SpotIQ analyses page. + -The default link format is `\https://{ThoughtSpot-Host}/#/insight/{object-id}`. If your host application is `www.mysite.com`, you can configure this link format as shown here: +The default link format is `\https://{ThoughtSpot-Host}/#/insight/{object-id}?{ts-query-params}`. The `{object-id}` variable is required. If your host application is `www.mysite.com`, you can configure this link format as shown here: + ---- @@ -185,7 +189,7 @@ Unsubscribe link:: This URL provides a link to the *Profile* settings page in ThoughtSpot. + -The default link format is `\https://{ThoughtSpot-Host}/#/user-preference`. If your host application is `www.mysite.com`, you can configure this link format as shown here: +The default link format is `\https://{ThoughtSpot-Host}/#/user-preference?{ts-query-params}`. This link format has no required variables. If your host application is `www.mysite.com`, you can configure this link format as shown here: + ---- @@ -220,7 +224,7 @@ Generic link:: The *Generic link* setting allows customizing the embedded ThoughtSpot page URLs and navigation links that are not parameterized using the other link setting options in the *Customization* > *Link settings* page. + -The default link format is `\https://{ThoughtSpot-Host}/#/\{path}`. If your host application is `www.mysite.com`, you can configure the link format as shown here: +The default link format is `\https://{ThoughtSpot-Host}/#/\{path}?{ts-query-params}`. The `{path}` variable is required. If your host application is `www.mysite.com`, you can configure the link format as shown here: + ---- @@ -229,6 +233,15 @@ https://www.mysite.com/{path} . Click *Save changes*. +== Customize links using REST API + +You can use the following REST API v2 endpoints to manage the link formats at the cluster level or for an Org, instead of using the *Link settings* page: + +* `POST /api/rest/2.0/customization/links/search` to retrieve the current link formats +* `POST /api/rest/2.0/customization/links/update` to set a link format (`REPLACE`) or clear an override (`RESET`) + +For more information, see xref:link-customization-api.adoc[Link customization APIs]. + == Override ThoughtSpot URLs Link override settings allow embedded users to redirect native ThoughtSpot URLs to links within their host application. ThoughtSpot supports Visual Embed SDK configurations for overriding links generated by ThoughtSpot. These settings work the same for multi-tenant ThoughtSpot embedded instances too. @@ -306,6 +319,8 @@ image::./images/embed-link-liveboardSchedule.png[Embed link format] * Verify the `Unsubscribe` links in email notifications. +* You can also retrieve the link formats in effect for your cluster or Org by using the `POST /api/rest/2.0/customization/links/search` API endpoint. The `is_overridden` attribute in the response indicates whether a link type is customized. For more information, see xref:link-customization-api.adoc#search-link-customizations[Searching link customizations]. + //// diff --git a/modules/ROOT/pages/customize-spotter-embed.adoc b/modules/ROOT/pages/customize-spotter-embed.adoc index 1852e7181..8c2a22c47 100644 --- a/modules/ROOT/pages/customize-spotter-embed.adoc +++ b/modules/ROOT/pages/customize-spotter-embed.adoc @@ -8,6 +8,11 @@ The Visual Embed SDK provides a vast set of configuration settings and object properties to customize the Spotter UI and chat experience for your embedding application users. +[NOTE] +==== +[.version-badge.new]#26.11.0.cl# ThoughtSpot introduces the new Spotter experience, which includes Spotter on Liveboards and has its own embedding and customization options. See xref:embed-new-spotter.adoc[Embed the new Spotter experience]. +==== + == Spotter interface in the embedded view When you xref:embed-spotter.adoc[embed Spotter] in your application, you'll notice that the embedded component loads an initial page with a prompt interface. The look and feel of this page varies depending on the Spotter version used for embedding. @@ -147,7 +152,15 @@ For a comprehensive list of supported actions, see the xref:Action.adoc[Action r //// +== Spotter on Liveboards + +[NOTE] +==== +[.version-badge.new]#26.11.0.cl# The customization options on this page apply to the classic Spotter experience. In the new Spotter experience, Spotter opens in a side panel on a Liveboard and uses the entire board as conversation context. To enable it and to see the supported features and the differences from the classic experience, see xref:embed-new-spotter.adoc[Embed the new Spotter experience]. +==== + == Additional resources +* xref:embed-new-spotter.adoc[Embedding the new Spotter experience] * xref:customize-spotter-chat-experience.adoc[Customizing the Spotter chat experience] * xref:customize-spotter-sidebar.adoc[Customizing the Spotter sidebar panel] * xref:customize-spotter-sharing.adoc[Customizing Spotter conversation sharing] diff --git a/modules/ROOT/pages/deploy-with-tml-apis.adoc b/modules/ROOT/pages/deploy-with-tml-apis.adoc index 48ec1e6da..4e0d2c2a5 100644 --- a/modules/ROOT/pages/deploy-with-tml-apis.adoc +++ b/modules/ROOT/pages/deploy-with-tml-apis.adoc @@ -59,7 +59,7 @@ Properties of a Connection can also be parameterized. Parameterization works with both TML import and xref:publishing-overview.adoc[publishing]. === obj_id -Before implementing any deployment process, you should ensure that `obj_id` is enabled on your ThoughtSpot instance. +Before implementing any deployment process, you should ensure that `obj_id` is enabled on your ThoughtSpot instance. For information about supported object types, format rules, and resolution order, see xref:object-id.adoc[Object ID (obj_id)]. [NOTE] ==== @@ -116,6 +116,34 @@ Once you have decided on the appropriate `obj_id` for all the objects in your de You only have to do this process for existing objects *one time*, and from that point forward, you can update objects in any Org using TML with obj_ids rather than GUIDs. +[#adopting-obj-id-in-deployment-pipeline] +==== Adopting obj_id in a deployment pipeline +You can move an existing GUID-based deployment pipeline to `obj_id` one step at a time. Existing GUID-based workflows continue to work while you migrate, and you can start with the objects you deploy most often. + +. *Confirm that Object ID is enabled* on every ThoughtSpot instance in your pipeline. For more information, see xref:object-id.adoc#_enable_object_id[Enable Object ID]. +. *Define a naming convention.* Choose stable, readable identifiers that do not depend on the object's display name or GUID, for example, `--`: ++ +---- +sales-liveboard-prod +sales-model-prod +hubspot-contacts-table +---- ++ +The values must follow the xref:object-id.adoc#_obj_id_format_and_constraints[obj_id format]. +. *Assign `obj_id` values in the dev Org.* Use the `metadata/update-obj-id` endpoint or edit the `obj_id` in the object's TML. Replace automatically generated values such as `RetailSalesRAD-KPIs-c1e4043a`: they include part of the GUID, so copies of the same object in different Orgs receive different generated values. +. *Align existing copies in the other Orgs.* Give each existing copy of an object the same `obj_id` as the original in the dev Org. See <<_implementing_obj_id_in_existing_environments,Implementing obj_id in existing environments>>. +. *Export the release TML* with `include_obj_id` and `include_obj_id_ref` set to `true`. See <<_obj_id_or_guid,obj_id or guid>>. +. *Deploy for the first time.* Import the TML into the target Org without a `guid` property. If the object does not exist in the target Org, ThoughtSpot creates it and assigns a new GUID in that Org. +. *Deploy subsequent releases.* Import the same TML. ThoughtSpot finds the existing object by its `obj_id` and updates it. +. *Check the import response* for each file to confirm that it created or updated the expected object. +// TODO: confirm with engineering whether an obj_id that matches no object falls back to the GUID with a WARNING status (object-id.adoc) or creates a new object ("Rules for create vs. update operations" on this page). If the WARNING fallback is correct, add: "A WARNING status means the obj_id did not match an object and ThoughtSpot matched by GUID instead." +. *Retire your GUID mapping.* Once every deployed object has a consistent `obj_id` in all Orgs, you no longer need to maintain a GUID mapping file. + +[NOTE] +==== +Visualizations and Liveboard tabs do not have an `obj_id`. Objects that reference a visualization, such as Monitor alerts, Liveboard schedules, and related links, still use a GUID that is different in each Org. For more information, see xref:object-id.adoc#_objects_that_do_not_support_obj_id[Objects that do not support obj_id]. +==== + [#linkBuildRelease] == Identifying release package in dev Org The set of objects on the *dev Org* that makes up the "deployed releases" should be identified in a way that allows easy identification of the objects to be exported into Git. diff --git a/modules/ROOT/pages/development-and-deployment.adoc b/modules/ROOT/pages/development-and-deployment.adoc index 60ee8af69..2abbb84d8 100644 --- a/modules/ROOT/pages/development-and-deployment.adoc +++ b/modules/ROOT/pages/development-and-deployment.adoc @@ -21,7 +21,7 @@ xref:orgs.adoc[Orgs] are fully separated tenants on a single ThoughtSpot instanc image::./images/instances_and_orgs.png[Instances and Orgs] -By setting the `xref:intro-thoughtspot-objects.adoc#object-identifiers[obj_id]` property of objects, objects in various Orgs that are related copies of one another will have the same `obj_id`, allowing for tracking related objects and updating them without concern for each object's unique GUID. +By setting the `xref:object-id.adoc[obj_id]` property of objects, objects in various Orgs that are related copies of one another will have the same `obj_id`, allowing for tracking related objects and updating them without concern for each object's unique GUID. [NOTE] ==== diff --git a/modules/ROOT/pages/embed-new-spotter.adoc b/modules/ROOT/pages/embed-new-spotter.adoc new file mode 100644 index 000000000..4ae238648 --- /dev/null +++ b/modules/ROOT/pages/embed-new-spotter.adoc @@ -0,0 +1,271 @@ += Embed the new Spotter experience +:toc: true +:toclevels: 2 + +:page-title: Embed the new Spotter experience +:page-pageid: embed-new-spotter +:page-description: Enable the new Spotter experience, including Spotter on Liveboards, in your embedded application using the Visual Embed SDK. + +ThoughtSpot introduces a new Spotter experience where Spotter opens in a side panel on a Liveboard and uses the entire board, including its charts, tabs, groups, note tiles, and applied filters, as conversation context. The Spotter home page also moves to the new experience, and conversations are saved with the Liveboard so users can return to them later. + +The new experience is disabled by default. You can enable it using the `spotterExperienceVersion` attribute in full application, Liveboard, or Spotter embedding. + +== Before you begin + +Ensure you have the following setup: + +* Your ThoughtSpot instance must be running 26.11.0.cl or later, with the new experience enabled at the instance or Org level. A ThoughtSpot administrator enables it from **Admin** > **ThoughtSpot AI** > **Choose Spotter 3 Liveboard experience** > **Liveboard side panel (New)**. The setting can be applied to the whole instance or to a single Org. +* Your host application domain is added to xref:security-settings.adoc[ThoughtSpot CSP and CORS allowlists]. +* Your embedding application project has Visual Embed SDK v1.53.0 or later. Some of the controls described on this page need a later SDK version. The required version is noted for each control. + +== Enabling the new Spotter experience +To enable the new Spotter experience in your embed, set the `spotterExperienceVersion` property to `SpotterExperienceVersion.SPOTTER_2026_11` in your embed configuration. The property is available in `SpotterEmbed`, `LiveboardEmbed`, and `AppEmbed`, and the `SpotterExperienceVersion` enum is exported from the SDK. + +[NOTE] +==== +If you set `spotterExperienceVersion` to a value that the SDK doesn't recognize, the embed falls back to the standard Spotter experience without an error or warning. If the new experience doesn't load, check the `spotterExperienceVersion` value. +==== + +Spotter embed:: + +[source,JavaScript] +---- +import { + SpotterEmbed, + SpotterExperienceVersion, + AuthType, + init, +} from '@thoughtspot/visual-embed-sdk'; + +init({ + thoughtSpotHost: 'https://your-thoughtspot-host', + authType: AuthType.None, +}); + +const spotterEmbed = new SpotterEmbed(document.getElementById('ts-embed'), { + frameParams: { + height: '100%', + width: '100%', + }, + worksheetId: 'your-worksheet-id', + spotterExperienceVersion: SpotterExperienceVersion.SPOTTER_2026_11, + //... other configuration attributes +}); + +spotterEmbed.render(); +---- + +Liveboard embed:: + +[source,JavaScript] +---- +import { + LiveboardEmbed, + SpotterExperienceVersion, + AuthType, + init, +} from '@thoughtspot/visual-embed-sdk'; + +init({ + thoughtSpotHost: 'https://your-thoughtspot-host', // Replace with your ThoughtSpot URL + authType: AuthType.None, +}); + +const liveboardEmbed = new LiveboardEmbed(document.getElementById('ts-embed'), { + frameParams: { + height: '100%', + width: '100%', + }, + liveboardId: 'your-Liveboard-id', // Replace with your Liveboard ID + spotterExperienceVersion: SpotterExperienceVersion.SPOTTER_2026_11, + //... other configuration attributes +}); + +liveboardEmbed.render(); +---- + +Full application embed:: + +[source,JavaScript] +---- +import { + AppEmbed, + Page, + SpotterExperienceVersion, + AuthType, + init, +} from '@thoughtspot/visual-embed-sdk'; + +init({ + thoughtSpotHost: 'https://your-thoughtspot-host', // Replace with your ThoughtSpot URL + authType: AuthType.None, +}); + +const appEmbed = new AppEmbed(document.getElementById('ts-embed'), { + frameParams: { + height: '100%', + width: '100%', + }, + pageId: Page.Home, + spotterExperienceVersion: SpotterExperienceVersion.SPOTTER_2026_11, + //... other configuration attributes +}); + +appEmbed.render(); +---- + +== Spotter on Liveboards in embedded apps + +When the new experience is enabled, you'll see the following behavior: + +* Spotter opens in a side panel next to the Liveboard, and the board stays usable while the panel is open. The board resizes to make room for the panel. +* Spotter reads every tab, group, chart, and insight on the Liveboard, so users can ask about one chart, several selected tiles, or the whole board. +* Answers respect the filters applied to the Liveboard. Users do not need to restate filter context in their questions. +* The **Spotter** button on a chart opens the Spotter panel and adds the chart to it as a reference to set context, instead of opening a pop-up for that one chart. Users can select several charts, groups, and note tiles as context. +* Spotter can use a note tile, such as a tile with quarterly targets, as context next to the data. +* On a Liveboard, Spotter uses only the data models behind that Liveboard. Make sure Spotter is enabled on those models. +* Conversations are saved with the Liveboard, and users can continue them later. +* When the Liveboard is switched to edit mode, the Spotter panel closes. To control who can enter edit mode in your embed, see <<_sdk_controls_for_the_new_experience,SDK controls for the new experience>>. +* The panel opens automatically when the Liveboard loads. To change this, see <<_sdk_controls_for_the_new_experience,SDK controls for the new experience>>. + +[source,JavaScript] +---- +const liveboardEmbed = new LiveboardEmbed(document.getElementById('ts-embed'), { + liveboardId: 'your-liveboard-id', + spotterExperienceVersion: SpotterExperienceVersion.SPOTTER_2026_11, + //... other configuration attributes +}); +---- + +=== Spotter panel visibility +If the panel is missing from a Liveboard embed, check these conditions: + +* You are embedding a single visualization instead of the full Liveboard. +* The user doesn't have permission to use Spotter. +* The Liveboard doesn't contain any visualization. +* None of the Liveboard's visualizations are based on a data model that has Spotter enabled. +* The **Spotter** button is hidden or turned off with `Action.SpotterOnLiveboard`. + +== Comparison with the standard Spotter experience + +The following table compares Spotter on Liveboards (the new experience) with the standard Spotter experience, which includes the Spotter classic, Spotter 2, and Spotter 3 experiences. It summarizes the differences that matter most to embed developers, including the capabilities that aren't available yet in the new experience. Responses and charts, code-based analysis, and data and permissions work the same in both experiences. + +[width="100%", cols="2,3,3"] +|==== +|Area |Standard Spotter experience (including Spotter classic, Spotter 2, and Spotter 3) |Spotter on Liveboards (new experience) + +|Where users ask a question +|Spotter home page, and a pop-up for one chart on a Liveboard. +|Spotter home page, and a side panel on the whole Liveboard. + +|Context on a Liveboard +|The selected chart. +|The entire Liveboard, including its tabs, groups, charts, note tiles, and applied filters. + +|Embed property +|Default. The `spotterExperienceVersion` is not set. +|The `spotterExperienceVersion` is set to `SpotterExperienceVersion.SPOTTER_2026_11`. + +|Data model selection +|Configurable with the automatic data model selection setting. +|Automatic data model selection is on by default. New conversations on the Spotter home page search all data models the user can access, and users can still pick a specific model. On a Liveboard, the selection is limited to the underlying data models used to generate its visualizations. + +|Chat history +|Controlled by the **Enable chat history** setting at the instance level and `enablePastConversationsSidebar` setting in the `spotterSidebarConfig` at the SDK level. +|Chat history on by default. Retention is 6 hours, 30, 90, or 180 days. Currently, there is no option available in the SDK to turn off chat history in the new experience. To turn chat history off, contact your ThoughtSpot administrator. + +|Spotter conversations on a Liveboard +|Not saved with the Liveboard. +|Saved with the Liveboard. + +|Clarifying questions +|Not available. +|Available. When Spotter is unsure what a question means, it asks a clarifying question with options to choose from. + +|Deep analysis +|Available. +|Not available. Spotter decides the depth of analysis from the question. + +|Monitoring +|Spotter conversations Liveboard. +|Usage metrics Liveboard and an all chats list, available to administrators only. + +|Existing conversations +|Saved in the standard Spotter experience. +|Copied to the new experience in the background, with their original dates and IDs, so deep links from your host application keep working. Conversations added in the new experience are not copied to the standard Spotter experience. + +|CSV file upload +|Available in Spotter 2 and Spotter 3. +|Available. Users can upload a CSV file and analyze it alongside the Liveboard data in the same conversation. + +|Data model instructions and data preview +|Shown in the Spotter view. +|Not shown in the Spotter view. Users can still view them on the data model. + +|Connectors, personal memory, agent instructions, and custom calendars +|Available. +|Available. Each connector stays off until an administrator, or a user with the **Can manage Spotter** privilege, turns it on. + +|Edit and drill down on answers +|Available. +|Not available. + +|Sharing conversations and shared links +|Available. +|Not available. The `spotterShareConversationConfig` property has no effect, and existing shared links stop working after an Org switches. + +|Searching conversations in the Spotter panel +|Available. +|Available. + +|Scheduling questions +|Available. +|Not available. + +|Report generation (PDF) and benchmarks +|Available. +|Not available. + +|Spotter Analysts +|Available on the Spotter home page. +|Not available in the Spotter panel on a Liveboard. + +|Mobile and Slack app +|Supported. +|Not supported. They continue to use the standard Spotter experience. +|==== + +== SDK controls for the new experience + +The following Visual Embed SDK options are available in embeds that use the new experience: + +* `spotterChatConfig.openSpotterOnLiveboardByDefault`: Controls whether the Spotter panel opens automatically when the Liveboard loads. The default value is `true`. Set it to `false` to load the Liveboard with the panel closed. Supported in `LiveboardEmbed` and `AppEmbed` from v1.53.0 onwards. ++ +[source,JavaScript] +---- +const liveboardEmbed = new LiveboardEmbed(document.getElementById('ts-embed'), { + liveboardId: 'your-liveboard-id', + spotterExperienceVersion: SpotterExperienceVersion.SPOTTER_2026_11, + spotterChatConfig: { + openSpotterOnLiveboardByDefault: false, + }, +}); +---- +* `Action.SpotterOnLiveboard`: Controls the **Spotter** button in the Liveboard header. Add it to `hiddenActions` to remove the Spotter panel completely. Add it to `disabledActions` to grey out the header button. Supported in `LiveboardEmbed` and `AppEmbed` from v1.53.0 onwards. +* `Action.EditLiveboard` and `Action.EditVisualization`: Hide or turn off the **Edit** option on a Liveboard or a visualization independently. `Action.Edit` continues to control both. Because the Spotter panel closes when a Liveboard enters edit mode, you can use these actions to control when users leave Spotter. Supported in `LiveboardEmbed` and `AppEmbed` from v1.54.0 onwards. +* `EmbedEvent.EditLiveboard` and `EmbedEvent.EditVisualization`: Fire when a user selects **Edit** on a Liveboard or a visualization, alongside `EmbedEvent.Edit`. Supported from v1.54.0 onwards. +* `HostEvent.EditLiveboard` and `HostEvent.EditVisualization`: Trigger Edit on one surface. `EditVisualization` requires a `vizId`. Supported from v1.54.0 onwards. + +== Switching to the standard Spotter experience +To switch to the standard experience at any time: + +. Remove the `spotterExperienceVersion` property from your embed configuration and re-render the embed. +. If the new experience is enabled in your instance or Org, contact your administrators to turn it off and return to the standard Spotter experience. + +Note that when you switch to the standard experience, conversations started in the new experience aren't available in the standard Spotter experience, and shared links don't move between experiences. + +== Additional resources + +* xref:embed-spotter.adoc[Embed Spotter experience] +* xref:customize-spotter-embed.adoc[Customize the Spotter embed view] +* link:https://docs.thoughtspot.com/cloud/latest/spotter[Spotter Product Documentation, window=_blank] \ No newline at end of file diff --git a/modules/ROOT/pages/embed-spotter.adoc b/modules/ROOT/pages/embed-spotter.adoc index 01fbdf608..5f14da352 100644 --- a/modules/ROOT/pages/embed-spotter.adoc +++ b/modules/ROOT/pages/embed-spotter.adoc @@ -8,6 +8,11 @@ You can embed the full Spotter experience in your applications using the `SpotterEmbed` component in the Visual Embed SDK. Using the customization settings available in the SDK for each Spotter version, you can configure the Spotter interface to suit the needs of your embedding application. +[NOTE] +==== +[.version-badge.new]#26.11.0.cl# To embed the new Spotter experience, including Spotter on Liveboards, see xref:embed-new-spotter.adoc[Embed the new Spotter experience]. +==== + == Before you begin To embed Spotter, you need the following access and setup: diff --git a/modules/ROOT/pages/input-table-api.adoc b/modules/ROOT/pages/input-table-api.adoc new file mode 100644 index 000000000..c50e1d9f0 --- /dev/null +++ b/modules/ROOT/pages/input-table-api.adoc @@ -0,0 +1,345 @@ += Input Table APIs +:toc: true +:toclevels: 2 + +:page-title: Input Table APIs +:page-pageid: input-table-api +:page-description: Use the Input Table REST API v2 endpoints to create input tables, add or remove columns, and write data to input tables linked to ThoughtSpot models. +:keywords: input table, input tables, writeback, Cloud Data Warehouse, model, REST API + +Input tables are user-editable tables stored in an external Cloud Data Warehouse (CDW) and linked to a ThoughtSpot model. They allow analysts to enter or import data directly from the ThoughtSpot UI without requiring access to the underlying warehouse. + +ThoughtSpot provides public REST API v2 endpoints to manage input tables programmatically for the following purposes: + +* To create an input table and link it to a model as part of an automated deployment workflow. +* To add or remove editable columns as your data requirements change. +* To write data, such as forecasts, targets, or other planning inputs, from an external application or pipeline to an input table. + +[NOTE] +==== +The Input Table APIs are available on ThoughtSpot Cloud 26.11.0.cl and later. +==== + +== Input table workflow +To create an input table and populate it with data: + +. <> + +Call `POST /api/rest/2.0/input-tables/create` with the model to link, the model columns to reference as key columns, and the new editable columns. The response returns the `input_table_id` and the ID of each column. +. <> (optional) + +Call `POST /api/rest/2.0/input-tables/{input_table_identifier}/columns/create` to add more editable columns later. +. <> + +Call `POST /api/rest/2.0/input-tables/{input_table_identifier}/update` to insert or update rows. +. <> or <> (optional) + +Call the delete endpoints to remove a column or the entire table when it is no longer required. + +=== Required privileges +All Input Table API endpoints require one of the following privileges: + +* `DATAMANAGEMENT` (**Can manage data**) +* `ADMINISTRATION` (**Can administer ThoughtSpot**) + +If link:https://developers.thoughtspot.com/docs/rbac[Role-Based Access Control (RBAC), window=_blank] is enabled on your instance, the `CAN_MANAGE_INPUT_TABLES` (**Can manage input tables**) privilege is required. + +The caller must also have `MODIFY` permission on the following objects: + +* The model specified in `model_identifier`, to create an input table. +* The input table, to add or delete columns, write rows, or delete the table. + +[#create-input-table] +== Creating an input table +The `/api/rest/2.0/input-tables/create` API endpoint creates an input table and links it to a ThoughtSpot model. The physical table is created in the same connection, database, and schema as the linked model. Ensure that the connection user has `CREATE TABLE` permission in the target schema and that upload is enabled on the connection. If upload is disabled, the API returns a `400` error. + +=== Request parameters +[cols="2,4", options="header"] +|=== +|Parameter | Description +| `table_name` +|__String__. Physical name of the table to create in the external warehouse. The name must start with a letter or underscore, contain only letters, digits, and underscores, and be at most 128 characters. +| `model_identifier` +|__String__. GUID or name of the model (worksheet) to link the input table to. ThoughtSpot derives the connection, database, and schema for the physical table from this model. +| `table_definition` +a|__Object__. Defines the table schema. Specify the following attributes: + +* `referenced_columns` + +__Array of strings__. Names of the model columns to include as read-only reference columns, as they appear on the model. These columns become the key columns of the input table. The input table is joined to the model on these columns, and rows are matched on them when you write data. At least one column is required. Each name must match exactly one visible model column and resolve to exactly one physical base column. You cannot reference formula, cohort, or constant columns. +* `new_columns` + +__Array of objects__. The new editable columns to create. For each column, specify the following attributes: + +** `name`. __String__. Display name of the column. +** `data_type`. __String__. Data type of the column in the warehouse, for example, `VARCHAR`, `DOUBLE`, or `DATE`. The supported values depend on the underlying CDW. +** `type`. __String__. Semantic role of the column: `ATTRIBUTE` for dimension columns or `MEASURE` for numeric columns. +** `allowed_values`. __Array of strings__. Optional. Up to 500 permitted values, which turn the column into a fixed-choice column. Each value must be non-empty, at most 8192 characters, and valid for the column's `data_type`: a number for numeric types, `true` or `false` for `BOOL`, and an epoch integer for `DATE`, `DATE_TIME`, and `TIME`. Writes that contain any other non-empty value are rejected. If you omit this attribute, the column accepts any value that its data type supports. +* `referenced_column_time_dimensions` + +__Array of objects__. Optional. Locks the referenced date columns to a specific time dimension (grain) at creation. Each entry includes the `column_identifier`, which is the name of the referenced model column exactly as specified in `referenced_columns`, and the `time_dimension`. Supported values for `time_dimension` are `HOURLY`, `DAILY`, `WEEKLY`, `MONTHLY`, `QUARTERLY`, and `YEARLY`. If you omit a column, ThoughtSpot applies no bucketing to it. The time dimension applies only to `DATE` and `DATE_TIME` columns. `HOURLY` requires a `DATE_TIME` column. If you specify `HOURLY` for a `DATE` column, it is ignored and the column is not bucketed. Date-part grains, such as day of the week, and grains on `TIME` columns are not supported. Time dimensions apply only to referenced columns. Columns created through `new_columns` are always unbucketed. +|=== + +=== Request example + +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/input-tables/create' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{ + "table_name": "forecast_data", + "model_identifier": "{model-guid}", + "table_definition": { + "referenced_columns": ["Region", "Quarter"], + "new_columns": [ + { + "name": "forecast_revenue", + "data_type": "DOUBLE", + "type": "MEASURE" + }, + { + "name": "confidence_level", + "data_type": "VARCHAR", + "type": "ATTRIBUTE", + "allowed_values": ["HIGH", "MEDIUM", "LOW"] + } + ] + } +}' +---- + +=== API Response +Returns `200 OK` and the input table ID with the details of each column in the input table. + +[source,JSON] +---- +{ + "input_table_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", + "input_columns": [ + { + "name": "Region", + "id": "b1c2d3e4-0000-1111-2222-333344445555", + "mapped_column_id": "c7d8e9f0-1234-5678-abcd-ef0987654321" + }, + { + "name": "Quarter", + "id": "d2e3f4a5-1111-2222-3333-444455556666", + "mapped_column_id": "e8f9a0b1-2345-6789-bcde-f01987654322" + }, + { + "name": "forecast_revenue", + "id": "a9b8c7d6-9999-8888-7777-666655554444" + }, + { + "name": "confidence_level", + "id": "f0a1b2c3-3333-4444-5555-666677778888" + } + ] +} +---- + +The response includes the following parameters: + +[cols="2,4", options="header"] +|=== +| Parameter | Description +| `input_table_id` +| GUID of the new input table. Use this value as the `input_table_identifier` path parameter in the other Input Table API endpoints. +| `input_columns` +a| Every column on the new table. Each entry includes the following attributes: + +* `name`: Display name of the column. +* `id`: GUID of the column. +* `mapped_column_id`: GUID of the model column that the input column is mapped from. Present only for referenced columns. + +Use the column IDs to address specific columns in later calls without a separate lookup. +| `message_info` +| A note that is present only when ThoughtSpot renames a referenced column to keep the column names of the input table unique. If a model column name occurs in more than one base table, ThoughtSpot prefixes it with the base table name. For example, `Region` becomes `sales_Region`. The final name of the renamed column is also available in `input_columns`, and it is the name you must use when you write rows. +|=== + +[#create-input-table-column] +== Adding columns to an input table +The `/api/rest/2.0/input-tables/{input_table_identifier}/columns/create` API endpoint adds one or more editable columns to an existing input table. This operation widens the physical table in the CDW and refreshes the metadata of the input table in ThoughtSpot, so that the new columns are available on the linked model. + +You can add only new editable columns with this endpoint. A column added this way is never a key column and does not have a time dimension. + +=== Request parameters +[cols="2,4", options="header"] +|=== +|Parameter | Description +| `input_table_identifier` +|__String__. Path parameter. GUID of the input table to add the columns to. +| `column_definition` +a|__Object__. Defines the columns to add. Specify the following attribute: + +* `columns` + +__Array of objects__. The new editable columns. For each column, specify the `name`, `data_type`, and `type` (`ATTRIBUTE` or `MEASURE`). Optionally, include `allowed_values`. The column name must not collide with an existing column on the table. For more information about these attributes, see <>. +|=== + +=== Request example + +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/input-tables/{input_table_identifier}/columns/create' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{ + "column_definition": { + "columns": [ + { + "name": "forecast_margin", + "data_type": "DOUBLE", + "type": "MEASURE" + } + ] + } +}' +---- + +=== API Response +Returns `200 OK` and the added columns with their generated GUIDs. Use these GUIDs as the `column_identifier` to <>. + +[source,JSON] +---- +{ + "columns": [ + { + "name": "forecast_margin", + "id": "6b3a8f21-9c4d-4e77-bf2a-1d5e7c9a0b34" + } + ] +} +---- + +[#update-input-table] +== Updating an input table +The `/api/rest/2.0/input-tables/{input_table_identifier}/update` API endpoint writes rows into an existing input table using a keyed upsert (MERGE) operation. ThoughtSpot matches the rows in the request with the existing rows on the key columns of the input table, which are the columns mapped to the linked model. A matched row is updated in place, and a row whose key is not found is inserted. + +=== Request parameters +[cols="2,4", options="header"] +|=== +|Parameter | Description +| `input_table_identifier` +|__String__. Path parameter. GUID of the input table to write to. +| `columns` +|__Array of strings__. Ordered list of the column names to write. The column names must exactly match the names defined when the input table was created. The list must include every key column and at least one non-key column. Key columns identify a row but are never overwritten, so a payload with only key columns is rejected. +| `rows` +|__Array of arrays__. The rows to write. At least one row is required. An empty `rows` array is rejected. Each row is an array of string values in the same order as `columns`, with exactly one value per column. Pass all values as strings regardless of the data type of the column. An empty value writes `NULL` to the cell. +|=== + +=== Date value handling +* For `DATE` columns, pass an ISO calendar date (`yyyy-MM-dd`), for example, `2025-01-01`. ThoughtSpot stores the value exactly as written, without time zone conversion. Epoch numbers, in seconds or milliseconds, are also accepted, but they are resolved in the cluster's local time zone, so a UTC-midnight epoch can land on the previous day on clusters west of UTC. Use the ISO format. +* `DATE_TIME` and `TIME` columns accept epoch numbers only. An ISO value is rejected. +* All rows must use the same format for a given column. A calendar-invalid date, such as `2026-02-30`, is rejected. + +=== Write semantics +* **Matched rows**: Only the non-key columns in `columns` are overwritten. Columns that you do not include keep their existing values. +* **New rows**: A new row is inserted. Non-key columns that you do not include are set to `NULL`. +* This is not a full-table replace. Existing rows whose keys are not in the request are not changed. +* The operation is idempotent. Retrying the same request is safe. + +The API rejects the request if a column name does not match the table schema, the number of values in a row does not match the number of `columns`, a key column is missing, no non-key column is specified, or a value is not compatible with the data type of its column. + +=== Request example + +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/input-tables/{input_table_identifier}/update' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{ + "columns": ["Region", "Quarter", "forecast_revenue"], + "rows": [ + ["West", "Q1 2026", "500000"], + ["East", "Q1 2026", "750000"] + ] +}' +---- + +=== API Response +Returns `200 OK` and the number of rows written, which is the sum of rows updated and rows inserted. The count is the number reported by the warehouse. If the warehouse completes the load but does not report a count, the API returns a `500` error. + +[source,JSON] +---- +{ + "rows_loaded": 2 +} +---- + +[#delete-input-table-column] +== Deleting an input table column +The `/api/rest/2.0/input-tables/{input_table_identifier}/columns/{column_identifier}/delete` API endpoint deletes a single editable column from an input table. This operation removes the column from the input table metadata in ThoughtSpot and drops the physical column from the CDW. All data stored in the column is permanently deleted. + +[WARNING] +==== +This operation cannot be undone. +==== + +You can delete only the columns that were added directly to the input table (editable, non-referenced columns). The API rejects the request if the column is a referenced (model-projected) column or if an existing Answer or Liveboard still references it. + +=== Request parameters +[cols="2,4", options="header"] +|=== +|Parameter | Description +| `input_table_identifier` +|__String__. Path parameter. GUID of the input table that owns the column. +| `column_identifier` +|__String__. Path parameter. GUID of the column to delete. Use the `id` returned for the column in the response of the <> API (`input_columns`) or the <> API (`columns`). +|=== + +This endpoint does not require a request body. + +=== Request example + +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/input-tables/{input_table_identifier}/columns/{column_identifier}/delete' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' +---- + +=== API Response +Returns `204 No Content` if the column is deleted and the physical column is dropped from the CDW. + +[#delete-input-table] +== Deleting an input table +The `/api/rest/2.0/input-tables/{input_table_identifier}/delete` API endpoint deletes an input table. This operation unlinks the input table from its owner model, removes it from the connection metadata, and drops the physical table from the CDW. All data stored in the input table is permanently deleted. + +[WARNING] +==== +This operation cannot be undone. +==== + +Deleting an input table does not delete the linked model. However, any Answers or Liveboards that reference columns from the deleted input table lose access to that data and may return errors until you update the affected visualizations. + +=== Request parameters +[cols="2,4", options="header"] +|=== +|Parameter | Description +| `input_table_identifier` +|__String__. Path parameter. GUID of the input table to delete. ThoughtSpot derives the owner model from the metadata of the input table. +|=== + +This endpoint does not require a request body. + +=== Request example + +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/input-tables/{input_table_identifier}/delete' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' +---- + +=== API Response +Returns `204 No Content` if the input table is deleted and the physical table is dropped from the CDW. + +== Additional resources + +* xref:rest-api-v2-reference.adoc#_input_tables[REST API v2.0 Reference] +* xref:rest-apiv2-changelog.adoc[REST API v2.0 changelog] +* +++REST API Playground - Create input table endpoint+++ +* +++REST API Playground - Create input table column endpoint+++ +* +++REST API Playground - Update input table endpoint+++ +* +++REST API Playground - Delete input table column endpoint+++ +* +++REST API Playground - Delete input table endpoint+++ diff --git a/modules/ROOT/pages/intro-thoughtspot-objects.adoc b/modules/ROOT/pages/intro-thoughtspot-objects.adoc index 2b9394169..dc97770ae 100644 --- a/modules/ROOT/pages/intro-thoughtspot-objects.adoc +++ b/modules/ROOT/pages/intro-thoughtspot-objects.adoc @@ -4,11 +4,11 @@ :page-title: ThoughtSpot objects :page-pageid: thoughtspot-objects -:page-description: +:page-description: Learn about ThoughtSpot objects, their identifiers, and how they are organized in the ThoughtSpot data model. -ThoughtSpot is a business intelligence and data analytics platform for exploring, analyzing, and sharing real-time business analytics and interactive insights. Besides being an interactive data analytics platform, ThoughtSpot provides robust, guided search functionality that business users can use to search data instantly. ThoughtSpot is different from other BI tools because ThoughtSpot Search is the core of the ThoughtSpot system. +ThoughtSpot is a business intelligence (BI) and data analytics platform for exploring, analyzing, and sharing real-time business analytics and interactive insights. ThoughtSpot Search is the core of the ThoughtSpot system, making it distinct from other BI tools. -Review this page to understand how ThoughtSpot's architecture differs from other BI tools before proceeding with the developer documentation. +This page explains how ThoughtSpot's architecture differs from other BI tools. Read this before proceeding with the developer documentation. == Object model hierarchy @@ -17,109 +17,29 @@ The following figure illustrates the object model hierarchy in ThoughtSpot withi image::./images/object_model_hierarchy.png[Object Model Hierarchy] == Object identifiers -Every object in ThoughtSpot has a globally unique ID (GUID), visible in URLs and in REST API responses as the `id` or `metadata_id` property. GUIDs are unique within a ThoughtSpot instance and thus cannot repeat in different Orgs. -Objects have an additional `obj_id` property that is *user-settable* and *unique per Org*. It appears as `metadata_obj_id` in responses from the `/metadata/search` REST API. +[#object-identifiers] +Every object in ThoughtSpot has a globally unique ID (GUID), visible in URLs and in REST API responses as the `id` or `metadata_id` property. GUIDs are unique within a ThoughtSpot instance and thus cannot repeat in different Orgs. Because GUIDs are generated separately on each instance, a copy of an object in another Org or instance has a different GUID. -Each Org can have one object with a particular `obj_id`. The combination of `org_id` + `obj_id` is unique per instance, so it is equivalent to the object's GUID. +[#_supported_object_types] +Supported objects also have an Object ID (`obj_id`) property that is *user-settable* and *unique per Org*. The combination of `org_id` + `obj_id` is unique per instance, so it is equivalent to the object's GUID. The `obj_id` appears as `metadata_obj_id` in responses from the `/metadata/search` REST API. -`obj_id` enables TML export and import across Orgs and instances, allowing ThoughtSpot to automatically determine the object's GUID without manual GUID mapping. +[#_obj_id_format_and_constraints] +Because you choose the `obj_id`, related copies of an object in different Orgs and instances can share the same value. This allows ThoughtSpot to match objects during TML import without manual GUID mapping, and allows you to reference objects in REST API requests and ThoughtSpot URLs with the same identifier in every environment. -=== Supported object types +[#_obj_id_resolution] +For more information, see the following pages: -Currently, `obj_id` is supported for the following object types: - -// SOURCE: PRD doc section "Requirements"; SCAL-317366 description - -* Answers -* Data Model -* Logical Tables -* Liveboards -* Visualizations -* Collections -* Personalized Views -* Roles -* Template variables - -=== obj_id format and constraints - -// SOURCE: PRD doc section "Identity Constraints and Object-ID Specification"; SCAL-314582 -`obj_id` values must meet the following requirements: - -[cols="2,3", options="header"] -|=== -|Constraint | Requirement - -|Allowed characters | Lowercase alphanumeric, dots, and hyphens: `[a-z0-9.-]` -|Casing | Strictly lowercase -|Maximum length | 64 characters -|GUID exclusion | Must not match a standard GUID format to prevent ambiguity -|=== - -*Valid examples:* `sales.pipeline.v1`, `finance-ledger-prod`, `ingestion-worker-01` - -=== obj_id resolution - -// SOURCE: PRD doc section "Deterministic Keying and Distributed Consistency"; SCAL-317366 -When an identifier is passed to a REST API endpoint that accepts an `object_identifier`, ThoughtSpot resolves it in the following order: - -. `obj_id` (user-defined identifier) -. GUID -. Name - -This resolution order enables `obj_id` to be used anywhere a GUID or name is accepted in the REST API v2.0 endpoints that support the `object_identifier` field. Backward compatibility with existing GUID-based and name-based integrations is fully maintained. - -[NOTE] -==== -`obj_id` resolution is scoped to the Org. An `obj_id` value is unique within a single Org. The `org_id` + `obj_id` combination uniquely identifies an object across the entire ThoughtSpot instance. -==== - -=== Setting and updating obj_id - -`obj_id` values can be set or updated using the following REST API endpoints: - -* `POST /api/rest/2.0/metadata/update-obj-id` + -Updates the `obj_id` for one or more metadata objects. Accepts the object's GUID (`metadata_identifier`) or its current `obj_id` (`current_obj_id`). - -// SOURCE: deploy-with-tml-apis.adoc; SCAL-317366 -[,json] ----- -{ - "metadata": [ - { - "metadata_identifier": "c1e4043a-4524-4fcb-a20f-9e7aff4dc972", - "new_obj_id": "sales-pipeline-v1" - } - ] -} ----- - -Or, using the current `obj_id`: - -[,json] ----- -{ - "metadata": [ - { - "current_obj_id": "sales-pipeline-v1-c1e4043a", - "new_obj_id": "sales-pipeline-v1" - } - ] -} ----- - -The request accepts an array, allowing multiple objects to be updated in a single API call. - -[NOTE] -==== -Objects are assigned an automatic `obj_id` after the first change to the object once the feature is enabled on your instance. The auto-generated format appends the first segment of the GUID: for example, `RetailSalesRAD-KPIs-c1e4043a`. If the `metadata_obj_id` property in the `/metadata/search` response is `null`, the object has not been updated since the feature was enabled. -==== - -For information about using `obj_id` in CI/CD workflows, see xref:deploy-with-tml-apis.adoc[Deploy with TML APIs] and xref:development-and-deployment.adoc[Development and deployment]. +[#_setting_and_updating_obj_id] +* xref:object-id.adoc[Object ID (obj_id)] + +Supported object types, `obj_id` format and constraints, how identifiers are resolved, and how to set or update an `obj_id`. +* xref:object-id-in-urls.adoc[Object ID in ThoughtSpot URLs] + +Use an `obj_id` instead of a GUID in Liveboard, Answer, Collection, data object, and connection URLs. == Data modeling + A data model requires at least one link:https://docs.thoughtspot.com/cloud/latest/connections[connection, window=_blank] and one link:https://docs.thoughtspot.com/cloud/latest/connect-data[Table, window=_blank] to use link:https://docs.thoughtspot.com/cloud/latest/search-data[Search data, window=_blank] to create content. -Most often, there will be multiple *Tables* with a variety of link:https://docs.thoughtspot.com/cloud/latest/tables-join[joins, window=_blank] defined in ThoughtSpot, and a link:https://docs.thoughtspot.com/cloud/latest/models[Model, window=_blank] that brings those tables together into a presentable analytics model for end users. +In most cases, there are multiple *Tables* with a variety of link:https://docs.thoughtspot.com/cloud/latest/tables-join[joins, window=_blank] defined in ThoughtSpot, and a link:https://docs.thoughtspot.com/cloud/latest/models[Model, window=_blank] that brings those tables together into a presentable analytics model for end users. Data engineers with the *Can manage data* privilege can add connections either link:https://docs.thoughtspot.com/cloud/latest/connections[in the UI, window=_blank] or via xref:connections.adoc[REST API]. Connections are owned and accessible only to their creator, who then imports *Tables* from the connection. Once imported, tables can be shared with other ThoughtSpot groups and users. @@ -131,6 +51,7 @@ Worksheets are deprecated and replaced with Models in ThoughtSpot Cloud 10.12.0. ==== === Data modeling workflow + 1. Create a *connection* to a cloud data warehouse. 2. Import *tables* from the *connection*. 3. Create link:https://docs.thoughtspot.com/cloud/latest/models[*Models*, window=_blank] (analytic data models) based on tables. @@ -139,6 +60,7 @@ Worksheets are deprecated and replaced with Models in ThoughtSpot Cloud 10.12.0. ThoughtSpot also supports programmatic deployment of data models via link:https://docs.thoughtspot.com/cloud/latest/tml[ThoughtSpot Modeling Language (TML), window=_blank] and table import from link:https://docs.thoughtspot.com/cloud/latest/dbt-integration#integrate[dbt, window=_blank]. == Content creation + ThoughtSpot Search data creates a table or chart view based on the query in the search bar and any additional view configuration applied after the search results are displayed. Search data serves the role of report builder or widget designer, while *Liveboards* serve the role of dashboards in other tools. A single search can be saved as a link:https://docs.thoughtspot.com/cloud/latest/answers[*Answer*, window=_blank] object, or the search result can be pinned to a Liveboard. @@ -153,6 +75,7 @@ To create content: 2. Save the search result as an *Answer* or pin it to a Liveboard as a visualization. === Visualizations on a Liveboard + Any number of visualizations from search results can be added to a Liveboard object. Pinned visualizations exist only within the Liveboard and are independent of objects saved as *Answers*. Each time a search result is pinned, a separate new visualization is created on the Liveboard. @@ -166,6 +89,7 @@ To edit a visualization on a Liveboard: Visualizations on a Liveboard have their own GUIDs, but the visualization objects do not exist separately from the Liveboard object. === Tags + link:https://docs.thoughtspot.com/cloud/latest/tags[Tags, window=_blank] allow you to organize your objects and find them easily. A tag object is created by the administrator, is visible to all users, and can be assigned by any user. @@ -173,25 +97,37 @@ A tag object is created by the administrator, is visible to all users, and can b Tag search is always an *OR* operation: filtering on multiple tags results in all objects with any of the tags, not just those with all of the specified tags. == Access control (sharing) + ThoughtSpot's link:https://docs.thoughtspot.com/cloud/latest/data-security[access control model, window=_blank] works by having an `author` or `administrator` share objects with link:https://docs.thoughtspot.com/cloud/latest/groups-privileges[ThoughtSpot groups, window=_blank] or individual users: * The creator of an object is referred to as the *author*. * The author can share the object with their groups using the *Shareable* property. * The author can share the object with other users in *Shareable* groups that the *author* belongs to, and if the other *user* is also marked *Shareable*. -An administrator can share any object with any group or user without restrictions. ThoughtSpot administrators can add users locally link:https://docs.thoughtspot.com/cloud/latest/user-management[in the UI, window=_blank] or via xref:user-api.adoc[REST API]. Similarly, they can manage groups and sharing privileges by using the *Groups* feature in the UI or via REST API. +An administrator can share any object with any group or user without restrictions. ThoughtSpot administrators can add users locally link:https://docs.thoughtspot.com/cloud/latest/user-management[in the UI, window=_blank] or via xref:api-user-management.adoc[REST API v2.0]. Similarly, they can manage groups and sharing privileges by using the *Groups* feature in the UI or via xref:api-user-management.adoc[REST API v2.0]. === Single sign-on + If xref:configure-saml.adoc[SAML] or xref:configure-oidc.adoc[OpenID Connect (OIDC)] integration is enabled on your instance, users who authenticate with external identity providers (IdP) can log in to ThoughtSpot with their Single Sign-On credentials. Embedded ThoughtSpot instances also support the xref:trusted-authentication.adoc[trusted authentication] method to sign in application users. == Object properties in REST API -Object representations in the ThoughtSpot REST API include the following properties: -* `id` + +The `POST /api/rest/2.0/metadata/search` REST API v2.0 endpoint returns the following properties for each object: + +* `metadata_id` + GUID of the object. Unique within a given ThoughtSpot instance. -* `obj_id` + -User-defined string identifier for the object. Unique within a given Org. +* `metadata_obj_id` + +User-defined string identifier for the object (`obj_id`). Unique within a given Org. For more information, see xref:object-id.adoc[Object ID (obj_id)]. +* `metadata_name` + +Name of the object. +* `metadata_type` + +Object type, for example, `LIVEBOARD`. For the list of types, see <<_object_names_in_rest_api_v1,Object types in REST API v2.0>>. + +The `metadata_header` object in the response includes the following properties: + +* `id` + +GUID of the object. Same as `metadata_id`. * `author` + GUID of the user who created / uploaded the object, or had the object transferred to them. * `owner` + @@ -205,30 +141,35 @@ GUID of the user who last modified the object. * `tags` + Array of tag objects representing the tags assigned to the object. -== Object names in REST API v1 -Object type names in ThoughtSpot REST API v1 differ from the current names shown in the ThoughtSpot UI. Data objects have both a `type` and a `subtypes` field in the REST API, allowing you to request all valid data objects or specify an individual subtype. +For more information, see xref:rest-api-v2-metadata-search.adoc[Metadata search API]. + +[#_object_names_in_rest_api_v1] +== Object types in REST API v2.0 -The following notation is used in REST API v1 for object types: +Object type names in ThoughtSpot REST API v2.0 differ from the names shown in the ThoughtSpot UI. Use the following values in the `type` attribute of REST API v2.0 requests, such as `/metadata/search`: -* *Answers*: `QUESTION_ANSWER_BOOK` -* *Liveboards*: `PINBOARD_ANSWER_BOOK` -* *Connections*: `DATA_SOURCE` -* *Data objects*: `LOGICAL_TABLE`, with the following subtypes: -** *Tables*: `ONE_TO_ONE_LOGICAL` -** *Models*: `WORKSHEET` -** *Views*: `AGGR_WORKSHEET` -** *SQL views*: `SQL_VIEW` -** *CSV imported data*: `USER_DEFINED` +* *Liveboards*: `LIVEBOARD` +* *Answers*: `ANSWER` +* *Connections*: `CONNECTION` +* *Data objects*: `LOGICAL_TABLE` * *Joins*: `LOGICAL_RELATIONSHIP` * *Columns*: `LOGICAL_COLUMN` * *Tags*: `TAG` * *Users*: `USER` * *Groups*: `USER_GROUP` +* *Collections*: `COLLECTION` -Column and join objects with their own GUIDs do exist within the ThoughtSpot system, but they are connected to *Tables*, *Models*, or other data objects. Columns and joins can be viewed or modified only within the context of the data object to which they belong. +For the `LOGICAL_TABLE` type, you can also specify the following values in the `subtypes` attribute to filter the results: -== Related resources +* *Tables*: `ONE_TO_ONE_LOGICAL` +* *Models*: `WORKSHEET` +* *Private Models*: `PRIVATE_WORKSHEET` +* *Views*: `AGGR_WORKSHEET` +* *SQL Views*: `SQL_VIEW` +* *CSV imported data*: `USER_DEFINED` -* link:https://docs.thoughtspot.com/home/[ThoughtSpot product documentation, window=_blank] +Column and join objects with their own GUIDs do exist within the ThoughtSpot system, but they are connected to *Tables*, *Models*, or other data objects. Columns and joins can be viewed or modified only within the context of the data object to which they belong. +== Related resources +* link:https://docs.thoughtspot.com/home/[ThoughtSpot product documentation, window=_blank] \ No newline at end of file diff --git a/modules/ROOT/pages/link-customization-api.adoc b/modules/ROOT/pages/link-customization-api.adoc new file mode 100644 index 000000000..e1de2fbb8 --- /dev/null +++ b/modules/ROOT/pages/link-customization-api.adoc @@ -0,0 +1,315 @@ += Link Customization APIs +:toc: true +:toclevels: 2 + +:page-title: Link Customization APIs +:page-pageid: link-customization-api +:page-description: Use the Link Customization REST API v2 endpoints to manage the URL templates ThoughtSpot uses when generating shareable links. +:keywords: link customization, shareable links, URL templates, share link, embedded application, REST API + +ThoughtSpot generates shareable links for Liveboards, Answers, visualizations, SpotIQ insights, Spotter conversations, and other objects. These links appear in scheduled emails, the Share dialog, and alert notifications. + +By default, shareable links point to your ThoughtSpot instance. If you embed ThoughtSpot in your own application, you can use the link customization REST API v2 endpoints to redirect these links to your application. When a user clicks a shared link, they are directed to your embedding application instead of the ThoughtSpot application. + + +== Link customization workflow +Each link type has a URL template with placeholders that ThoughtSpot replaces with the object details when it generates a link. To customize the links: + +. <> + +Call `POST /api/rest/2.0/customization/links/search` to view the templates in effect at the cluster level or for your Org. +. <> + +Call `POST /api/rest/2.0/customization/links/update` with the `REPLACE` operation to set a template, or with the `RESET` operation to clear an override. + +=== Scopes +You can manage the templates at the following scopes: + +* `CLUSTER`: Sets the default templates that all Orgs inherit. +* `ORG`: Sets the templates for the caller's Org and overrides the default settings. Requires Orgs to be enabled on your instance. + +Cluster-level templates are available only to callers in the primary Org. If an Org does not set its own template for a link type, it inherits the cluster template. If the cluster does not set one either, ThoughtSpot uses its default template. + +=== Required privileges +To use the Link Customization APIs, the user requires one of the following privileges: + +* `ADMINISTRATION` (**Can administer ThoughtSpot**) +* `DEVELOPER` (**Has developer privilege**) + +Authenticate API requests with a bearer token. For information about obtaining a token, see xref:authentication.adoc[REST API v2 authentication]. + +[#search-link-customizations] +== Searching link customizations +The `/api/rest/2.0/customization/links/search` API endpoint retrieves the URL templates that ThoughtSpot uses to generate shareable links, at the cluster level or for the Org that the caller is signed in to. Use this endpoint to verify what an Org has customized before you modify it, or to confirm the destination URLs used in scheduled emails and the Share dialog. + +Cluster-level templates are the default that Orgs inherit. Org-level templates override that default. + +=== Request parameters +[cols="2,4", options="header"] +|=== +|Parameter | Description +| `scope` +a|__String__. Optional. The scope to retrieve: + +* `CLUSTER` returns the cluster templates. Available only to callers in the primary Org. +* `ORG` returns the templates for the Org that the caller is signed in to. Requires Orgs to be enabled. + +If you omit the parameter, the API returns whichever of these scopes the caller can access. +|=== + +=== Example request + +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/customization/links/search' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{}' +---- + +=== Example response +If the API request is successful, the API returns an array of link preferences, one for each scope. + +[source,JSON] +---- +[ + { + "scope": "CLUSTER", + "org": null, + "templates": [ + { + "type": "LIVEBOARD_SHARE_URL", + "value": "https://mysite.com/#/pinboard/{object-id}?{ts-query-params}", + "is_overridden": true + }, + { + "type": "VISUALIZATION_SHARE_URL", + "value": "https://mysite.com/#/pinboard/{object-id}/{sub-object-id}?{ts-query-params}", + "is_overridden": true + }, + { + "type": "ANSWER_SHARE_URL", + "value": "https://mysite.com/#/saved-answer/{object-id}?{ts-query-params}", + "is_overridden": true + }, + { + "type": "SPOTIQ_ANALYSIS_URL", + "value": "https://mysite.com/#/insight/{object-id}", + "is_overridden": true + }, + { + "type": "UNSUBSCRIBE_URL", + "value": "https://mysite.com/#/user-preference", + "is_overridden": true + }, + { + "type": "GENERIC_URL", + "value": "https://mysite.com/#/{path}", + "is_overridden": true + }, + { + "type": "CONVERSATION_SHARE_URL", + "value": "https://{ThoughtSpot-Host}/#/insights/conv-assist/s/{conversation-id}?{ts-query-params}", + "is_overridden": false + } + ] + }, + { + "scope": "ORG", + "org": { + "id": 12345, + "name": "Org1" + }, + "templates": [ + { + "type": "LIVEBOARD_SHARE_URL", + "value": "https://org1-mysite.com/#/pinboard/{object-id}?{ts-query-params}", + "is_overridden": true + }, + { + "type": "VISUALIZATION_SHARE_URL", + "value": "https://org1-mysite.com/#/pinboard/{object-id}/{sub-object-id}?{ts-query-params}", + "is_overridden": true + }, + { + "type": "ANSWER_SHARE_URL", + "value": "https://org1-mysite.com/#/saved-answer/{object-id}?{ts-query-params}", + "is_overridden": true + }, + { + "type": "SPOTIQ_ANALYSIS_URL", + "value": "https://org1-mysite.com/#/insight/{object-id}", + "is_overridden": true + }, + { + "type": "UNSUBSCRIBE_URL", + "value": "https://org1-mysite.com/#/user-preference", + "is_overridden": true + }, + { + "type": "GENERIC_URL", + "value": "https://org1-mysite.com/#/{path}", + "is_overridden": true + }, + { + "type": "CONVERSATION_SHARE_URL", + "value": "https://org1-mysite.com/#/insights/conv-assist/s/{conversation-id}?{ts-query-params}", + "is_overridden": true + } + ] + } +] +---- + +=== Response parameters +[cols="2,4", options="header"] +|=== +| Parameter | Description +| `scope` | Indicates whether the link customization changes are applied globally (`CLUSTER`) or for an individual Org (`ORG`). +| `org` | The Org that the link templates belong to. Includes the `id` and `name` of the Org. The value is `null` when `scope` is `CLUSTER`. +| `templates` +a| The effective URL template for every link type at this scope. Each entry includes the following attributes: + +* `type`: The link type. For the list of supported types, see <>. +* `value`: The effective URL template at the requested scope. +* `is_overridden`: `true` when the scope stores a value that differs from the value it would otherwise inherit. For `ORG`, the inherited value is the cluster template. For `CLUSTER`, it is the ThoughtSpot default. The value is `false` when they match. +|=== + +[#update-link-customizations] +== Updating link customizations +The `/api/rest/2.0/customization/links/update` API endpoint updates the URL templates that ThoughtSpot uses to generate shareable links, at the cluster level or for the Org that the caller is signed in to. Use this endpoint to point shared links to your embedding application, so that a link in a scheduled email or the Share dialog opens your page instead of the ThoughtSpot application. + +=== Request parameters +[cols="2,4", options="header"] +|=== +|Parameter | Description +| `scope` +a|__String__. Optional. The scope to apply the templates at: + +* `ORG` (default) updates the templates for the Org that the caller is signed in to. Requires Orgs to be enabled. +* `CLUSTER` updates the defaults that all Orgs inherit. Available only to callers in the primary Org. +| `operation` +a|__String__. Optional. The operation to perform: + +* `REPLACE` (default) sets each listed link type to the `value` provided in the request. +* `RESET` clears each listed link type, so an Org falls back to the cluster template and the cluster falls back to the ThoughtSpot default. +| `templates` +a|__Array of objects__. The link types to update. At least one entry is required. For each entry, specify the following attributes: + +* `type`. __String__. The link type. For the list of supported types, see <>. +* `value`. __String__. The URL template, including the placeholders that the link type requires. Required for `REPLACE`. Do not specify it for `RESET`. +|=== + +=== Update behavior +* This is a partial update. Only the link types listed in `templates` change. All other link types keep their current value, whether it is set at this scope or inherited. +* The API rejects a template that doesn't include the placeholders required for its link type. For more information, see <>. +* The API rejects a request that includes the same link type more than once. +* The API rejects a request that includes a `value` with the `RESET` operation. +* To clear every override, list all link types with the `RESET` operation. +* Resetting at the cluster level changes only the cluster default. An Org that has set its own value keeps it. + +[#link-types] +=== Supported link types and placeholders +Each link type requires specific placeholders in its URL template. ThoughtSpot rejects a template that does not include the required placeholders. + +[cols="2,3,2,3", options="header"] +|=== +|Link type | Used for | Required placeholders | Example template +| `LIVEBOARD_SHARE_URL` +| Links to a Liveboard in share and scheduled job notifications. +| `{object-id}`, `{ts-query-params}` +| `\https://www.mysite.com/dashboards/{object-id}?{ts-query-params}` +| `VISUALIZATION_SHARE_URL` +| Links to a visualization on a Liveboard. +| `{object-id}`, `{sub-object-id}`, `{ts-query-params}` +| `\https://www.mysite.com/dashboards/{object-id}/charts/{sub-object-id}?{ts-query-params}` +| `ANSWER_SHARE_URL` +| Links to a saved Answer in share notifications. +| `{object-id}`, `{ts-query-params}` +| `\https://www.mysite.com/answers/{object-id}?{ts-query-params}` +| `SPOTIQ_ANALYSIS_URL` +| Links to a SpotIQ analysis. +| `{object-id}` +| `\https://www.mysite.com/insights/{object-id}` +| `UNSUBSCRIBE_URL` +| The *Unsubscribe* link in notification emails. +| None +| `\https://www.mysite.com/account/email-preferences` +| `GENERIC_URL` +| Navigation links and pages that the other link types don't cover. +| `{path}` +| `\https://www.mysite.com/{path}` +| `CONVERSATION_SHARE_URL` +| Links to a shared Spotter conversation. +| `{conversation-id}`, `{ts-query-params}` +| `\https://www.mysite.com/spotter/{conversation-id}?{ts-query-params}` +|=== + +The placeholders are replaced as follows: + +* `{object-id}`: The GUID of the Liveboard, Answer, or SpotIQ analysis. +* `{sub-object-id}`: The GUID of the visualization. +* `{conversation-id}`: The ID of the shared Spotter conversation. +* `{path}`: The ThoughtSpot application page path. +* `{ts-query-params}`: The query parameters that ThoughtSpot passes in the link, for example, the parameters required to unsubscribe from an alert. + +`{ts-query-params}` is optional for any link type that does not require it. ThoughtSpot substitutes it wherever it appears and removes it when there is nothing to substitute, so it never appears in a generated link. + +=== Example request + +.Replace a template +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/customization/links/update' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{ + "scope": "ORG", + "operation": "REPLACE", + "templates": [ + { + "type": "LIVEBOARD_SHARE_URL", + "value": "https://www.mysite.com/dashboards/{object-id}?{ts-query-params}" + } + ] +}' +---- + +.Reset a template +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/customization/links/update' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{ + "scope": "ORG", + "operation": "RESET", + "templates": [ + { + "type": "LIVEBOARD_SHARE_URL" + } + ] +}' +---- + +=== Response codes +If the API request is successful, the API returns `204 No Content` without a response body. + +[cols="1,3", options="header"] +|=== +| HTTP status code | Description +| **204** | Link preferences updated successfully. +| **400** | Invalid request. For example, a template is missing a required placeholder, a link type is repeated, or a `value` is supplied with `RESET`. +| **401** | Authentication token is missing, expired, or invalid. +| **403** | The caller does not have the required privilege. +| **500** | Unexpected server error. +|=== + +== Additional resources + +* xref:rest-api-v2-reference.adoc#_link_customization[REST API v2.0 Reference] +* xref:rest-apiv2-changelog.adoc[REST API v2.0 changelog] +* +++REST API Playground - Search link customizations endpoint+++ +* +++REST API Playground - Update link customizations endpoint+++ diff --git a/modules/ROOT/pages/locale-setting.adoc b/modules/ROOT/pages/locale-setting.adoc index d9a40fa16..d134c696f 100644 --- a/modules/ROOT/pages/locale-setting.adoc +++ b/modules/ROOT/pages/locale-setting.adoc @@ -43,11 +43,15 @@ If you want to set your embedded app view to a specific locale for your applicat | `it-IT` | Italiano | `nb-NO` | Norsk | `nl-NL` | Nederland +| `pl-PL` | Polski | `pt-BR` | Português (Brasil) | `pt-PT` | Português (Portugal) | `ru-RU` | Pусский (ограниченный выпуск) +| `ro-RO` | Română | `fi-FI` | Suomi | `sv-SE` | Svenska +| `tr-TR` | Türkçe +| `uk-UA` | Українська | `zh-CN` | 中文(简体) | `zh-HANT`| 中文 (繁體) |==================== diff --git a/modules/ROOT/pages/object-id-in-urls.adoc b/modules/ROOT/pages/object-id-in-urls.adoc new file mode 100644 index 000000000..1f338c7b7 --- /dev/null +++ b/modules/ROOT/pages/object-id-in-urls.adoc @@ -0,0 +1,125 @@ += Object ID in ThoughtSpot URLs +:toc: true +:toclevels: 2 + +:page-title: Object ID in ThoughtSpot URLs +:page-pageid: object-id-urls +:page-description: Learn how to use a stable, user-defined Object ID (obj_id) instead of a globally unique identifier (GUID) in ThoughtSpot Liveboard, Answer, Collection, data object, and connection URLs. Use an Object ID (obj_id) instead of a GUID in ThoughtSpot URLs so that deep links work in every environment + +You can use an object's xref:object-id.adoc[Object ID] (`obj_id`) in place of its GUID in a ThoughtSpot URL. Because you assign the same `obj_id` to an object in every environment, a URL built with an `obj_id` opens the correct object in development, staging, and production. + +== When to use Object ID in URLs + +GUIDs are generated separately on each ThoughtSpot instance and in each Org. When content is promoted from one environment to another, every object gets a new GUID, so any URL built with a GUID works only in the environment where it was created. Without Object ID, embedded applications and deployment pipelines have to maintain a GUID mapping table for each environment and update it after every deployment. + +Use `obj_id` in URLs if: + +* Your host application builds ThoughtSpot URLs or deep links programmatically. +* You promote content across environments by using TML or a CI/CD pipeline. +* You want links to keep working after content is redeployed. + +With `obj_id`, you assign a stable identifier to an object once and use it in every environment. + +== Before you begin + +* Object ID must be enabled on your instance. For more information, see xref:object-id.adoc#_enable_object_id[Enable Object ID]. +* The objects you want to link to must have an `obj_id`. Objects created before Object ID was enabled do not have an `obj_id` until one is assigned or generated. For more information, see xref:object-id.adoc#_how_objects_get_an_obj_id[How objects get an obj_id]. + +== Enable Object ID in URLs + +Object ID in URLs is disabled by default and there is no setting for it in the ThoughtSpot UI. To enable it on your instance, contact ThoughtSpot Support. The feature is enabled without a restart. + +[NOTE] +==== +Enabling this feature affects only URLs. Object ID in REST APIs and TML works independently of this setting. +==== + +== Supported URLs + +You can use an `obj_id` in place of the GUID in the following URLs: + +[cols="2,4", options="header"] +|=== +|Object |URL format + +|Liveboard |`https://{ThoughtSpot-host}/#/insights/pinboard/{id}` +|Answer |`https://{ThoughtSpot-host}/#/insights/answer/{id}` +|Collection |`https://{ThoughtSpot-host}/insights/collections/{id}` + +In nested collection paths, each segment is resolved separately. +|Model, Worksheet, Table, or View |`https://{ThoughtSpot-host}/#/data/tables/{id}` +|Connection |`https://{ThoughtSpot-host}/#/data/embrace/{id}` +|=== + +In each URL, `{id}` can be either the object's GUID or its `obj_id`. Both formats are accepted on the same URLs. + +=== Example + +A Liveboard URL with a GUID differs in each environment: + +[source,text] +---- +https://{ThoughtSpot-host}/#/insights/pinboard/a3f9c2e1-7b44-4d8e-9f10-6c2b5e8d1a07 +---- + +The same Liveboard URL with an `obj_id` is identical in development, staging, and production: + +[source,text] +---- +https://{ThoughtSpot-host}/#/insights/pinboard/sales-weekly-performance +---- + +== How ThoughtSpot resolves the identifier in a URL + +ThoughtSpot resolves the identifier in a URL on the server, in the following order: + +. *GUID first.* If the identifier is a GUID that matches an existing object of the expected type, ThoughtSpot opens that object. An `obj_id` can never override a valid GUID. +. *Object ID.* Otherwise, ThoughtSpot looks up the identifier as an `obj_id` in the current user's Org. +. *Type check.* If the `obj_id` belongs to an object of a different type, for example, a Model `obj_id` in a Liveboard URL, the object is not opened. + +[IMPORTANT] +==== +Object names are never resolved in URLs. Only the GUID or the `obj_id` of an object can be used. +==== + +== Unsupported objects + +The following objects do not have a URL in ThoughtSpot, so `obj_id` cannot be used to open them in a URL. You can still reference them by `obj_id` through the REST APIs. + +* Groups +* Roles +* Custom actions +* Columns +* Personalized Views +* Visualizations and tabs within a Liveboard + + +//// +== Backward compatibility + +* All existing GUID-based URLs, bookmarks, and saved links continue to work. +* There is no breaking change to the Visual Embed SDK public API. +* You can adopt `obj_id` gradually. For example, you can move high-value deep links to `obj_id` and keep using GUIDs for other links. +//// + +[IMPORTANT] +==== +* If you change an object's `obj_id`, URLs that use the previous value no longer resolve. Update any links that use the old value. +* `obj_id` values are unique within an Org. The same `obj_id` in two Orgs opens a different object in each Org. +==== + +== Troubleshooting + +An obj_id in a URL returns an invalid identifier error (HTTP 400):: +Object ID in URLs is not enabled on your instance, or the object type is not supported in URLs. If the same `obj_id` works in REST API requests, the URL feature is not enabled. Contact ThoughtSpot Support to enable it. This is a configuration setting, not a defect. + +The URL opens a different object than expected:: +The `obj_id` is resolved in the Org of the user who opens the URL. Make sure the user is in the Org where the `obj_id` was set. + +An obj_id in GUID format does not resolve:: +A value in GUID format is always tried as a GUID first. If a real object has that GUID, that object is opened. Assign the object an `obj_id` that is not in GUID format. + +== Related resources + +* xref:object-id.adoc[Object ID (obj_id)] +* xref:intro-thoughtspot-objects.adoc[ThoughtSpot objects] +* xref:development-and-deployment.adoc[Development and deployment] \ No newline at end of file diff --git a/modules/ROOT/pages/object-id.adoc b/modules/ROOT/pages/object-id.adoc new file mode 100644 index 000000000..60f23204a --- /dev/null +++ b/modules/ROOT/pages/object-id.adoc @@ -0,0 +1,302 @@ += Object ID (obj_id) +:toc: true +:toclevels: 2 + +:page-title: Object ID (obj_id) +:page-pageid: object-id +:page-description: Learn how to set and use a stable, user-defined Object ID (obj_id) to identify ThoughtSpot objects consistently across instances, Orgs, and environments. Use Object ID (obj_id) to reference ThoughtSpot objects by a stable, user-defined identifier across Orgs and instances + +Every object in ThoughtSpot has a system-generated GUID. GUIDs are minted per instance, so the same Liveboard promoted from a development environment to a production environment has a different GUID in each one. + +An Object ID (`obj_id`) is a customer-defined, human-readable identifier that you assign to an object in addition to its GUID. An `obj_id` survives renames, TML export and import, and moves between Orgs and instances. Because you choose the value, related copies of an object in different Orgs can share the same `obj_id`, and your deployment scripts, Git-based CI/CD pipelines, and host application can reference the object without maintaining a GUID mapping for each environment. + +Object ID is generally available from ThoughtSpot Cloud 26.9.0.cl. + +== Overview + +* `obj_id` is *user-settable* and *unique per Org*. Each Org can have only one object with a particular `obj_id`. +* The combination of Org ID and `obj_id` is the uniqueness key, so the same `obj_id` in two Orgs refers to two different objects. This is by design. +* The `obj_id` of an object is returned as `metadata_obj_id` in the `POST /api/rest/2.0/metadata/search` API response, and as `obj_id` in TML. +* Object ID is the key that TML-based deployment, xref:publishing-overview.adoc[publishing], and xref:git-provider-integration.adoc[Git provider integration] build on. + +== Enable Object ID + +Object ID must be enabled on your ThoughtSpot instance before `obj_id` participates in TML export, TML import, and metadata search. Until it is enabled, ThoughtSpot continues to resolve objects by GUID and name. + +To use `obj_id` in ThoughtSpot URLs, an additional setting is required. For more information, see xref:object-id-in-urls.adoc[Object ID in ThoughtSpot URLs]. + +== Supported object types + +The following object types support `obj_id`: + +[cols="2,4", options="header"] +|=== +|Object type |In TML + +|Liveboard |`liveboard` + +Exported in TML and resolved first on import. +|Answer |`answer` +|Model |`model` + +Includes Worksheets. +|Table |`table` +|SQL View |`sql_view` +|Column |None + +Supported on columns within Tables and Models. +|Connection |`connection` +|Collection |None +|Custom action |None + +Supported for custom actions managed through the API or the server. +|Personalized View |None + +For information about importing Personalized Views with `obj_id`, see xref:tml-import.adoc[TML import]. +|Variable |None + +Supported from 26.10.0.cl. Template variables can also reference Object IDs from 26.10.0.cl. +|Memory |None + +Carries an Object ID through the Model it is tagged to. +|Group |None +|Role |None +|=== + +[IMPORTANT] +==== +The `obj_id` field appears in the TML of every object kind, but TML import honors it only for the supported object types. The presence of `obj_id` in a TML file does not mean that the object type supports Object ID. +==== + +=== Objects that do not support obj_id + +The following objects do not have an `obj_id`: + +[cols="2,5", options="header"] +|=== +|Object |Behavior + +|Visualization on a Liveboard +|In TML, a visualization is identified only by `viz_guid`. Objects that reference a visualization, such as Monitor alerts, Liveboard schedules, and related links, depend on a GUID that differs between Orgs. + +|Liveboard tab +|A tab is identified only by its `id`, which is a GUID. + +|Monitor alert (KPI alert) +|The alert has no `obj_id` of its own. Its TML includes `pinboard_obj_id` and `answer_obj_id`, which resolve on import, but the visualization reference is a GUID that must already exist in the target environment. + +|Schedule +|Liveboard schedules reference visualizations through `included_viz_id`, which is a GUID. + +|Webhook +|The `obj_id` field is present in webhook TML but is ignored on import. + +|Parameter +|Parameters have no `obj_id` and do not migrate by name. + +|Semantic integration +|Semantic integrations have no `obj_id` and do not migrate by name. + +|User +|Users are identified by name in TML and migrate without an `obj_id`. + +|Tag +|Tags are identified by name in TML and migrate without an `obj_id`. + +|Org +|Orgs are part of the uniqueness key (Org ID + `obj_id`), so they do not have an `obj_id` themselves. +|=== + +=== TML kinds that ignore obj_id on import + +The `obj_id` field is present in the following TML kinds but is ignored during import: + +* `Join` +* `user_object` +* `webhook` +* `column_security_rules` +* `nl_instruction` +* `column_alias` +* `nls_feedback` +* `cohort` +* `monitor_alert` + +== obj_id format and constraints + +An `obj_id` value must meet the following requirements: + +[cols="2,4", options="header"] +|=== +|Constraint |Requirement + +|Length |1 to 64 characters +|Allowed characters |Letters, digits, and the special characters hyphen (`-`), underscore (`_`), period (`.`), and tilde (`~`). Spaces are not allowed. +|Uniqueness |Unique within an Org +|=== + +*Valid examples:* `sales-weekly-performance`, `finance_ledger.prod`, `retail~kpis-v2` + +[TIP] +==== +Do not use a value that has the same format as a GUID. When ThoughtSpot resolves an identifier in a URL, a GUID-shaped value is always tried as a GUID first, so a GUID-shaped `obj_id` might not resolve as expected. +==== + +== How objects get an obj_id + +* New objects are assigned an `obj_id` when they are created. +* Objects that existed before Object ID was enabled are not assigned an `obj_id` retroactively. They receive an automatically generated `obj_id` the first time the object is updated or imported through TML. +* You can assign or change the `obj_id` of any supported object at any time. For more information, see <<_setting_and_updating_obj_id,Setting and updating obj_id>>. + +An automatically generated `obj_id` appends the first segment of the object's GUID to the object name. For example, `RetailSalesRAD-KPIs-c1e4043a`. If the `metadata_obj_id` property in the `/metadata/search` API response is `null`, the object has not been updated since Object ID was enabled. + +== obj_id resolution + +How ThoughtSpot resolves an identifier depends on where you use it. + +=== REST API endpoints + +When an identifier is passed to a REST API v2.0 endpoint that accepts an `object_identifier`, ThoughtSpot resolves it in the following order: + +. `obj_id` +. GUID +. Name + +This allows `obj_id` to be used anywhere a GUID or name is accepted in those fields. Existing integrations that use GUIDs or names continue to work. + +The `POST /api/rest/2.0/metadata/search` endpoint and the metadata update endpoints also accept an `obj_identifier` field. When you use `obj_identifier`, ThoughtSpot resolves the value strictly as an `obj_id`, without falling back to the object name. + +In the `/metadata/search` API, `obj_identifier` is supported for the following object types: + +* `LIVEBOARD` +* `ANSWER` +* `LOGICAL_TABLE` +* `LOGICAL_COLUMN` +* `CONNECTION` +* `USER_GROUP` +* `COLLECTION` + +Other object types, such as Roles and Personalized Views, can have an `obj_id`, but you cannot search for them by `obj_identifier`. To find these objects, search by GUID or name and read the `metadata_obj_id` value in the response. + +=== TML import + +During TML import, ThoughtSpot matches the TML to an existing object in the following order: + +. `obj_id` +. GUID +. Name + +If the `obj_id` in the TML does not match any object in the target Org, ThoughtSpot falls back to the GUID in the TML and updates that object. The import returns a `WARNING` status in this case. It does not create a duplicate object or fail the import. + +=== ThoughtSpot URLs + +In ThoughtSpot URLs, a GUID is always tried first, and object names are never resolved. For more information, see xref:object-id-in-urls.adoc[Object ID in ThoughtSpot URLs]. + +[NOTE] +==== +`obj_id` resolution is always scoped to the Org of the user making the request. The Org ID + `obj_id` combination uniquely identifies an object across the entire ThoughtSpot instance. +==== + +== Setting and updating obj_id + +You can set or change the `obj_id` of an object by using the REST API or by editing the object's TML. + +=== Using the update-obj-id API + +The `POST /api/rest/2.0/metadata/update-obj-id` endpoint updates the `obj_id` of one or more objects. The endpoint uses the metadata header update mechanism to apply the change. + +Required privileges:: +`DATAMANAGEMENT` (*Can manage data*) or `ADMINISTRATION` (*Can administer ThoughtSpot*). If Role-Based Access Control (RBAC) is enabled, the `ORG_ADMINISTRATION` (*Can manage Orgs*) privilege is also required. + +Request parameters:: +For each object in the `metadata` array: ++ +* Identify the object by using either `current_obj_id` alone, or `metadata_identifier`. +* `metadata_identifier` accepts the object's GUID or name. If you use the name, you must also specify the object `type`, for example, `ANSWER` or `LOGICAL_TABLE`. +* `new_obj_id` is always required. The value must follow the xref:object-id.adoc#_obj_id_format_and_constraints[obj_id format] and be unique within the Org. + +[TIP] +==== +Before updating Object IDs, export the TML of the objects as a backup. +==== + +Using the GUID: + +[source,json] +---- +{ + "metadata": [ + { + "metadata_identifier": "c1e4043a-4524-4fcb-a20f-9e7aff4dc972", + "new_obj_id": "sales-pipeline-v1" + } + ] +} +---- + +Using the current `obj_id`: + +[source,json] +---- +{ + "metadata": [ + { + "current_obj_id": "sales-pipeline-v1-c1e4043a", + "new_obj_id": "sales-pipeline-v1" + } + ] +} +---- + +Using the object name and type: + +[source,json] +---- +{ + "metadata": [ + { + "metadata_identifier": "Sales Pipeline", + "type": "ANSWER", + "new_obj_id": "sales-pipeline-answer" + } + ] +} +---- + +The request accepts an array, so you can update multiple objects in a single API call. Each object in the array can use a different identification method: + +[source,json] +---- +{ + "metadata": [ + { + "current_obj_id": "retail-kpis-c1e4043a", + "new_obj_id": "retail-kpis" + }, + { + "metadata_identifier": "Sales Model", + "type": "LOGICAL_TABLE", + "new_obj_id": "sales-model" + } + ] +} +---- + +=== Using the metadata headers update API + +The `POST /api/rest/2.0/metadata/headers/update` endpoint also sets the `obj_id` in an object's header. From 26.10.0.cl, this endpoint and the `update-obj-id` endpoint support the `ROLE` and `TEMPLATE_VARIABLE` types. + +=== Using TML + +Set the `obj_id` property in the object's TML and import the TML. For examples, see xref:deploy-with-tml-apis.adoc[Deploy with TML APIs]. + +== Behavior and limitations + +Renaming an obj_id:: +After you change an object's `obj_id`, the previous value no longer resolves. Integrations, scripts, and URLs that use the old value must be updated to use the new value. + +Org scope:: +The same `obj_id` in two Orgs resolves to two different objects. Make sure requests are made in the context of the Org where the `obj_id` is set. + +Delete operations:: +The `POST /api/rest/2.0/metadata/delete` endpoint does not accept `obj_identifier`. Use GUIDs when deleting objects in automation scripts. + +== Related resources + +* xref:object-id-in-urls.adoc[Object ID in ThoughtSpot URLs] +* xref:intro-thoughtspot-objects.adoc[ThoughtSpot objects] +* xref:development-and-deployment.adoc[Development and deployment] +* xref:deploy-with-tml-apis.adoc[Deploy with TML APIs] +* xref:tml-import.adoc[TML import] \ No newline at end of file diff --git a/modules/ROOT/pages/rest-api-csharp-sdk.adoc b/modules/ROOT/pages/rest-api-csharp-sdk.adoc index 449797186..d1aca41fc 100644 --- a/modules/ROOT/pages/rest-api-csharp-sdk.adoc +++ b/modules/ROOT/pages/rest-api-csharp-sdk.adoc @@ -323,6 +323,7 @@ await api.ApplyConfigurationAsync(newConfig); [options="header"] |==== |ThoughtSpot release|Recommended SDK version +|ThoughtSpot Cloud: 26.11.0.cl|v2.30.0 or later |ThoughtSpot Cloud: 26.10.0.cl|v2.29.1 or later |ThoughtSpot Cloud: 26.9.0.cl|v2.28.0 or later |ThoughtSpot Cloud 26.8.0.cl|v2.27.1 or later diff --git a/modules/ROOT/pages/rest-api-java-sdk.adoc b/modules/ROOT/pages/rest-api-java-sdk.adoc index 3bb0c4b93..be19ae4ae 100644 --- a/modules/ROOT/pages/rest-api-java-sdk.adoc +++ b/modules/ROOT/pages/rest-api-java-sdk.adoc @@ -281,6 +281,7 @@ Note the recommendation of Java SDK: [options='header'] |==== |ThoughtSpot release version|Supported SDK version +|ThoughtSpot Cloud: 26.11.0.cl|v2.30.0 or later |ThoughtSpot Cloud: 26.10.0.cl|v2.29.1 or later |ThoughtSpot Cloud: 26.9.0.cl|v2.28.0 or later |ThoughtSpot Cloud: 26.8.0.cl|v2.27.1 or later diff --git a/modules/ROOT/pages/rest-api-python-sdk.adoc b/modules/ROOT/pages/rest-api-python-sdk.adoc index 9054b0a94..3192de84c 100644 --- a/modules/ROOT/pages/rest-api-python-sdk.adoc +++ b/modules/ROOT/pages/rest-api-python-sdk.adoc @@ -373,6 +373,7 @@ on every request. [options='header'] |==== |ThoughtSpot release version|Recommended SDK version +|ThoughtSpot Cloud: 26.11.0.cl|v2.30.0 or later |ThoughtSpot Cloud: 26.10.0.cl|v2.29.1 or later a|ThoughtSpot Cloud: 26.9.0.cl|v2.28.0 or later a|ThoughtSpot Cloud: 26.8.0.cl | v2.27.1 or later diff --git a/modules/ROOT/pages/rest-api-sdk-typescript.adoc b/modules/ROOT/pages/rest-api-sdk-typescript.adoc index 5951dd7e2..3f4352a16 100644 --- a/modules/ROOT/pages/rest-api-sdk-typescript.adoc +++ b/modules/ROOT/pages/rest-api-sdk-typescript.adoc @@ -201,6 +201,7 @@ const test = async () => { [options='header'] |==== |ThoughtSpot release version|Recommended SDK version +|ThoughtSpot Cloud: 26.11.0.cl|v2.30.0 or later |ThoughtSpot Cloud: 26.10.0.cl|v2.29.1 or later |ThoughtSpot Cloud: 26.9.0.cl|v2.28.0 or later |ThoughtSpot Cloud: 26.8.0.cl|v2.27.1 or later diff --git a/modules/ROOT/pages/rest-api-v1v2-comparison.adoc b/modules/ROOT/pages/rest-api-v1v2-comparison.adoc index a48eacdcb..020e44e9c 100644 --- a/modules/ROOT/pages/rest-api-v1v2-comparison.adoc +++ b/modules/ROOT/pages/rest-api-v1v2-comparison.adoc @@ -106,13 +106,13 @@ Includes the following subtypes: * `DATA_SOURCE` for data source objects * `USER` for user objects * `USER_GROUP` for user group objects -* `LOGICAL_COLUMN` for a column of any data object such as tables, worksheets, or views -* `LOGICAL_RELATIONSHIP` for table or worksheet joins +* `LOGICAL_COLUMN` for a column of any data object such as tables, models, or views +* `LOGICAL_RELATIONSHIP` for table or model joins + The `LOGICAL_COLUMN` and `LOGICAL_RELATIONSHIP` metadata types include the following subtypes: -** `FORMULA` to query a list of formulas applied to a worksheet column + -** `CALENDAR_TYPE` to query the type of calendar used by the DATE TYPE column in a worksheet + +** `FORMULA` to query a list of formulas applied to a model column + +** `CALENDAR_TYPE` to query the type of calendar used by the DATE TYPE column in a model + ** `CALENDAR_TABLE` to query columns that have a custom calendar configured a| Metadata object types in REST API v2.0: @@ -122,9 +122,9 @@ a| Metadata object types in REST API v2.0: * `TAG` for tag objects * `USER` for user objects * `USER_GROUP` for groups -* `LOGICAL_TABLE` for Table, Worksheet, or View. -* `LOGICAL_COLUMN` for a column of any data object such as tables, worksheets, or views. -* `LOGICAL_RELATIONSHIP` for table and worksheet joins +* `LOGICAL_TABLE` for Table, model, or view. +* `LOGICAL_COLUMN` for a column of any data object such as tables, models, or views. +* `LOGICAL_RELATIONSHIP` for table and model joins _Querying metadata objects by subtypes is not supported in the current release_. diff --git a/modules/ROOT/pages/rest-api-v2-metadata-search.adoc b/modules/ROOT/pages/rest-api-v2-metadata-search.adoc index d0dffee50..7dea843a5 100644 --- a/modules/ROOT/pages/rest-api-v2-metadata-search.adoc +++ b/modules/ROOT/pages/rest-api-v2-metadata-search.adoc @@ -44,7 +44,7 @@ If you do not send specific object IDs as part of your request, the API lists al For information about the supported object types, see link:https://developers.thoughtspot.com/docs/restV2-playground?apiResourceId=http%2Fmodels%2Fenumerations%2Ftype-3[API Playground]. === Subtypes for LOGICAL_TABLE -For metadata types such as Models, Tables, and Views, set the `type` to `LOGICAL_TABLE`. When `type` is set as `LOGICAL_TABLE` and no object identifier is specified in the request, the API returns all available objects in ThoughtSpot. To get a complete list of `LOGICAL_TABLE` objects, set the `record_size` attribute to a desired value and configure xref:rest-api-v2-metadata-search.adoc#_pagination_settings[pagination settings]. +For metadata types such as Models, Tables, and Views, set the `type` to `LOGICAL_TABLE`. When `type` is set as `LOGICAL_TABLE` and no object identifier is specified in the request, the API returns all available objects in ThoughtSpot. To get a complete list of `LOGICAL_TABLE` objects, set the `record_size` attribute to a desired value and configure xref:rest-api-v2-metadata-search.adoc#_pagination_settings_for_metadata_objects[pagination settings]. For `LOGICAL_TABLE` object type, you can also specify the subtype as an additional option to filter API response. You can specify one of the following values to define the `LOGICAL_TABLE` subtype: @@ -3926,6 +3926,56 @@ Common use cases for the dependent objects include tagging, auditing proper shar The `dependent_object_version` parameter specifies the version of the dependent object information in the response. The only supported value is `V1`. +==== Pagination settings for dependent objects + +When `include_dependent_objects` is set to `true`, you can paginate the dependent objects returned for each metadata object specified in the API request. These settings apply only to dependent objects. To paginate the metadata objects returned in the response, use the xref:rest-api-v2-metadata-search.adoc#_pagination_settings_for_metadata_objects[pagination settings for metadata objects]. Use the following parameters to control pagination of dependent objects: + +* `dependent_objects_record_offset` + +_Request parameter_. Number of dependent objects to skip for each metadata object before collecting them. Use this parameter with `dependent_objects_record_size`, which sets the page size. The default page size is `50`. If you specify an offset and set `dependent_objects_record_size` to `0`, the API uses the default. The API rejects a negative offset. If you omit this parameter, the API returns dependent objects without pagination, as in earlier releases. +* `dependent_objects_is_last_batch` + +_Response attribute_. Returns `true` if the returned page (batch) of `dependent_objects` is the last page for the object. If a page is full, the API returns `false` even if it is the final page. Continue requesting pages until the value is `true`. + +The following example retrieves the second page of 50 dependent objects: + +[source,JSON] +---- +{ + "metadata": [ + { + "identifier": "782b50d1-fe89-4fee-812f-b5f9eb0a552d" + } + ], + "include_dependent_objects": true, + "dependent_objects_record_offset": 50, + "dependent_objects_record_size": 50 +} +---- + +The `dependent_objects_is_last_batch` attribute appears in each metadata object in the response, next to `dependent_objects`. In the following example, the returned page is the last page of dependent objects for the object: + +[source,JSON] +---- +[ + { + "metadata_id": "782b50d1-fe89-4fee-812f-b5f9eb0a552d", + "metadata_name": "", + "metadata_type": "LOGICAL_TABLE", + "dependent_objects": { + "782b50d1-fe89-4fee-812f-b5f9eb0a552d": { + "LOGICAL_TABLE": [...], + "QUESTION_ANSWER_BOOK": [...] + } + }, + "dependent_objects_is_last_batch": true, + "incomplete_objects": null, + "metadata_detail": null, + "metadata_header": {...}, + "visualization_headers": null, + "stats": null + } +] +---- + === include_stats The `include_stats` boolean option causes the `stats` key of the response to be filled with an object with statistics about user access to the object. @@ -3956,7 +4006,7 @@ On ThoughtSpot instances running 10.11.0.cl or later, set the `include_only_publ === show_resolved_parameters On ThoughtSpot instances running 10.9.0.cl or later, if your metadata objects are parameterized, set the `show_resolved_parameters` boolean parameter to `true` to return the resolved parameter values in the response. -=== Pagination settings +=== Pagination settings for metadata objects By default, the following pagination settings are applied to the API response retrieved from the search metadata endpoint: diff --git a/modules/ROOT/pages/rest-api-v2-reference.adoc b/modules/ROOT/pages/rest-api-v2-reference.adoc index c400ff740..1e650adbd 100644 --- a/modules/ROOT/pages/rest-api-v2-reference.adoc +++ b/modules/ROOT/pages/rest-api-v2-reference.adoc @@ -41,8 +41,9 @@ Breaks down a user submitted query into relevant questions |ThoughtSpot Cloud: __10.13.0.cl or later__ + |+++Try it out+++ -a| `POST /api/rest/2.0/ai/agent/converse/sse` + -Allows sending a natural language query or a follow-up question to an ongoing conversation session and returns the AI agent's response, including answers, tokens, and visualization details. +a| `POST /api/rest/2.0/ai/agent/converse/sse` [tag redBackground]#DEPRECATED# + +Allows sending a natural language query or a follow-up question to an ongoing conversation session and returns the AI agent's response, including answers, tokens, and visualization details. + +__Note: This API endpoint is deprecated in ThoughtSpot 26.5.0.cl and later versions. To stream responses from a Spotter agent conversation, use `POST /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream`.__ |ThoughtSpot Cloud: __10.13.0.cl or later__ | +++Try it out+++ @@ -56,11 +57,22 @@ Generates an Answer for a Natural Language Search query. |ThoughtSpot Cloud: __10.4.0.cl or later__ + ThoughtSpot Software: __Not available__ a| +++Try it out+++ -a|`POST /api/rest/2.0/ai/agent/{conversation_identifier}/converse` + -Allows sending a query to an ongoing conversation session with Spotter agent and generate response. +a|`POST /api/rest/2.0/ai/agent/{conversation_identifier}/converse` [tag redBackground]#DEPRECATED# + +Allows sending a query to an ongoing conversation session with Spotter agent and generate response. + +__Note: This API endpoint is deprecated in ThoughtSpot 26.5.0.cl and later versions. To send messages to a Spotter agent conversation, use `POST /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send`.__ |ThoughtSpot Cloud: __10.15.0.cl or later__ + ThoughtSpot Software: __Not available__ a| +++Try it out+++ +a|`POST /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send` + +Sends natural language messages to an existing Spotter agent conversation and returns the complete response synchronously. +|ThoughtSpot Cloud: __26.5.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ + +a|`POST /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream` + +Sends natural language messages to an existing Spotter agent conversation and returns the response as a real-time Server-Sent Events (SSE) stream. +|ThoughtSpot Cloud: __26.5.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ + a|`POST /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/stop-response` + Stops an in-progress Spotter agent response for a given conversation session. |ThoughtSpot Cloud: __26.6.0.cl or later__ + @@ -115,10 +127,35 @@ a|`POST /api/rest/2.0/ai/memory/export` + Exports Spotter memory entries for audit, backup, or cross-environment migration. |ThoughtSpot Cloud: __26.8.0.cl or later__ + ThoughtSpot Software: __Not available__ a| +++Try it out+++ + +a|`GET /api/rest/2.0/ai/usage-data/user` [beta betaBackground]^Beta^ + +Retrieves a user's combined Spotter usage: every pool the user draws from, with usage, warning limits, and limits summed across them. +|ThoughtSpot Cloud: __26.11.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ + +a|`POST /api/rest/2.0/ai/usage-data/search` [beta betaBackground]^Beta^ + +Retrieves Spotter usage pools: the question allowance configured for each user, user group, or Org and how much has been consumed. +|ThoughtSpot Cloud: __26.11.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ + +a|`POST /api/rest/2.0/ai/usage-data/update` [beta betaBackground]^Beta^ + +Creates or updates Spotter usage pools, setting the question allowance for a user, user group, or Org. +|ThoughtSpot Cloud: __26.11.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ + +a|`POST /api/rest/2.0/ai/usage-data/delete` [beta betaBackground]^Beta^ + +Deletes Spotter usage pools. Users who no longer draw from any pool are no longer metered. +|ThoughtSpot Cloud: __26.11.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ + +a|`POST /api/rest/2.0/ai/agent/analysts/{analyst_identifier}/share` [beta betaBackground]^Beta^ + +Updates share permissions on a Spotter Analyst for one or more users or groups. Requires ownership of the Analyst, or `ADMINISTRATION` or `CAN_MANAGE_SPOTTER` privilege. +|ThoughtSpot Cloud: __26.10.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ |===== -- - + == Authentication [div boxAuto] @@ -413,7 +450,7 @@ Updates a custom calendar. |ThoughtSpot Cloud: __10.12.0.cl or later__ + ThoughtSpot Software: __26.3.0.sw or later__ a|+++Try it out+++ -|==== +|===== -- == Data @@ -593,6 +630,41 @@ ThoughtSpot Software: __9.0.1.sw or later__ a| |===== -- +== Input tables + +[div boxAuto] +-- +[width="100%" cols="6,6,3"] +[options='header'] +|===== +|API endpoint| Release version | Playground link +a|`POST /api/rest/2.0/input-tables/create` + +Creates an input table in the external Cloud Data Warehouse and links it to a ThoughtSpot model. +|ThoughtSpot Cloud: __26.11.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ + +a|`POST /api/rest/2.0/input-tables/{input_table_identifier}/columns/create` + +Adds one or more editable columns to an existing input table. +|ThoughtSpot Cloud: __26.11.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ + +a|`POST /api/rest/2.0/input-tables/{input_table_identifier}/update` + +Writes rows into an input table using a keyed upsert (MERGE). +|ThoughtSpot Cloud: __26.11.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ + +a|`POST /api/rest/2.0/input-tables/{input_table_identifier}/delete` + +Deletes an input table and drops the physical table from the Cloud Data Warehouse. +|ThoughtSpot Cloud: __26.11.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ + +a|`POST /api/rest/2.0/input-tables/{input_table_identifier}/columns/{column_identifier}/delete` + +Deletes an editable column from an input table. +|ThoughtSpot Cloud: __26.11.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ +|===== +-- + == Jobs @@ -606,7 +678,27 @@ a|`POST /api/rest/2.0/jobs/history/communication-channels/search` + Gets information about the execution and delivery status for scheduled jobs such as webhook delivery. |ThoughtSpot Cloud: __26.4.0.cl or later__ ThoughtSpot Software: __Not available__ - a| +++Try it out+++ +a| +++Try it out+++ +|===== +-- + +== Link customization + +[div boxAuto] +-- +[width="100%" cols="6,6,3"] +[options='header'] +|===== +|API endpoint| Release version | Playground link +a|`POST /api/rest/2.0/customization/links/search` + +Retrieves the URL templates ThoughtSpot uses to generate shareable links, at the cluster level or for the caller's Org. +|ThoughtSpot Cloud: __26.11.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ + +a|`POST /api/rest/2.0/customization/links/update` + +Sets or resets the URL templates at the cluster level or for the caller's Org. +|ThoughtSpot Cloud: __26.11.0.cl or later__ + +ThoughtSpot Software: __Not available__ a| +++Try it out+++ |===== -- diff --git a/modules/ROOT/pages/rest-apiv2-changelog.adoc b/modules/ROOT/pages/rest-apiv2-changelog.adoc index bdb92ca85..ae5f815ca 100644 --- a/modules/ROOT/pages/rest-apiv2-changelog.adoc +++ b/modules/ROOT/pages/rest-apiv2-changelog.adoc @@ -8,6 +8,91 @@ 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.11.0.cl, November 2026 + +=== Org-level API rate limiting enforced +The Org-level rate limit of 50 requests per second (RPS) per Org is now enforced for all public REST API endpoints on instances with Orgs enabled. This limit was announced in 26.10.0.cl and operates independently of the existing cluster-level limit of 100 RPS per client IP. Requests exceeding the Org-level limit receive an `HTTP 429: Too Many Requests` response. + +For more information, see xref:about-rest-apis.adoc#_rate_limits_for_api_requests[Rate limits for API requests]. + +=== Link Customization APIs +ThoughtSpot introduces two REST API v2.0 endpoints for managing the URL templates used when ThoughtSpot generates shareable links. + +* `POST /api/rest/2.0/customization/links/search` + +Retrieves the URL templates at the cluster level or for the Org the caller is signed in to. +* `POST /api/rest/2.0/customization/links/update` + +Updates the URL templates at the cluster level or for the caller's Org, using `REPLACE` to set templates or `RESET` to clear overrides. + +Supported link types include `LIVEBOARD_SHARE_URL`, `VISUALIZATION_SHARE_URL`, `ANSWER_SHARE_URL`, `SPOTIQ_ANALYSIS_URL`, `UNSUBSCRIBE_URL`, `GENERIC_URL`, and `CONVERSATION_SHARE_URL`. + +Requires `ADMINISTRATION` or `DEVELOPER` privilege. + +For more information, see xref:link-customization-api.adoc[Link Customization APIs]. + +=== Input Table APIs +ThoughtSpot introduces the following REST API endpoints for managing input tables (user-editable tables) stored in an external Cloud Data Warehouse and linked to a ThoughtSpot model: + +* `POST /api/rest/2.0/input-tables/create` + +Creates an input table and links it to a ThoughtSpot model. +* `POST /api/rest/2.0/input-tables/{input_table_identifier}/update` + +Writes rows to an input table using a keyed upsert (MERGE). +* `POST /api/rest/2.0/input-tables/{input_table_identifier}/delete` + +Deletes an input table. +* `POST /api/rest/2.0/input-tables/{input_table_identifier}/columns/create` + +Adds one or more editable columns to an input table. +* `POST /api/rest/2.0/input-tables/{input_table_identifier}/columns/{column_identifier}/delete` + +Deletes an editable column from an input table. + +For more information, see xref:input-table-api.adoc[Input Table APIs]. + +=== Spotter usage data APIs [beta betaBackground]^Beta^ +ThoughtSpot introduces four REST API v2.0 endpoints for managing Spotter usage pools, which control how many Spotter questions a user, user group, or Org can ask. + +* `GET /api/rest/2.0/ai/usage-data/user` + +Retrieves a user's combined Spotter usage across all pools. +* `POST /api/rest/2.0/ai/usage-data/search` + +Retrieves usage pools configured for users, user groups, or Orgs. +* `POST /api/rest/2.0/ai/usage-data/update` + +Creates or updates usage pools, setting question allowances. +* `POST /api/rest/2.0/ai/usage-data/delete` + +Deletes usage pools. + +For more information, see xref:spotter-usage-data-api.adoc[Spotter Usage Data APIs]. + +=== Webhook configuration reset + +The `POST /api/rest/2.0/webhooks/{webhook_identifier}/update` endpoint now supports the following parameters: + +* `operation` + +`REPLACE` (default) updates the fields provided in the request. `RESET` clears the sections specified in `reset_options` and accepts no other fields. +* `reset_options` + +The sections to remove from the webhook configuration when `operation` is `RESET`: `AUTHENTICATION`, `SIGNATURE_VERIFICATION`, and `STORAGE_DESTINATION`. + +=== Pagination of dependent objects in metadata search + +The `POST /api/rest/2.0/metadata/search` endpoint now supports pagination of dependent objects through the following parameters: + +* `dependent_objects_record_offset` + +Request parameter. Number of dependent objects to skip for each metadata object. Use it with `dependent_objects_record_size` (default: `50`). +* `dependent_objects_is_last_batch` + +Response attribute. `true` if the returned page is the last page of dependent objects for the object. + +For more information, see xref:rest-api-v2-metadata-search.adoc#_pagination_settings_for_dependent_objects[Pagination settings for dependent objects]. + +=== Maintenance schedule in system information + +The `GET /api/rest/2.0/system` response includes the `maintenance_schedule` object with details of the next maintenance window scheduled for the cluster. The object is absent when no maintenance is scheduled and includes the following attributes: + +* `start_time_in_millis`: Start time of the maintenance window in milliseconds since epoch. +* `duration_in_seconds`: Expected duration of the maintenance window. +* `status`: `SCHEDULED` or `AD_HOC`. +* `type`: `UPGRADE` or `PATCH`. +* `description`: Description of the maintenance event. + +=== Role identifiers in group import + +The group objects in the `POST /api/rest/2.0/groups/import` request body accept `role_identifiers`, an array of role IDs or names to assign to the group. + == Version 26.10.0.cl, October 2026 === Metadata search API enhancements @@ -36,6 +121,8 @@ Creates a Spotter Analyst with a name, description, data sources, and optional i Returns the Spotter Analysts visible to the caller. * `POST /api/rest/2.0/ai/agent/analysts/{analyst_identifier}/update` + Updates a Spotter Analyst. +* `POST /api/rest/2.0/ai/agent/analysts/{analyst_identifier}/share` [beta betaBackground]^Beta^ + +Updates share permissions on a Spotter Analyst for one or more users or groups. Granting access also shares the Analyst's data sources with the principal. * `POST /api/rest/2.0/ai/agent/analysts/{analyst_identifier}/delete` + Deletes a Spotter Analyst. + diff --git a/modules/ROOT/pages/roles.adoc b/modules/ROOT/pages/roles.adoc index 992e60f1c..40de9146b 100644 --- a/modules/ROOT/pages/roles.adoc +++ b/modules/ROOT/pages/roles.adoc @@ -166,6 +166,14 @@ UI: *Can create/edit Connections*| Allows creating, editing, and managing link:h UI: *Can manage data models* |Allows users to create, edit, delete, and manage Models, Tables, and Views. |Custom variables| API: `CAN_MANAGE_VARIABLES` + UI: *Can manage variables* | Allows users to manage formula Variables in the current Org scope. +// SOURCE: SCAL-301436; SCAL-305010; PrivilegeTypeEnum.java (dev/scaligent) +// Available from: ThoughtSpot Cloud 26.6.0.cl +|Manage input tables| API: `CAN_MANAGE_INPUT_TABLES` + +UI: *Can manage input tables* | Allows users to create, delete, and upload data to input tables. Applicable only on ThoughtSpot Cloud (SaaS) instances. +// SOURCE: SCAL-305010; PrivilegeTypeEnum.java (dev/scaligent) +// Available from: ThoughtSpot Cloud 26.10.0.cl +|Edit input tables| API: `CAN_EDIT_INPUT_TABLES` + +UI: *Can edit input tables* | Allows users to update values in existing input tables. Does not grant permission to create or delete input tables. Applicable only on ThoughtSpot Cloud (SaaS) instances. |=== diff --git a/modules/ROOT/pages/spotter-agent-apis.adoc b/modules/ROOT/pages/spotter-agent-apis.adoc index b664b5e0e..195dab868 100644 --- a/modules/ROOT/pages/spotter-agent-apis.adoc +++ b/modules/ROOT/pages/spotter-agent-apis.adoc @@ -4,7 +4,7 @@ :page-title: Spotter Agent APIs :page-pageid: spotter-agent-apis -:page-description: You can use Spotter REST APIs to receive Answers for your analytical queries sent through the conversational experience with ThoughtSpot. +:page-description: Use the Spotter agent REST APIs to create conversation sessions, send queries, receive synchronous or streaming responses, and share conversations. ThoughtSpot's Spotter AI agent APIs allow users to start a conversation session with Spotter Agent and send queries to explore data and receive responses synchronously or as a real-time Server-Sent Events (SSE) stream. @@ -20,16 +20,16 @@ The key capabilities of the Spotter APIs include the following: * Decomposing complex user queries == Supported API endpoints -The API endpoints introduced for Spotter 2 also support Spotter 3 capabilities as of version 26.2.0.cl. Some of these API endpoints are deprecated in 26.5.0.cl; ThoughtSpot recommends using the new API endpoints instead. +The API endpoints introduced for Spotter 2 also support Spotter 3 capabilities. Some of these API endpoints are deprecated; ThoughtSpot recommends using the new API endpoints instead. Initialize session:: Call the create agent conversation API (`/api/rest/2.0/ai/agent/conversation/create`) with a data source ID to establish the session context. When auto mode is enabled, and no data source ID is specified in the API request, Spotter will automatically identify the appropriate data source. See xref:spotter-agent-conversation-apis.adoc[Spotter agent conversation APIs]. Execute queries:: -To execute queries and generate a standard response synchronously, use the Send agent conversation message API (`/api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send`). The send agent message API (`/api/rest/2.0/ai/agent/{conversation_identifier}/converse`) is deprecated in 26.5.0.cl and later versions. See xref:spotter-agent-conversation-apis.adoc[Spotter agent conversation APIs]. +To execute queries and generate a standard response synchronously, use the Send agent conversation message API (`/api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send`). See xref:spotter-agent-conversation-apis.adoc[Spotter agent conversation APIs]. Real-time output (streaming):: -To stream responses to the application UI in real-time, use the `POST /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream`. The legacy streaming API (`/api/rest/2.0/ai/agent/converse/sse`) is deprecated in 26.5.0.cl and later versions. See xref:spotter-agent-streaming-apis.adoc[Spotter agent streaming APIs]. +To stream responses to the application UI in real-time, use the `POST /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream`. See xref:spotter-agent-streaming-apis.adoc[Spotter agent streaming APIs]. Share a conversation:: Share a saved Spotter conversation with other users or groups as read-only content. See xref:spotter-agent-sharing-apis.adoc[Spotter agent conversation sharing APIs]. @@ -41,11 +41,12 @@ a|`POST /api/rest/2.0/ai/agent/conversation/create` + xref:spotter-agent-conversation-apis.adoc#_create_a_conversation_session_with_spotter_agent[Creates a conversation session with the Spotter agent] to generate Answers for the specified data context. __Available on ThoughtSpot Cloud instances from 10.13.0.cl onwards. Breaking changes introduced in 26.5.0.cl.__ -a| `POST /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send` [.version-badge.new]#New# + +a| `POST /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send` + + xref:spotter-agent-conversation-apis.adoc#_send_queries_to_a_conversation_session[Sends natural language messages] to an existing Spotter agent conversation and returns the complete response synchronously. __Replaces /api/rest/2.0/ai/agent/{conversation_identifier}/converse__. -a|`POST /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream` [.version-badge.new]#New# + +a|`POST /api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream` + xref:spotter-agent-streaming-apis.adoc[Sends one or more natural language messages] to an existing Spotter agent conversation and returns the response as a real-time Server-Sent Events (SSE) stream. __Replaces /api/rest/2.0/ai/agent/converse/sse__. @@ -61,15 +62,15 @@ a| `POST /api/rest/2.0/ai/relevant-questions/` [beta betaBackground]^Beta^ + xref:spotter-agent-data-literacy-apis.adoc#_get_relevant_questions[Decomposes a user query] into relevant sub-questions. Guides users to explore data more deeply for a comprehensive analysis. + __Available on ThoughtSpot Cloud instances from 10.13.0.cl onwards__. -a| `POST /api/rest/2.0/ai/agent/conversations/{conversation_identifier}/share` [.version-badge.new]#New# + +a| `POST /api/rest/2.0/ai/agent/conversations/{conversation_identifier}/share` + xref:spotter-agent-sharing-apis.adoc#_share_a_conversation[Shares a saved Spotter conversation] with one or more users or groups. Use `grant` and `revoke` arrays to manage access. Shared conversations are `READ_ONLY`. + __Available on ThoughtSpot Cloud instances from 26.9.0.cl onwards.__ -a| `GET /api/rest/2.0/ai/agent/conversations/{conversation_identifier}/get-shared-content` [.version-badge.new]#New# + +a| `GET /api/rest/2.0/ai/agent/conversations/{conversation_identifier}/get-shared-content` + xref:spotter-agent-sharing-apis.adoc#_get_shared_content[Returns the shared content] of a Spotter conversation, including messages and associated answers. + __Available on ThoughtSpot Cloud instances from 26.9.0.cl onwards.__ -a| `GET /api/rest/2.0/ai/agent/conversations/{conversation_identifier}/get-share-info` [.version-badge.new]#New# + +a| `GET /api/rest/2.0/ai/agent/conversations/{conversation_identifier}/get-share-info` + xref:spotter-agent-sharing-apis.adoc#_get_share_information[Returns sharing metadata] for a Spotter conversation — the list of principals it is shared with and whether the shared content is outdated. + __Available on ThoughtSpot Cloud instances from 26.9.0.cl onwards.__ @@ -84,17 +85,6 @@ __Deprecated in 26.5.0.cl__. == Additional resources -* xref:spotter-agent-conversation-apis.adoc[Spotter agent conversation APIs] + -Create conversation sessions, send synchronous queries, and stop in-progress responses. -* xref:spotter-agent-streaming-apis.adoc[Spotter agent streaming APIs] + -Send queries and receive real-time Server-Sent Events (SSE) responses from the Spotter agent. -* xref:spotter-agent-process-results-apis.adoc[Process Spotter agent conversation results] + -Export or download Answers generated by a Spotter agent conversation session. -* xref:spotter-agent-data-literacy-apis.adoc[Spotter agent data literacy APIs] + -Get data source suggestions and decompose a user query into relevant sub-questions. -* xref:spotter-agent-sharing-apis.adoc[Spotter agent conversation sharing APIs] + -Share saved Spotter conversations with other users and groups. -* xref:spotter-agent-conversation-mgmt-apis.adoc[APIs for managing saved conversations] + -Retrieve, update, and delete saved Spotter 3 conversations and their messages. +* For the complete list of Spotter API pages, rate limits, and locale settings, see xref:spotter-apis.adoc[Spotter APIs]. * Visit the +++REST API v2.0 Playground+++ to view the API endpoints and verify the request and response workflows. * For information about MCP tools, see xref:mcp-integration.adoc[MCP server integration]. diff --git a/modules/ROOT/pages/spotter-agent-conversation-apis.adoc b/modules/ROOT/pages/spotter-agent-conversation-apis.adoc index 4aa924ef6..2983c1c56 100644 --- a/modules/ROOT/pages/spotter-agent-conversation-apis.adoc +++ b/modules/ROOT/pages/spotter-agent-conversation-apis.adoc @@ -8,7 +8,7 @@ ThoughtSpot's Spotter agent conversation APIs allow you to create a conversation session with the Spotter agent, send natural language queries to it, and stop an in-progress response. -For information about receiving responses as a real-time event stream, see xref:spotter-agent-streaming-apis.adoc[Spotter agent streaming APIs]. For information about exporting Answers generated by a conversation, see xref:spotter-agent-process-results-apis.adoc[Process Spotter agent conversation results]. For information about the data source and question suggestion APIs, see xref:spotter-agent-data-literacy-apis.adoc[Spotter agent data literacy APIs]. For information about sharing saved conversations, see xref:spotter-agent-sharing-apis.adoc[Spotter agent conversation sharing APIs]. +For an overview of all Spotter agent APIs and related pages, see xref:spotter-agent-apis.adoc[Spotter agent APIs]. == Create a conversation session with Spotter Agent @@ -161,7 +161,7 @@ If the conversation context uses a Spotter Analyst agent, the API endpoint retur To send queries to an ongoing conversation session with the Spotter agent and receive a response synchronously, use the `/api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send` API endpoint. -This API operation requires the conversation ID obtained from the conversation creation API endpoint (`/api/rest/2.0/ai/agent/conversation/create`). The user making the API request must have access to the conversation session. The API request body must include at least one message in natural language format. +This API operation requires the conversation ID obtained from the conversation creation API endpoint (`/api/rest/2.0/ai/agent/conversation/create`). The user making the API request must have the `CAN_USE_SPOTTER` privilege, access to the metadata object associated with the conversation, and access to the conversation session. The API request body must include at least one message in natural language format. === Request parameters @@ -406,7 +406,6 @@ If the conversation session is not found or has expired, the API returns an erro == Additional resources -* See also xref:spotter-agent-apis.adoc[Spotter Agent APIs] * xref:spotter-agent-streaming-apis.adoc[Spotter agent streaming APIs] * xref:spotter-agent-process-results-apis.adoc[Process Spotter agent conversation results] * xref:spotter-agent-data-literacy-apis.adoc[Spotter agent data literacy APIs] diff --git a/modules/ROOT/pages/spotter-agent-streaming-apis.adoc b/modules/ROOT/pages/spotter-agent-streaming-apis.adoc index 3094ce90a..e6854fc92 100644 --- a/modules/ROOT/pages/spotter-agent-streaming-apis.adoc +++ b/modules/ROOT/pages/spotter-agent-streaming-apis.adoc @@ -14,6 +14,8 @@ For information about creating a conversation session and sending queries to it, To send queries to an ongoing conversation session with Spotter agent and receive streaming responses, use the `/api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream` API endpoint. This API endpoint uses the SSE protocol to deliver data incrementally in real time, rather than waiting for the entire response to be generated before sending it to the client. +This API operation requires the `CAN_USE_SPOTTER` privilege and access to the metadata object associated with the conversation. The user making the API request must also have access to the conversation session. + The `/api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream` API can be used as an integrated tool for real-time streaming of conversational interactions between agents and the ThoughtSpot backend. === Request parameters diff --git a/modules/ROOT/pages/spotter-apis.adoc b/modules/ROOT/pages/spotter-apis.adoc index a9e29c858..b7a773699 100644 --- a/modules/ROOT/pages/spotter-apis.adoc +++ b/modules/ROOT/pages/spotter-apis.adoc @@ -8,13 +8,6 @@ The Spotter APIs support natural-language-driven analytics, context-aware and guided data analysis, and integration with agentic systems. -The key capabilities of the Spotter APIs include the following: - -* Initiating and managing conversational sessions -* Processing natural-language queries and interpreting user intent -* Generating analytical responses, insights, and visualizations -* Decomposing complex user queries - Spotter manages conversation sessions, context tracking, and response generation for user-submitted queries. The Spotter APIs are designed for use in Spotter-driven analytics and also for agentic interactions within an orchestrated agent framework. Spotter API operations require `CAN_USE_SPOTTER` privilege and at least view-level access to the underlying metadata entities referenced in the response. @@ -55,8 +48,6 @@ The following rate limits apply to Spotter agent APIs per user: |`/api/rest/2.0/ai/agent/conversation/create` | 10 |`/api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send`| 30 |`/api/rest/2.0/ai/agent/conversation/{conversation_identifier}/send/stream` | 30 -|`/api/rest/2.0/ai/agent/{conversation_identifier}/converse` [.version-badge.deprecated]#Deprecated# | 30 -|`/api/rest/2.0/ai/agent/converse/sse` [.version-badge.deprecated]#Deprecated# | 30 |===== If you are integrating these APIs in your environment, consider implementing a retry logic to handle the rate limit errors. diff --git a/modules/ROOT/pages/spotter-usage-data-api.adoc b/modules/ROOT/pages/spotter-usage-data-api.adoc new file mode 100644 index 000000000..c7df8392f --- /dev/null +++ b/modules/ROOT/pages/spotter-usage-data-api.adoc @@ -0,0 +1,383 @@ += Spotter Usage Data APIs +:toc: true +:toclevels: 2 + +:page-title: Spotter Usage Data APIs +:page-pageid: spotter-usage-data-api +:page-description: Use the Spotter usage data REST API v2 endpoints to manage Spotter question allowances for users, user groups, and Orgs. +:keywords: Spotter usage, usage pools, usage limits, question allowance, Spotter limits, REST API + +[beta betaBackground]^Beta^ + +Spotter usage pools let administrators control how many Spotter questions a user, user group, or Org can ask. Each pool tracks a question allowance, a warning threshold, and the number of questions consumed. + +ThoughtSpot provides public REST API v2 endpoints to create, retrieve, update, and delete usage pools programmatically for the following purposes: + +* To provision limits for new users or groups. +* To monitor consumption and find pools that are close to their limit. +* To raise or lower the limits. +* To reset usage at the start of a billing period. + +To set up usage limits end to end, including the Visual Embed SDK configuration for the usage counter and an upgrade workflow, see xref:spotter-usage-limits.adoc[Manage Spotter usage limits]. + +[NOTE] +==== +The Spotter usage data APIs are in Beta in ThoughtSpot Cloud 26.11.0.cl. Breaking changes may be introduced before the endpoints are made Generally Available. +==== + +== Usage pools and metering +A *usage pool* is a Spotter question allowance assigned to an entity: a user, a user group, or an Org. Each pool tracks the following values: + +* `usage` + +The number of questions consumed from the pool. +* `warning_limit` + +The usage level at which users start seeing a warning. Optional. +* `limit` + +The maximum number of questions that the pool allows. Optional. If it is not set, the pool is unlimited. + +=== Metering scope +A cluster meters Spotter usage at exactly one scope: per user, per user group, or per Org. The first pool created on the cluster sets the scope, and every pool created after that must use the same `entity_type`. To switch the scope, delete all existing pools using the <> API endpoint. + +=== How users draw from pools +A user draws from every pool that meters them. Depending on the metering scope of the cluster, these are the user's own pool (per user), the pools of the user groups that the user belongs to, including inherited groups (per user group), or the pool of the user's Org (per Org). The totals in the <> response are sums across these pools. For example, a user in two groups with limits of 100 and 50 has a `total_limit` of 150. + +A user who draws from no pool is not metered and can use Spotter without a limit. + +=== Required privileges +To use the Spotter usage data APIs, the user requires the following privileges: + +* **Get usage data for user**: Any user can retrieve their own usage. To retrieve another user's usage, the user requires `ADMINISTRATION` (**Can administer ThoughtSpot**) privilege. `CAN_MANAGE_SPOTTER` is not sufficient. +* **Search, update, and delete usage data**: These endpoints require `ADMINISTRATION` (**Can administer ThoughtSpot**) privilege. Users with only `CAN_MANAGE_SPOTTER`, and Org administrators without cluster-level `ADMINISTRATION`, cannot call these endpoints. + +[#get-usage-data-for-user] +== Getting usage data for a user +The `GET /api/rest/2.0/ai/usage-data/user` API endpoint retrieves a user's combined Spotter usage: every usage pool that the user draws from, with usage, warning limits, and limits summed across them. Use this endpoint to show users how many Spotter questions they have left, or to check whether a user is blocked by a usage limit. + +=== Request parameters +[cols="2,4", options="header"] +|=== +|Parameter | Description +| `user_identifier` +|__String__. Optional. Query parameter. GUID of the user whose usage you want to retrieve. If you omit this parameter, the API returns the usage of the authenticated user. Passing another user's GUID requires `ADMINISTRATION` privilege. +|=== + +=== Example request + +.Retrieve the authenticated user's usage +[source,cURL] +---- +curl -X GET \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/ai/usage-data/user' \ + -H 'Accept: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' +---- + +.Retrieve another user's usage +[source,cURL] +---- +curl -X GET -G \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/ai/usage-data/user' \ + -H 'Accept: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-urlencode 'user_identifier={user-guid}' +---- + +=== Example response +If the API request is successful, the API returns the following response: + +[source,JSON] +---- +{ + "summary": { + "pools": [ + { + "key": { + "entity_type": "USER_GROUP", + "entity_identifier": "{group-guid-1}" + }, + "usage": 120, + "warning_limit": 80, + "limit": 100, + "updated_time_in_millis": 1793433600000, + "updated_by": "{admin-user-guid}" + }, + { + "key": { + "entity_type": "USER_GROUP", + "entity_identifier": "{group-guid-2}" + }, + "usage": 0, + "warning_limit": 40, + "limit": 50, + "updated_time_in_millis": 1793433600000, + "updated_by": "{admin-user-guid}" + } + ], + "total_usage": 120, + "total_warning_limit": 120, + "total_limit": 150, + "total_remaining": 30, + "is_at_warning": true, + "is_at_limit": false, + "has_unlimited_pool": false + } +} +---- + +=== Response parameters +[cols="2,4", options="header"] +|=== +| Parameter | Description +| `summary` +a| The user's combined usage across every pool that the user draws from. The object includes the following attributes: + +* `pools`: The individual pools that the user draws from. Each entry has the same attributes as an entry in the `usage_data` array returned by the <> API. The array is empty if the user is not metered. +* `total_usage`: Total questions consumed across all pools. +* `total_warning_limit`: Sum of the warning limits across all pools. +* `total_limit`: Sum of the limits across all pools. +* `total_remaining`: Questions that the user can still ask. Absent when `has_unlimited_pool` is `true`. +* `is_at_warning`: `true` when usage has reached the combined warning limit. +* `is_at_limit`: `true` when usage has reached the combined limit and further Spotter questions are blocked. For a user who is not metered, the value is `false`. +* `has_unlimited_pool`: `true` when any of the user's pools has no limit, which makes the user effectively unlimited. +|=== + +[#search-usage-data] +== Searching usage data +The `/api/rest/2.0/ai/usage-data/search` API endpoint retrieves Spotter usage pools. A usage pool is the Spotter question allowance configured for a user, user group, or Org, together with the number of questions consumed from it. Use this endpoint to monitor usage across your users, for example, to find pools that are close to their limit. + +To retrieve every pool on the cluster, send an empty request body. To retrieve specific pools, pass `keys`. The API omits keys that match no pool from the response. + +To see the combined usage of a single user across every pool the user draws from, use the <> API endpoint. + +=== Request parameters +[cols="2,4", options="header"] +|=== +|Parameter | Description +| `keys` +a|__Array of objects__. Optional. Specify the pools to retrieve. Omit this parameter to return every usage pool on the cluster. Keys that do not correspond to existing pools are silently ignored and do not appear in the response. + +For each key, specify the following attributes: + +* `entity_type`. __String__. Type of entity that the pool meters: `USER`, `USER_GROUP`, or `ORG`. It must match the scope that the cluster meters at. +* `entity_identifier`. __String__. GUID of the user or user group, or the ID of the Org. +|=== + +=== Example request + +.Retrieve all pools +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/ai/usage-data/search' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{}' +---- + +.Retrieve specific pools +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/ai/usage-data/search' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{ + "keys": [ + { + "entity_type": "USER", + "entity_identifier": "{user-guid}" + } + ] +}' +---- + +=== Example response +If the API request is successful, the API returns the following response: + +[source,JSON] +---- +{ + "usage_data": [ + { + "key": { + "entity_type": "USER", + "entity_identifier": "{user-guid}" + }, + "usage": 120, + "warning_limit": 400, + "limit": 500, + "updated_time_in_millis": 1793433600000, + "updated_by": "{admin-user-guid}" + } + ] +} +---- + +=== Response parameters +[cols="2,4", options="header"] +|=== +| Parameter | Description +| `usage_data` +a| One entry for each pool. Each entry includes the following attributes: + +* `key`: The entity that the pool meters, with `entity_type` and `entity_identifier`. +* `usage`: Number of questions consumed from the pool. +* `warning_limit`: Usage level at which users are warned that they are approaching the limit. Absent when no warning is configured. +* `limit`: Maximum number of questions that the pool allows. Absent when the pool is unlimited. +* `updated_time_in_millis`: Time of the last change to the pool configuration, in milliseconds since epoch. +* `updated_by`: ID of the user who last changed the pool configuration. +|=== + +[#update-usage-data] +== Creating or updating usage data +The `/api/rest/2.0/ai/usage-data/update` API endpoint creates or updates Spotter usage pools. Use this endpoint to provision limits for new users or groups, raise or lower an existing limit, or reset usage at the start of a billing period. + +A pool that does not exist is created. Fields omitted from an update keep their current value. Every key must use the scope that the cluster meters at. To switch the scope, delete the existing pools first. + +=== Request parameters +[cols="2,4", options="header"] +|=== +|Parameter | Description +| `updates` +a|__Array of objects__. The changes to apply, one entry for each pool. At least one entry is required. For each entry, specify the following attributes: + +* `key`. __Object__. The pool to create or update. Specify the `entity_type` (`USER`, `USER_GROUP`, or `ORG`) and the `entity_identifier` (the GUID of the user or user group, or the ID of the Org). The `entity_type` must match the scope that the cluster meters at. +* `limit`. __Integer__. Optional. Maximum number of Spotter questions that the pool allows. To remove a limit from an existing pool entirely, delete the pool using the xref:spotter-usage-data-api.adoc#delete-usage-data[delete usage data] endpoint and recreate it without a `limit` attribute. +* `warning_limit`. __Integer__. Optional. Usage level at which users are warned that they are approaching the limit. +* `usage`. __Integer__. Optional. Number of questions consumed so far. Set it to `0` to reset the pool. +|=== + +=== Example request + +.Create a pool for a user +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/ai/usage-data/update' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{ + "updates": [ + { + "key": { + "entity_type": "USER", + "entity_identifier": "{user-guid}" + }, + "limit": 500, + "warning_limit": 400 + } + ] +}' +---- + +.Reset the usage of a pool to zero +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/ai/usage-data/update' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{ + "updates": [ + { + "key": { + "entity_type": "USER", + "entity_identifier": "{user-guid}" + }, + "usage": 0 + } + ] +}' +---- + +=== Example response +If the API request is successful, the API returns `usage_data` with each updated pool as it stands after the change. The response has the same structure as the response of the <> API. + +[source,JSON] +---- +{ + "usage_data": [ + { + "key": { + "entity_type": "USER", + "entity_identifier": "{user-guid}" + }, + "usage": 0, + "warning_limit": 400, + "limit": 500, + "updated_time_in_millis": 1793433600000, + "updated_by": "{admin-user-guid}" + } + ] +} +---- + +[#delete-usage-data] +== Deleting usage data +The `/api/rest/2.0/ai/usage-data/delete` API endpoint deletes Spotter usage pools. Use this endpoint to remove a limit from a user, user group, or Org, or to clear every pool before switching the metering scope. + +Deleting a pool removes its limit rather than blocking its users. A user who no longer draws from any pool is not metered and can use Spotter without a limit. + +[WARNING] +==== +This operation cannot be undone. To recreate a deleted pool, use the <> API endpoint. The usage of the new pool restarts from `0`. +==== + +=== Request parameters +[cols="2,4", options="header"] +|=== +|Parameter | Description +| `keys` +a|__Array of objects__. The pools to delete. At least one entry is required. For each key, specify the following attributes: + +* `entity_type`. __String__. Type of entity that the pool meters: `USER`, `USER_GROUP`, or `ORG`. It must match the scope that the cluster meters at. +* `entity_identifier`. __String__. GUID of the user or user group, or the ID of the Org. +|=== + +=== Example request + +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/ai/usage-data/delete' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{ + "keys": [ + { + "entity_type": "ORG", + "entity_identifier": "{org-id}" + } + ] +}' +---- + +=== Example response +If the API request is successful, the API returns `deleted_keys`, the keys of the pools that existed and were deleted. The API omits keys that matched no pool. + +[source,JSON] +---- +{ + "deleted_keys": [ + { + "entity_type": "ORG", + "entity_identifier": "{org-id}" + } + ] +} +---- + +== Additional resources + +* xref:spotter-usage-limits.adoc[Manage Spotter usage limits] +* xref:rest-api-v2-reference.adoc#_ai[REST API v2.0 Reference] +* xref:rest-apiv2-changelog.adoc[REST API v2.0 changelog] +* +++REST API Playground - Get usage data for user endpoint+++ +* +++REST API Playground - Search usage data endpoint+++ +* +++REST API Playground - Update usage data endpoint+++ +* +++REST API Playground - Delete usage data endpoint+++ diff --git a/modules/ROOT/pages/spotter-usage-limits.adoc b/modules/ROOT/pages/spotter-usage-limits.adoc new file mode 100644 index 000000000..8917bba23 --- /dev/null +++ b/modules/ROOT/pages/spotter-usage-limits.adoc @@ -0,0 +1,406 @@ += Manage Spotter usage limits +:toc: true +:toclevels: 2 + +:page-title: Manage Spotter usage limits +:page-pageid: spotter-usage-limits +:page-description: Control and monitor the number of questions users can ask Spotter using usage pools, the Spotter usage data REST APIs, and the Visual Embed SDK. +:keywords: Spotter usage limits, usage pools, question allowance, usage counter, spotterUsageLimitConfig, upgrade workflow + +Spotter usage limits allow administrators to control and monitor the number of natural language questions that users can ask Spotter. You can define usage allowances at the individual user, user group, or Org level. Spotter tracks query consumption, shows an allowance meter to end users in the embedded interface, and blocks further questions after the allowance is spent. + +This page describes how to configure usage limits, choose a metering scope, configure the usage counter in the Visual Embed SDK, and build a custom upgrade workflow. + +[NOTE] +==== +The Spotter usage data APIs are in Beta in ThoughtSpot Cloud 26.11.0.cl. Breaking changes may be introduced before the endpoints are made Generally Available (GA). +==== + +== Before you begin + +Ensure you have the following setup: + +* Your ThoughtSpot instance is running 26.11.0.cl or later. +* Your embedding application project has Visual Embed SDK v1.53.0 or later. +* You have a user account with `ADMINISTRATION` (**Can administer ThoughtSpot**) privilege to create and manage usage pools via REST APIs. + +== How usage limits work +A *usage pool* is a tracked question allowance assigned to an entity: a user (`USER`), a user group (`USER_GROUP`), or an Org (`ORG`). Each pool has the following properties: + +[cols="2,4", options="header"] +|=== +| Field | Description +| `limit` | The maximum number of questions that the pool allows. +| `warning_limit` | The usage level at which the embedded UI shows a warning banner. +| `usage` | The cumulative number of questions consumed from the pool. +|=== + +You manage usage pools using the Spotter usage data REST APIs. As users ask questions in Spotter, ThoughtSpot debits the questions from the pools that apply to them and updates the usage counter in the embedded UI. + +The following rules determine how pools apply to a user: + +* **Allowances are additive**. + +If a user belongs to multiple groups that have usage pools, the user's effective limit is the sum of all applicable pools. For example, membership in two groups with limits of 100 and 50 results in a total limit of 150. +* **A pool without a limit makes the user unlimited**. + +If any pool that applies to a user has no `limit`, the user is treated as unlimited (`has_unlimited_pool: true`). ThoughtSpot does not debit questions for the user and does not calculate a remaining balance. +* **Usage limits are opt-in**. + +A user who does not map to any usage pool is not metered and can use Spotter without a limit. + +== Choosing a metering scope +A cluster supports exactly one metering scope at a time. The first usage pool created on a cluster sets its `entity_type`, and all subsequent pools must use the same `entity_type`. To change the metering scope, you must first delete all existing pools. + +[cols="1,2,3", options="header"] +|=== +| Metering scope (`entity_type`) | How the allowance is evaluated | Recommended use case +| `USER` +| Per individual user account. +| Personalized usage quotas, or individual user seat management. + +| `USER_GROUP` +| Across all groups that a user belongs to, including inherited groups. +| Plan tier packaging, such as Trial, Standard, and Premium, or team-level caps. + +| `ORG` +| Against the user's current active Org. +| Multi-tenant deployments in which Orgs purchase shared query pools. +|=== + +[NOTE] +==== +For the `ORG` scope, `entity_identifier` is the numeric Org ID expressed as a string. For example, `"0"` represents the Primary Org. +==== + +== Setting up usage limits +To set up usage limits for the embedded Spotter interface, complete the following steps in order: + +. <<_choosing_a_metering_scope,Choose a metering scope>>. +. <> using the REST API from your backend. +. <>. +. <>. + +After you complete these steps, you can <<_customizing_usage_limits_in_the_embed,customize the usage counter>> and <<_building_an_upgrade_workflow,build an upgrade workflow>>. + +[#step-create-pools] +=== Creating usage pools +To create a usage pool, send a `POST` request to the `/api/rest/2.0/ai/usage-data/update` endpoint. Identify each pool with a key that contains the following attributes: + +* `entity_type`: `USER`, `USER_GROUP`, or `ORG`. Use the scope that you chose in <<_choosing_a_metering_scope,Choosing a metering scope>>. +* `entity_identifier`: The GUID of the user or user group, or the ID of the Org. + +Set `limit` to the maximum number of questions, and optionally set `warning_limit` to the usage level at which users see a warning. The following example creates a pool for a user group, for example, Trial users: + +[source,cURL] +---- +curl -X POST \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/ai/usage-data/update' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-raw '{ + "updates": [ + { + "key": { + "entity_type": "USER_GROUP", + "entity_identifier": "{group-guid}" + }, + "limit": 50, + "warning_limit": 40 + } + ] +}' +---- + +[IMPORTANT] +==== +Do not call the usage data endpoints that create, update, delete, or search pools from client-side code. These endpoints require cluster-level `ADMINISTRATION` (**Can administer ThoughtSpot**) privilege, so run them from your backend. +==== + +You can use the following endpoints to manage pools. For the request and response details, and for tasks such as raising a limit, resetting usage, removing a limit, or deleting a pool, see xref:spotter-usage-data-api.adoc[Spotter usage data APIs]. + +[cols="3,3", options="header"] +|=== +| Endpoint | Purpose +| `POST /api/rest/2.0/ai/usage-data/update` | Create, update, or reset usage pools. See xref:spotter-usage-data-api.adoc#update-usage-data[Creating or updating usage data]. +| `POST /api/rest/2.0/ai/usage-data/search` | Query existing usage pools. See xref:spotter-usage-data-api.adoc#search-usage-data[Searching usage data]. +| `GET /api/rest/2.0/ai/usage-data/user` | Retrieve the evaluated usage status of a user. See xref:spotter-usage-data-api.adoc#get-usage-data-for-user[Getting usage data for a user]. +| `POST /api/rest/2.0/ai/usage-data/delete` | Delete usage pools. See xref:spotter-usage-data-api.adoc#delete-usage-data[Deleting usage data]. +|=== + +[#step-enable-embed] +=== Enabling usage limits in the embed +To enable usage tracking and show the usage counter in your embedded Spotter interface, set `spotterUsageLimitConfig` in your `SpotterEmbed` or `AppEmbed` configuration: + +[source,JavaScript] +---- +// SpotterEmbed +import { SpotterEmbed, SpotterUsageCounterDisplayMode } from '@thoughtspot/visual-embed-sdk'; + +const embed = new SpotterEmbed('#tsEmbed', { + worksheetId: '', + spotterUsageLimitConfig: { + isEnabled: true, + usageCounterDisplayMode: SpotterUsageCounterDisplayMode.AlwaysVisible, + }, +}); + +embed.render(); +---- + +[source,JavaScript] +---- +// AppEmbed +import { AppEmbed, SpotterUsageCounterDisplayMode } from '@thoughtspot/visual-embed-sdk'; + +const embed = new AppEmbed('#tsEmbed', { + spotterUsageLimitConfig: { + isEnabled: true, + usageCounterDisplayMode: SpotterUsageCounterDisplayMode.AlwaysVisible, + }, +}); + +embed.render(); +---- + +For the other configuration options, see <<_configuring_the_usage_counter,Configuring the usage counter>>. + +[#step-verify-usage] +=== Verifying the usage status of a user +To check the current usage position of a user, send a `GET` request to the `/api/rest/2.0/ai/usage-data/user` endpoint: + +[source,cURL] +---- +curl -X GET -G \ + --url 'https://{ThoughtSpot-Host}/api/rest/2.0/ai/usage-data/user' \ + -H 'Accept: application/json' \ + -H 'Authorization: Bearer {AUTH_TOKEN}' \ + --data-urlencode 'user_identifier={user-guid}' +---- + +If you omit `user_identifier`, the API returns the usage of the authenticated user. The response includes the pools that the user draws from and the combined totals, such as `total_usage`, `total_limit`, `total_remaining`, `is_at_warning`, `is_at_limit`, and `has_unlimited_pool`. For the full response, see xref:spotter-usage-data-api.adoc#get-usage-data-for-user[Getting usage data for a user]. + +To review all the pools on the cluster, use the xref:spotter-usage-data-api.adoc#search-usage-data[search usage data] endpoint. + +Then, load the embedded Spotter interface as a user who draws from one of the pools. With the default `AlwaysVisible` display mode, the usage counter appears in the interface. + +== Customizing usage limits in the embed +After you enable usage limits, you can customize how the usage counter and banners appear in the embedded interface, and respond to usage events in your host application. The following sections describe how to: + +* <<_configuring_the_usage_counter,Configure the usage counter>>, including the banners, the Upgrade button, and the counter display modes. +* <<_handling_usage_limit_events,Handle usage limit events>> when a user selects the *Upgrade* button. +* <<_refreshing_usage_data,Refresh usage data>> in the embed without reloading the page. + +=== Configuring the usage counter + +Use `spotterUsageLimitConfig` in your `SpotterEmbed` or `AppEmbed` configuration to control usage enforcement and the counter display. + +[cols="2,1,1,4", options="header"] +|=== +| Property | Type | Default | Description + +| `isEnabled` +| boolean +| `false` +| Enables Spotter usage limit enforcement and the usage display elements in the embedded interface. + +| `isUpgradeButtonVisible` +| boolean +| `true` +| Controls the visibility of the Upgrade button in the embedded interface. + +| `isWarningBannerEnabled` +| boolean +| `true` +| Displays a warning banner when the user's consumption reaches `warning_limit`. + +| `isLimitBannerEnabled` +| boolean +| `true` +| Displays a notification banner when the user's consumption reaches `limit`. + +| `usageCounterDisplayMode` +| Enum +| `AlwaysVisible` +| Specifies when the usage counter is shown. See <<_counter_display_modes,Counter display modes>>. +|=== + +[NOTE] +==== +Disabling `isLimitBannerEnabled` suppresses the notification banner but does not bypass query blocking when the limit is reached. Users are still blocked from asking additional questions. +==== + +==== Counter display modes + +The `SpotterUsageCounterDisplayMode` enum controls when the usage counter is visible to the user: + +[cols="1,3", options="header"] +|=== +| Value | Behavior + +| `AlwaysVisible` +| The counter is permanently displayed. + +| `AlwaysHidden` +| The counter is hidden at all times. + +| `VisibleAfterWarning` +| The counter appears only after the user's consumption reaches the `warning_limit` threshold. + +| `VisibleAfterLimit` +| The counter appears only after the user's consumption reaches the maximum `limit`. +|=== + +=== Handling usage limit events +When an end user clicks the *Upgrade* button in the embedded Spotter interface, the embed emits the `EmbedEvent.SpotterUsageLimitUpgrade` event. Register a handler for this event to start your own upgrade flow. The event payload includes the following properties: + +* `payload.data.usageCount` (__number__): Total questions asked across sessions. +* `payload.data.usageLimit` (__number__): Total assigned usage limit. +* `payload.data.status` (__string__): One of `withinLimit`, `almostReached`, or `limitReached`. + +[source,JavaScript] +---- +embed.on(EmbedEvent.SpotterUsageLimitUpgrade, (payload) => { + console.log(payload.data.usageCount, payload.data.usageLimit, payload.data.status); +}); +---- + +The `status` values indicate the following: + +[cols="1,3", options="header"] +|=== +| Value | Meaning + +| `withinLimit` +| The user's consumption is below the `warning_limit`. + +| `almostReached` +| The user's consumption has reached or exceeded the `warning_limit` but has not yet reached `limit`. + +| `limitReached` +| The user's consumption has reached or exceeded `limit`. The user is blocked from asking additional questions. +|=== + +=== Refreshing usage data +To refresh the usage data in the embed without reloading the page, for example, after a tier upgrade or a server-side REST API update, trigger the `HostEvent.SpotterRefreshUsageLimit` event: + +[source,JavaScript] +---- +// Refresh the current usage data +embed.trigger(HostEvent.SpotterRefreshUsageLimit); + +// Refresh and override settings for the current session +embed.trigger(HostEvent.SpotterRefreshUsageLimit, { + isUpgradeButtonVisible: false, + isUnlimited: true, +}); +---- + +The event accepts the following optional session overrides: + +* `isUnlimited`: When set to `true`, temporarily hides the usage tracking UI for the session. +* `isUpgradeButtonVisible`: Overrides the visibility of the *Upgrade* button for the session. + +The overrides apply only to the current embed session and do not modify the pool configuration stored in ThoughtSpot. + +For a complete list of event IDs, see xref:EmbedEvent.adoc[EmbedEvent reference] and xref:HostEvent.adoc[HostEvent reference]. + +== Building an upgrade workflow +ThoughtSpot does not handle subscription billing. To let users upgrade their allowance, coordinate the following components: the Visual Embed SDK, your host application, your billing service, and the ThoughtSpot REST APIs. + +. The end-user reaches an allowance threshold and clicks *Upgrade* in the embedded interface. +. Your host application receives the `EmbedEvent.SpotterUsageLimitUpgrade` event. +. Your host application runs its own upgrade logic, for example, opening a payment dialog or changing the account plan. +. After the payment or account change succeeds, your backend calls the `POST /api/rest/2.0/ai/usage-data/update` endpoint with server-side credentials, or reassigns the user's group memberships. +. Your host application triggers `HostEvent.SpotterRefreshUsageLimit` to refresh the embed state without a page reload. + +The following example shows the flow in the host application: + +[source,JavaScript] +---- +embed.on(EmbedEvent.SpotterUsageLimitUpgrade, async ({ data }) => { + // 1. Process the upgrade in your billing application + const isUpgraded = await myApplicationBillingFlow({ + currentUsage: data.usageCount, + currentLimit: data.usageLimit, + }); + + if (!isUpgraded) return; + + // 2. Call your backend endpoint, which securely calls the ThoughtSpot REST API update endpoint + await fetch('/api/thoughtspot/upgrade-quota', { method: 'POST' }); + + // 3. Refresh the usage state in the embed + embed.trigger(HostEvent.SpotterRefreshUsageLimit, { + isUpgradeButtonVisible: false, // Hide the Upgrade button after a successful upgrade + }); +}); +---- + +== Common operational tasks + +[cols="2,4", options="header"] +|=== +| Task | How to +| Reset usage for a new billing cycle +| Send a `POST` request to the xref:spotter-usage-data-api.adoc#update-usage-data[update usage data] endpoint for each pool with `"usage": 0`. Omit `limit` to preserve the existing limit. + +| Exempt a user in a group-metered cluster +| Create a `USER`-type pool without a `limit` attribute for the exempted user, using the xref:spotter-usage-data-api.adoc#update-usage-data[update usage data] endpoint. The resulting unlimited assignment overrides the group-level caps. + +| Audit the allowances of a user +| Send a `GET` request to the xref:spotter-usage-data-api.adoc#get-usage-data-for-user[get usage data for user] endpoint with the user's GUID, and review the `pools` array to see every contributing entity and the remaining balance. + +| Change the metering scope +| Send a `POST` request to the xref:spotter-usage-data-api.adoc#delete-usage-data[delete usage data] endpoint with all pool keys on the cluster, and then create new pools with the new `entity_type`. +|=== + +== Troubleshooting + +[cols="2,3,4", options="header"] +|=== +| Symptom | Cause | Resolution +| A user receives a higher limit than intended +| Allowances are cumulative across all pools that apply to the user. +| Review the `pools` array in the xref:spotter-usage-data-api.adoc#get-usage-data-for-user[get usage data for user] response to verify group memberships, and remove unintended assignments. + +| Usage is not metered for a user +| The user draws from an unlimited pool, or the assigned pools do not match the active `entity_type` of the cluster. +| Ensure all pool keys use the metering scope of the cluster, and verify that `has_unlimited_pool` is `false`. + +| The usage counter does not appear in the embed +| The configuration is missing, the display mode threshold is not met, or the SDK version is earlier than 1.53.0. +| Ensure that the SDK version is 1.53.0 or later, `isEnabled` is `true`, the display mode criteria are met, and the user maps to a valid pool. + +| HTTP 403 Forbidden on REST API calls +| The token does not have the required cluster-level privileges. +| Use a token for a user with the cluster-level *Can administer ThoughtSpot* (`ADMINISTRATION`) privilege. `CAN_MANAGE_SPOTTER` and Org-level administrator privileges are not sufficient. + +| HTTP 400 Bad Request on update +| The request uses an `entity_type` that differs from the one set by the existing pools on the cluster. +| Use the `entity_type` that the existing pools on the cluster use. + +| The counter does not change after an upgrade +| The embed state was not refreshed after the API update. +| Trigger `HostEvent.SpotterRefreshUsageLimit` immediately after the server-side update. +|=== + +== Limitations + +* **No administration UI**. + +You can manage usage pools only using the REST APIs. ThoughtSpot Cloud does not provide a UI for pool management. +* **Beta REST APIs**. + +The endpoints may change before they become Generally Available (GA). +* **Manual reset cycle**. + +ThoughtSpot does not support automatic scheduled resets, such as monthly resets. Use an external scheduler or a backend job that calls the REST API. +* **Single metering scope per cluster**. + +Switching between the `USER`, `USER_GROUP`, and `ORG` scopes requires you to delete all active pools on the cluster. +* **Shared pool consumption**. + +In group or Org metering, any member can consume the shared allowance. Per-user sub-caps and rate limits within shared pools are not supported. +* **Multi-Org contexts**. + +With the `ORG` scope, users who belong to multiple Orgs have a separate usage context for each Org, and draw from each Org pool independently as they switch Orgs. + +== Additional resources + +* xref:spotter-usage-data-api.adoc[Spotter usage data APIs] +* xref:customize-spotter-embed.adoc[Customizing the Spotter embed view] +* xref:embed-spotter.adoc[Embed Spotter] +* xref:rest-api-v2-reference.adoc#_ai[REST API v2.0 Reference] diff --git a/modules/ROOT/pages/spottercode-integration.adoc b/modules/ROOT/pages/spottercode-integration.adoc index 5a5e4ac08..09046cd4c 100644 --- a/modules/ROOT/pages/spottercode-integration.adoc +++ b/modules/ROOT/pages/spottercode-integration.adoc @@ -44,6 +44,8 @@ This is the primary authentication flow for developers connecting an MCP client The session token is stored in a secure backend store. Contact your ThoughtSpot administrator if you encounter repeated authentication prompts. ==== +// If the ThoughtSpot instance of the user has multiple Orgs, SpotterCode allows listing the Orgs they can access and switching the active Org during a session without reauthenticating. For more information, see xref:spottercode.adoc#_multi_org_support[Multi-Org support]. + === Bearer token authentication For programmatic or CI/CD scenarios where an MCP client cannot perform an interactive login, SpotterCode accepts a bearer token directly using a dedicated MCP Server endpoint: `https://spottercode.thoughtspot.app/bearer/mcp`. diff --git a/modules/ROOT/pages/spottercode-prompt-guide.adoc b/modules/ROOT/pages/spottercode-prompt-guide.adoc index 807bbf8f6..4ddc42e39 100644 --- a/modules/ROOT/pages/spottercode-prompt-guide.adoc +++ b/modules/ROOT/pages/spottercode-prompt-guide.adoc @@ -89,6 +89,39 @@ How do I create a new user with admin privileges via REST API? Provide the endpo |How do I see new actions in my app? | How do I get a list of custom actions added in my embed via REST API? |===== + +//// +=== Working with multiple Orgs +If your ThoughtSpot instance has Orgs enabled and you are connected via OAuth or SAML authentication, you can use SpotterCode to discover and switch between Orgs without leaving your IDE. + +[width="100%" cols="4,4" role="copy-cell-table prompt-guidance-table"] +[options='header'] +|===== +|Vague prompt|Clear prompt + +|What org am I in? +|Which Org is currently active in my SpotterCode session? + +|Show me my orgs +|List all Orgs I have access to on my ThoughtSpot instance, and indicate which one is currently active. + +|Switch org +|Switch my active Org to the one named "Sales EMEA" and confirm the switch was successful. + +|I can't find my Liveboard +a|I can't find a Liveboard called "Revenue Overview." List all Orgs I have access to — it may be in a different Org. Then switch to each Org and check whether the Liveboard exists there. + +|Use a different org for my API calls +|Switch to the Org with ID `123456` and then retrieve a list of all Liveboards in that Org via the REST API. +|===== + +[NOTE] +==== +The active Org selection is shared across all your active sessions. If you switch Orgs in one session, the change applies to all other concurrent sessions for your user account. +==== +//// + + == Prompting in the Visual Embed Playground The Visual Embed Playground includes a built-in SpotterCode panel with quick-starter prompts for each embed component. You can use these as starting points and refine them with follow-up prompts. diff --git a/modules/ROOT/pages/spottercode.adoc b/modules/ROOT/pages/spottercode.adoc index 0b29f2e5e..4502d5466 100644 --- a/modules/ROOT/pages/spottercode.adoc +++ b/modules/ROOT/pages/spottercode.adoc @@ -75,6 +75,14 @@ The full-capability SpotterCode endpoint. Requires authentication with a Thought a| `get-rest-api-reference` + `get-developer-docs-reference` + `execute-thoughtspot-code` +//// +ORG AWARENESS (unpublished): when ready, replace the `execute-thoughtspot-code` line above with the lines below. +`execute-thoughtspot-code` + +`list_orgs` + +`switch_org` + +__The `list_orgs` and `switch_org` are available only on ThoughtSpot instances with Orgs enabled. These tools require OAuth or SAML authentication and are not available when connecting via the Bearer token endpoint (`/bearer/mcp`)__ +//// a| *Documentation endpoint* + (`/mcp/docs`) @@ -96,18 +104,40 @@ Provides access to documentation on embedding, UI customization, deployment, sec * `execute-thoughtspot-code` + Executes authenticated ThoughtSpot API workflows directly from your IDE agent. This skill allows your IDE agent to perform common operations that can be done via public REST APIs. +//// +* `list_orgs` + +Lists all Orgs the authenticated user can access on the connected ThoughtSpot instance. Each Org entry includes its `id`, `name`, and `description`. The currently active Org is indicated by `is_active: true`. ++ +This tool is available only on ThoughtSpot instances with Orgs enabled and requires OAuth or SAML authentication. It is not available when connecting via the Bearer token endpoint (`/bearer/mcp`). + +* `switch_org` + +Switches the active Org for the current authenticated session. All subsequent tool calls operate in the context of the selected Org. + ++ +Accepts a single input, `org_id`, which is the ID of the Org to switch to (returned by `list_orgs`). Returns `success: true` if the switch succeeded. If the switch fails, the active Org is unchanged. ++ +[IMPORTANT] +==== +The active Org selection is stored per user, not per conversation. If two concurrent AI sessions switch to different Orgs, the last operation takes effect for both sessions. The selection persists across reconnects and resets only on re-authentication or after a period of inactivity. +==== ++ +This tool is available only on ThoughtSpot instances with Orgs enabled and requires OAuth or SAML authentication. It is not available when connecting via the Bearer token endpoint (`/bearer/mcp`). +//// + === Choosing the right endpoint -Use the following guidance to decide which endpoint to configure in your IDE: +Use the following guidance to decide which endpoint to configure in your IDE. -* *Use `/mcp` (authenticated)* if: -** You want the AI agent to execute ThoughtSpot API workflows from your IDE, for example, to generate a trusted authentication secret key, configure your application domain in CORS/CSP allowlists, or retrieve Liveboard and Answer object IDs from your instance. -** You want your IDE to use the full set of SpotterCode skills, including `run-ts-workflow`. -** You are building or configuring a ThoughtSpot embedded application and want end-to-end setup assistance without leaving the IDE. +Use `/mcp` (authenticated) if:: -* *Use `/mcp/docs` (unauthenticated)* if: -** You only need the AI agent to look up documentation, REST API reference material, and code samples. -** You are working in an environment where connecting to a ThoughtSpot instance is not appropriate. For example, a shared CI environment, a read-only developer workstation, or a demonstration setup. -** You do not have a ThoughtSpot Embedded subscription or instance credentials available. +* You want the AI agent to execute ThoughtSpot API workflows from your IDE, for example, to generate a trusted authentication secret key, configure your application domain in CORS/CSP allowlists, or retrieve Liveboard and Answer object IDs from your instance. +* You want your IDE to use the full set of SpotterCode skills, including `execute-thoughtspot-code`. +* You are building or configuring a ThoughtSpot embedded application and want end-to-end setup assistance without leaving the IDE. +// * Your ThoughtSpot instance uses Orgs and you want the AI agent to list or switch Orgs during a session. Use the `list_orgs` and `switch_org` tools with this endpoint. + +Use `/mcp/docs` (unauthenticated) if:: +* You only need the AI agent to look up documentation, REST API reference material, and code samples. +* You are working in an environment where connecting to a ThoughtSpot instance is not appropriate. For example, a shared CI environment, a read-only developer workstation, or a demonstration setup. +* You do not have a ThoughtSpot Embedded subscription or instance credentials available. +// * You do not need org-switching capabilities. The `/mcp/docs` unauthenticated endpoint does not support `list_orgs` or `switch_org`. [NOTE] ==== @@ -151,6 +181,33 @@ Because code executes as the authenticated user, write operations, such as creat SpotterCode performs operations as the authenticated user. Grant SpotterCode access only to accounts with the minimum permissions required for the intended use case. ==== +//// +[#_multi_org_support] +== Multi-Org support + +If your ThoughtSpot instance has Orgs enabled, SpotterCode can list and switch between Orgs during a session. By default, SpotterCode operates in the Org that was active when you authenticated. To work with resources in a different Org, use the `list_orgs` and `switch_org` tools. + +=== How it works +When you switch to a different Org using `switch_org`, SpotterCode mints a new per-Org session token scoped to that Org and stores it for your user account. Subsequent tool calls use this token and operate within the selected Org. The selection persists across reconnects until you re-authenticate or the session expires after a period of inactivity. +The active Org selection is stored per user, not per conversation. If you have multiple active AI sessions, the last `switch_org` call takes effect across all sessions. Plan org switches accordingly when running concurrent sessions. + +To check which Org you are in and switch to a different Org, use the following prompts in your IDE agent: + +. Ask the agent to list your available Orgs: ++ +`List all Orgs I have access to on my ThoughtSpot instance.` + ++ +The agent calls `list_orgs` and returns a list of Orgs. The currently active Org is marked with `is_active: true`. + +. Ask the agent to switch to the Org you want to work in: ++ +`Switch to the Sales EMEA Org.` + ++ +The agent calls `switch_org` with the corresponding `org_id`. After a successful switch, all subsequent API calls operate within that Org. +//// + == Limitations * Responses from SpotterCode are determined by the features and parameters currently supported in the Visual Embed SDK, REST API, and official ThoughtSpot developer documentation. SpotterCode cannot generate code or solutions that rely on unsupported or undocumented features. * SpotterCode can generate code samples for the most common use cases. Scenarios that require advanced customization or highly specialized workflows may require manual intervention or additional coding beyond what SpotterCode provides. diff --git a/modules/ROOT/pages/whats-new.adoc b/modules/ROOT/pages/whats-new.adoc index 105506f12..56b2790d5 100644 --- a/modules/ROOT/pages/whats-new.adoc +++ b/modules/ROOT/pages/whats-new.adoc @@ -23,6 +23,102 @@ This page lists new features, enhancements, and deprecated functionality introdu // ============================================================ +== November 2026 + +**Release version**: ThoughtSpot Cloud 26.11.0.cl + +*Upgrade notes*: Includes API rate limit enforcement and new REST API endpoints. Review the details in this page and the xref:rest-apiv2-changelog.adoc[REST API v2.0 changelog]. + +*Recommended SDK versions*: Visual Embed SDK v1.54.0 or later + +[.cl-table, cols="2,4", frame=none, grid=none] +|=== +a| +[.cl-label] +*Version 26.11.0.cl* + +a| + +[discrete] +==== New Spotter experience in embedded apps +ThoughtSpot introduces the new Spotter experience, including Spotter on Liveboards. Spotter opens in a side panel on a Liveboard and uses the entire board, its charts, tabs, and applied filters, as conversation context. Conversations are saved with the Liveboard so users can return to them later. + +In embedded apps, the new experience is opt-in. To enable it, set `spotterExperienceVersion` to `SpotterExperienceVersion.SPOTTER_2026_11` in your embed configuration. Existing Spotter embeds remain unchanged unless explicitly opted in. + +For more information, see xref:embed-new-spotter.adoc[Embed the new Spotter experience]. + +--- + +[discrete] +==== Org-level API rate limiting enforced +The Org-level rate limit of 50 requests per second (RPS) per Org is now enforced for all public REST API endpoints on instances with Orgs enabled. Requests exceeding the limit receive an `HTTP 429: Too Many Requests` response. For more information, see xref:about-rest-apis.adoc#_rate_limits_for_api_requests[Rate limits for API requests]. + +--- + +[discrete] +==== Link Customization APIs +New REST API v2.0 endpoints to manage the URL templates ThoughtSpot uses when generating shareable links, so links in scheduled emails and Share dialogs can point to your embedding application: + +* `POST /api/rest/2.0/customization/links/search` +* `POST /api/rest/2.0/customization/links/update` + +For more information, see xref:link-customization-api.adoc[Link Customization APIs]. + +--- + +[discrete] +==== Input Table APIs +ThoughtSpot introduces new REST API endpoints to create and manage input tables, which are user-editable tables stored in your Cloud Data Warehouse and linked to a ThoughtSpot model. + +For more information, see xref:input-table-api.adoc[Input Table APIs]. +--- + +[discrete] +==== Spotter usage limits +Administrators can now set Spotter question allowances for users, user groups, or Orgs. You can configure and manage usage limits using the following options: + +* Visual Embed SDK: Show and customize the usage counter, banners, and *Upgrade* button in embedded Spotter using `spotterUsageLimitConfig`. +* REST API: Manage usage pools using the xref:spotter-usage-data-api.adoc[Spotter usage limit] API endpoints. + +For more information, see xref:spotter-usage-limits.adoc[Manage Spotter usage limits]. + +--- + +[discrete] +==== Programmatically update Liveboard filters [earlyAccess eaBackground]#Early Access# +You can now programmatically update Liveboard filters in embedded apps at runtime. This feature is in Early Access and disabled by default. To enable this feature, contact ThoughtSpot Support. For more information, see xref:runtime-filters.adoc[Runtime filters]. +// TODO: verify with engineering - exact API surface (SCAL-280403) + +--- + +[discrete] +==== RBAC enabled by default for new instances +Role-Based Access Control (RBAC) is enabled by default on newly provisioned ThoughtSpot instances. Existing instances are unaffected. For more information about RBAC and roles, see xref:roles.adoc[Role-Based Access Control]. + +--- + +[discrete] +==== New locales +ThoughtSpot Embedded now supports four additional display languages: + +* Polish (`pl-PL`) +* Romanian (`ro-RO`) +* Turkish (`tr-TR`) +* Ukrainian (`uk-UA`) +For more information, see xref:locale-setting.adoc[Customize locale]. + +--- + +[discrete] +==== Visual Embed SDK +For information about the new features and enhancements introduced in Visual Embed SDK version 1.54.0, see the xref:api-changelog.adoc[Visual Embed SDK changelog]. + +--- + +[discrete] +==== REST API v2 +For information about REST API v2.0 enhancements in this release, see the xref:rest-apiv2-changelog.adoc[REST API v2.0 changelog]. + +|=== + == October 2026 **Release version**: ThoughtSpot Cloud 26.10.0.cl + @@ -37,6 +133,15 @@ a| a| +//// +[discrete] +==== SpotterCode Org awareness +SpotterCode now supports new `list_orgs` and `switch_org` tools to allow users to get a list of the Orgs they can access and switch to without leaving the IDE. +For more information, see xref:spottercode.adoc#_multi_org_support[Multi-Org support in SpotterCode]. + +--- +//// + [discrete] ==== Spotter Analyst diff --git a/src/assets/fonts/BB-Roller-Mono-Regular.otf b/src/assets/fonts/BB-Roller-Mono-Regular.otf old mode 100755 new mode 100644 diff --git a/src/configs/doc-configs.js b/src/configs/doc-configs.js index 2edc6b6bb..de8224dd7 100644 --- a/src/configs/doc-configs.js +++ b/src/configs/doc-configs.js @@ -22,8 +22,8 @@ module.exports = { // 'https://developers.thoughtspot.com/docs/26.3.0.cl?pageid=whats-new' // - GA: ' /docs/whats-new' //linkHref: '/docs/whats-new', - linkHref: '/docs/26.10.0.cl?pageid=whats-new', - linkText: 'Version 26.10.0.cl', + linkHref: '/docs/26.11.0.cl?pageid=whats-new', + linkText: 'Version 26.11.0.cl', openInNewTab: true, }, TYPE_DOC_PREFIX: 'typedoc', @@ -48,10 +48,16 @@ module.exports = { }, VERSION_DROPDOWN: [ { - label: '26.10.0.cl', + label: '26.11.0.cl', link: ' ', subLabel: 'Cloud (Latest)', - iframeUrl: 'https://developer-docs-26-10-0-cl.vercel.app/docs/', + iframeUrl: 'https://developer-docs-26-11-0-cl.vercel.app/docs/', + }, + { + label: '26.10.0.cl', + link: '26.10.0.cl', + subLabel: 'Cloud', + iframeUrl: 'https://developer-docs-26-10-0-cl.vercel.app/docs/', }, { label: '26.9.0.cl',