REST API v1 authentication

REST API v1 authentication

To create, access, and modify ThoughtSpot objects and resources through the REST API, you must log in as an authorized user. A successful login operation returns session cookies from the ThoughtSpot system, which must be included in subsequent REST API calls.

When using the REST API through a web browser, ThoughtSpot recommends that you use the SAML SSO or trusted authentication service to authenticate to ThoughtSpot. A successful login using the Visual Embed SDK via either of those two methods will establish the session within the web browser.

Basic authenticationπŸ”—

In the basic authentication method, REST clients can access ThoughtSpot objects using username and password parameters and programmatically sign in to ThoughtSpot using the /tspublic/v1/session/login API.

Resource URLπŸ”—

POST /tspublic/v1/session/login

Request ParametersπŸ”—

Form parameterDescription

username

String. Username of the user account.

password

String. The password of the user account.

rememberme

Boolean. A flag to remember the user session. When set to true, a session cookie that persists in subsequent API calls is set. The system default is false.

Example requestsπŸ”—

cURL
curl -X POST \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Accept: application/json' \
--header 'X-Requested-By: ThoughtSpot' \
-d 'username=test&password=fhfh2323bbn&rememberme=false'\
'https://{ThoughtSpot-Host}/callosum/v1/tspublic/v1/session/login'
Request URL
https://{ThoughtSpot-Host}/callosum/v1/tspublic/v1/session/login

Response codesπŸ”—

HTTP status codeDescription

200

User logged in

204

Successful login

401

Login failure/unauthorized request

A successful login returns a session cookie that can be used in your subsequent API calls. For more information, see Session cookies for subsequent API calls.

Trusted authenticationπŸ”—

For trusted authentication, you must obtain a token from ThoughtSpot via /tspublic/v1/session/auth/token and send it in your login request to the /tspublic/v1/session/login/token API endpoint.

Obtain a token for trusted authenticationπŸ”—

If you have enabled trusted authentication on ThoughtSpot and have access to the secret key, you can send an API request to the /tspublic/v1/session/auth/token endpoint and get a login token for a ThoughtSpot user.

After you get the authentication token from ThoughtSpot via a REST API call to the /tspublic/v1/session/auth/token endpoint, use this token in your API request to the /tspublic/v1/session/login/token endpoint to authenticate and log in a user.

Just-in-time provisioning and dynamic group assignmentπŸ”—

Starting from 8.9.0.cl, the /tspublic/v1/session/auth/token API endpoint supports adding a user Just-in-Time (JIT) and dynamically assigning groups and privileges. If a user for whom you want to request an authentication token doesn’t exist in the ThoughtSpot system, you can set the autocreate and groups properties in the API call to add the user and assign groups.

Resource URLπŸ”—

POST /tspublic/v1/session/auth/token

Request parametersπŸ”—

Form parameterDescription

secret_key

String. The secret key string provided by the ThoughtSpot application server. ThoughtSpot generates this secret key when you enable trusted authentication on an application instance.

username

String. The username of the user configured in ThoughtSpot.

If the user doesn’t exist in the ThoughtSpot system, you can set the autocreate flag to true to create a user account in ThoughtSpot.

email
Optional

String. Email address of the user. Specify a value for this parameter if provisioning a user just-in-time (JIT).

display_name
Optional

String. Display name of the user. Specify a value for this parameter if adding a user just-in-time (JIT).

access_level

String. User access privilege. Valid values are:

  • FULL - Creates a session with full access.

  • REPORT_BOOK_VIEW - Allows view access to the visualization or Liveboard.

id

String. GUID of the ThoughtSpot object. If you have set the access_level attribute to REPORT_BOOK_VIEW, specify the GUID of the Liveboard or visualization object.

orgid

Integer. ID of the Org to which the user belongs. This parameter is required if your ThoughtSpot instance is set as a multi-tenant environment and logically partitioned into Orgs.

  • If the user exists in ThoughtSpot and no orgid is specified, the API returns the authentication token to log the user in to their last logged-in Org.

  • If the user exists in ThoughtSpot but is not assigned to any Org, and autocreate is set to true, the user will be added to the specified Org.

  • If the user doesn’t exist in ThoughtSpot and autocreate is set to true, the user is created and added to the specified Org ID.

  • If the user already exists in the ThoughtSpot system, and the user does not belong to the specified orgid, the API returns an error.

Note

Org IDs are integers that are created automatically when a cluster administrator creates an Org. To know the Org IDs of Orgs, send a GET request to the /tspublic/v1/session/orgs API endpoint. If you have cluster administrator privileges, you can use the /tspublic/v1/org/search endpoint to get a list of all Orgs available on your cluster.

groups Optional

String. A JSON array of groups to which the user belongs. For example, ["sales", "marketing"].

  • If the user doesn’t exist in ThoughtSpot and autocreate is set to true, the user is assigned to the specified groups.

  • If the user already exists in the ThoughtSpot system and autocreate is set to false, the API ignores the values specified in the groups attribute.

  • If the user already exists in the ThoughtSpot system and autocreate is set to true, the API updates the user object.

  • If autocreate is set to true and the group names are not defined in the groups property, ThoughtSpot does not update the user object.

autocreate Optional

Boolean. When set to true, if the specified username does not exist in the ThoughtSpot system, a new user is created without a password. By default, the autocreate property is set to false.

Example requestπŸ”—

cURL
curl -X POST \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Accept: text/plain' \
-d 'secret_key=82749a88-1506-4cd9-803c-8316c7d41d7c&username=testUser2&access_level=FULL&groups=%5B%22sales%22%2C%20%22marketing%22%5D&autocreate=true' \
'https://{ThoughtSpot-Host}/callosum/v1/tspublic/v1/session/auth/token'
Request URL
https://{ThoughtSpot-Host}/callosum/v1/tspublic/v1/session/auth/token

Example responseπŸ”—

If the API request is successful, ThoughtSpot returns an authentication token for the user.

Note
  • If the username specified in the API request exists in the ThoughtSpot system, the API returns the token, else it returns the user not found error.

  • If the user does not exist in ThoughtSpot and the autocreate property is set to true, the user is created. If groups and orgid attributes are defined, ThoughtSpot assigns the user to the specified groups and Org ID.

  • If the user already exists in ThoughtSpot, autocreate is set to true, and the group names are defined in the groups attribute, the user will be added to the groups specified in the API request. Similarly, if you have specified the orgid with autocreate set to true, the user will be assigned to the specified Org.

  • When autocreate is set to true, if the groups specified in the groups attribute do not exist in the specified Org ID, ThoughtSpot will create groups in the specified Org ID and assign the user to these groups.

  • The authentication token returned by ThoughtSpot can be used to access only the Org specified in the API request. If the client must be logged in to another Org, you must send another API request to get an authentication token from ThoughtSpot.

The following example shows the authentication token returned by ThoughtSpot after a successful API call.

JHNoaXJvMSRTSEEtMjU2JDUwMDAwMCRPMFA2S0ZlNm51Qlo4NFBlZUppdzZ3PT0kMnJKaSswSHN6Yy96ZGxqdXUwd1dXZkovNVlHUW40d3FLMVdBT3hYVVgxaz0

Response codesπŸ”—

HTTP status codeDescription

200

The authentication token is generated successfully

400

Invalid parameter value

401

Unauthorized request or invalid token

500

Token-based trusted authentication is not enabled on ThoughtSpot

Authenticate and log in with a token (trusted authentication)πŸ”—

To authenticate and log in a user, you must obtain a login token from the ThoughtSpot system. After you receive the login token, you can send the authentication attributes to the /tspublic/v1/session/login/token endpoint using a POST or GET request.

  • GET /tspublic/v1/session/login/token

    This request method sends the user authentication attributes as query string parameters in the request URL.

  • POST /tspublic/v1/session/login/token (Recommended)

    This request method sends the user authentication attributes as formData parameters in the request body of the API call. For secure exchange of authentication information, we recommend using the POST request method.

Resource URLsπŸ”—

GET /tspublic/v1/session/login/token
POST /tspublic/v1/session/login/token

Request parametersπŸ”—

ParameterDescription

username

String. The username of the user who requested access to ThoughtSpot.

auth_token

String. The authentication token obtained from ThoughtSpot.

redirect_url

String. The URL to which you want to redirect the user after a successful login. This URL is fully encoded and includes the authentication token obtained for the user.

https://<redirect-domain>/?authtoken=<user_auth_token>&embedApp=true&primaryNavHidden=true#/embed/viz/<pinboard_id>/<viz-id>

For example, if the user has requested access to a specific visualization on a Liveboard, the redirect URL includes the host domain to which the user will be redirected, the authentication token, and the visualization and Liveboard IDs.

no_url_redirection

Boolean. By default, the API returns a 302 code and redirects the user to the requested URL. If you do not want to redirect users, set this parameter to true.

Example requestsπŸ”—

The following example shows a GET request with query parameters in the request URL:

cURL
curl -X GET \
--header 'Accept: text/html' \
--header 'X-Requested-By: ThoughtSpot' \
'https://{ThoughtSpot-Host}/callosum/v1/tspublic/v1/session/login/token?username=tsuser&auth_token=JHNoaXJvMSRTSEEtMjU2JDUwMDAwMCRPMFA2S0ZlNm51Qlo4NFBlZUppdzZ3PT0kMnJKaSswSHN6Yy96ZGxqdXUwd1dXZkovNVlHUW40d3FLMVdBT3hYVVgxaz0&redirect_url=https://{ThoughtSpot-Host}/?embedV2=true#/pinboard/7a9a6715-e154-431b-baaf-7b58246c13dd%2F'
Request URL
https://{ThoughtSpot-Host}/callosum/v1/tspublic/v1/session/login/token?username=tsadmin&auth_token=JHNoaXJvMSRTSEEtMjU2JDUwMDAwMCRPMFA2S0ZlNm51Qlo4NFBlZUppdzZ3PT0kMnJKaSswSHN6Yy96ZGxqdXUwd1dXZkovNVlHUW40d3FLMVdBT3hYVVgxaz0&redirect_url=https://{ThoughtSpot-Host}/?embedV2=true#/pinboard/7a9a6715-e154-431b-baaf-7b58246c13dd%2F

The following example shows a POST request with authentication attributes in the request body:

cURL
curl -X POST \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Accept: text/plain' \
-d 'username=tsadmin&auth_token=JHNoaXJvMSRTSEEtMjU2JDUwMDAwMCRyNGRXRmsxclVVOFY3dXJjTUNGMUh3PT0kSlZwSTZQZUl2Zm5iQjIwWlZ2Nzd2VysvMUpmTmFSL21sRDFLbTNWNWk3QT0&redirect_url=https://{ThoughtSpot-Host}/?embedV2=true#/pinboard/7a9a6715-e154-431b-baaf-7b58246c13dd%2F&no_url_redirection=false' \
'https://{ThoughtSpot-Host}/callosum/v1/tspublic/v1/session/login/token'
Request URL
https://{ThoughtSpot-Host}/callosum/v1/tspublic/v1/session/login/token

Example responseπŸ”—

If the API request is successful, ThoughtSpot returns the following:

  • If no_url_redirection is set to true, the API returns 204 response code.

  • If no_url_redirection is set to false, the API returns a response body and redirects the user to the requested URL.

    <!doctype html>
    <html lang="en">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width">
        <meta charset="utf-8">
        <meta name="description" content="">
            <!-- Preloading Fonts -->
            <link rel="preload" href="node_modules/@thoughtspot/radiant/widgets/resources/font/optimo/Plain-Light.otf"
                  as="font" crossorigin>
            <link rel="preload" href="node_modules/@thoughtspot/radiant/widgets/resources/font/bb-roller/BB-Roller-Mono-Regular-fontlab.ttf"
                  as="font" crossorigin>
            <link rel="preload" href="node_modules/@thoughtspot/radiant/widgets/resources/font/optimo/Plain-Regular.otf"
                  as="font" crossorigin>
            <link rel="preload" href="node_modules/@thoughtspot/radiant/widgets/resources/font/optimo/Plain-Medium.ttf"
                  as="font" crossorigin>
            <link rel="preload" href="node_modules/@thoughtspot/radiant/widgets/resources/font/optimo/Plain-LightIta.otf"
                  as="font" crossorigin>
            <link rel="modulepreload" href="https://cdn.skypack.dev/react">
    	<link rel="modulepreload" href="https://cdn.skypack.dev/react-dom">
        <link rel="stylesheet" href='(none)'>
        <style>
            .bk-app-loading-indicator {
        position: absolute;
        height: 100%;
        width: 100%;
        display: -webkit-box;
        display: -moz-box;
        display: -ms-flexbox;
        display: -webkit-flex;
        display: flex;
        flex-direction: row;
        -ms-flex-direction: row;
        -webkit-flex-direction: row;
        align-items: stretch;
        -webkit-align-items: stretch;
        -ms-flex-align: stretch;
        max-width: 100%;
        box-sizing: border-box;
    }
        </style>
    </head>
    <body>
        <div class="bk-app-loading-indicator">
            <div class="load-wrap">
        <div>
            <div class="circle"></div>
            <div class="circle"></div>
            <div class="circle"></div>
        </div>
    </div>
        </div>
    
        <script type="text/javascript" id="app-init">
            // Top level namespace var declaration
            var blink = {};
            // Object to store all CDN related variables
            blink.cdnAutoUpdateConfig = {};
            // Location of Eureka Base URL
            blink.eurekaBasePath = 'https://d2if2nytu6z4ml.cloudfront.net';
            // Keys set in blink.env will override / create flags
            blink.env = {
                dev: false
            };
            blink.commitId = '600e99e3c3ebe1b4d89abd99e920c6939616f54c';
            blink.gitBranch = '(HEAD detached at 600e99e3c3e)';
            blink.buildTimeStamp = 'Thu May 20 2021 09:25:58';
            blink.depsPath = 'node_modules';
            blink.localeSuffix = '.' + blink.commitId;
            blink.metrics = {
                scriptsLoadStartTime: window.performance.now()
            };
    
            function createNode(tag, attributes) {
                var node = document.createElement(tag);
                Object.keys(attributes).forEach(function (key) {
                    return node[key] = attributes[key];
                });
                return node;
            }
            function appendNodesToDom(nodes) {
                var fragment = document.createDocumentFragment();
                nodes.forEach(function (node) {
                    return fragment.appendChild(node);
                });
                document.getElementsByTagName('body')[0].appendChild(fragment);
            }
            function fetchAndLoadRelease(rcLink) {
                fetch(rcLink).then(function (response) {
                    return response.json()
                }).then(function (releaseJson) {
                    blink.cdnAutoUpdateConfig.evaluationMode = true;
                    blink.cdnAutoUpdateConfig.currentReleaseVersion = releaseJson.releaseVersion;
                    blink.cdnAutoUpdateConfig.cdnBuildTimestamp = releaseJson.buildTimestamp;
                    blink.cdnAutoUpdateConfig.cdnBasePath = releaseJson.basePath;
                    var nodes = releaseJson.resources.css.map(function (cssScript) {
                        return createNode('link', {
                            type: 'text/css',
                            rel:'stylesheet',
                            href: [blink.cdnAutoUpdateConfig.cdnBasePath, cssScript].join('/')
                        })
                    });
    
                    nodes = nodes.concat(releaseJson.resources.js.map(function (script) {
                        return createNode('script', {
                            src: [blink.cdnAutoUpdateConfig.cdnBasePath, script].join('/'),
                            async: false
                        });
                    }));
                    nodes = nodes
                        .concat(releaseJson.resources.modules.map(function (module, index) {
                            return createNode('script', {
                                async: false,
                                type: 'module',
                                src: [blink.cdnAutoUpdateConfig.cdnBasePath, module].join('/'),
                                id: 'module-script' + index
                            });
                        }));
                    nodes = nodes
                        .concat(releaseJson.resources.noModule.map(function (noModule, index) {
                            return createNode('script', {
                                async: false,
                                noModule: true,
                                src: [blink.cdnAutoUpdateConfig.cdnBasePath, noModule].join('/'),
                                id: 'nomodule-script' + index
                            });
                        }));
                    appendNodesToDom(nodes);
                }, function (error) {
                    appendNodesToDom([createNode('div', {
                        innerText: 'unable to fetch: ' + rcLink +
                        'Link does not exist'
                    })]);
                });
            }
            var ua = window.navigator && window.navigator.userAgent;
            var trident = ua && ua.indexOf('Trident/');
            var edge = ua && ua.indexOf('Edge');
            var safari = ua && ua.indexOf('Safari');
            var chrome = ua && ua.indexOf('Chrome');
    
        </script>
    
            <link type="text/css" rel="stylesheet" href="resources/css/all.min.90630a0a141abec0.css">
    
            <script src="js/lib.min.bcef417e2b193abd.js"></script>
            <script src="js/templates.133e974a290769f7.js"></script>
            <script src="js/all.min.b4be265ed3041f65.js"></script>
            <script type="module" src="js/module/app-ad896427.js
    " id="module-script"></script>
            <script nomodule src="js/nomodule/app.js" id="nomodule-script"></script>
        <app-controller class="bk-app-controller-container"></app-controller>
    </body>
    </html>

Response codesπŸ”—

HTTP status codeDescription

200

The user is logged in successfully.

204

No URL redirection.

302

The user is redirected to the specified URL.

401

Unauthorized request or invalid token.

Session cookies for subsequent API callsπŸ”—

If the login operation is successful, the API returns cookie details in the response header.

Set-Cookie: JSESSIONID=b9a5b821-fa91-49ea-99fc-12817a141e76; Path=/; HttpOnly
Set-Cookie: clientId=76d83461-1b8a-425a-9116-66c8d6f006bb; Path=/; Secure; HttpOnly

The session cookie is automatically set in the request header when you make your subsequent API calls via a web browser. REST clients in a non-browser environment must pass this cookie in the request header in their subsequent API calls.

Make a test API callπŸ”—

You can make a test API call to verify if your token is valid and allows access to ThoughtSpot objects. For example, you can send a GET request /tspublic/v1/metadata/listvizheaders to fetch the visualization headers of a Liveboard.

Note that if you are using a Web browser or Postman to make a REST API call, the session cookie obtained from the /tspublic/v1/session/login/token or /tspublic/v1/session/login API call is automatically set. REST clients in a non-browser environment must include the session cookie in the request header as shown in the following example:

curl -X GET \
--header 'Accept: text/html' \
--header 'X-Requested-By: ThoughtSpot' \
--header 'Cookie: JSESSIONID=fc3424f9-d3f0-4a24-bd33-400fd826cac7; clientId=70cf1328-af97-40b2-9bd5-1c520e133963' \
'https://{ThoughtSpot-Host}/callosum/v1/tspublic/v1/metadata/listvizheaders?id=d084c256-e284-4fc4-b80c-111cb606449a'

Once the session is established in the browser, you can set the withCredentials: true property for any XMLHttpRequest object or credentials: "include" as part of a Fetch object to pass the cookies along when making REST API requests:

// Simple XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

// Using Fetch with Promises
return async fetch(
            apiFullEndpoint, {
            method: 'GET',
            headers: {
                "Accept": "application/json",
                "X-Requested-By": "ThoughtSpot"
            },
            credentials: "include"
            })
Note

If you are accessing the REST API outside a web browser, create a long-lived session object in your code, and then call the login API using that session object. Make subsequent REST API calls with the same session object to send the session cookies along with the other aspects of the REST API call.

Log out of a user sessionπŸ”—

To log a user out of the current session, use the /tspublic/v1/session/logout API.

Resource URLπŸ”—

POST /tspublic/v1/session/logout

Example requestπŸ”—

cURL
curl -X POST \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Requested-By: ThoughtSpot'
'https://{ThoughtSpot-Host}/callosum/v1/tspublic/v1/session/logout'
Request URL
https://{ThoughtSpot-Host}/callosum/v1/tspublic/v1/session/logout

If the logout request is sent as an AJAX call, add the following parameter to send credentials with the request:

xhrFields: { withCredentials: true }

Response codesπŸ”—

HTTP status codeDescription

200

User logged out

204

Successful log out of user

401

Logout failure/unauthorized request