Skip to end of metadata
Go to start of metadata

You can use the API as follows:

  • Use the built-in API visualization tool located in your dashboard’s management area. You can use this tool to execute API calls from your browser to your dashboards.
  • You can call the API from outside the Sisense web environment. For example, you can create a python script that adds Sisense users in bulk. To call the API, you will need a security token.

Click on a method below to learn more.

Using the REST API in the Sisense Web Environment

You can access the API reference documentation and run queries from within Sisense.

To access the API:

  1. Log into the Sisense web app.
  2. Click ADMIN in the top-right of the screen, and click REST API in the left menu.
  3. Click REST API Reference to view the list of operations. Operations are listed by category.
  4. For each operation, you can enter parameters where relevant, and click RUN to call the API in real time. Refresh your dashboard to see updates. See the following example.

Sisense Web Usage Example

In the following example, we want to see metadata for a specific user.

Using the GET /users/{user} operation, you can enter the user's email in the user parameter field, and click RUN. In the Response Body below, you can see all of the user's metadata, including the user's name, creation date, etc. 

Note

You do not need a token to use the internal tool. Security is managed using your browser cookies.

Accessing the REST API from External Tools

This method requires a security token. The security token provides you secure access to the API from external scripts and tools.

  1. Log into the Sisense web app.
  2. Click MANAGE in the top-right of the screen, and click REST API in the left menu.
  3. Click ISSUE TOKEN to generate a token. If you need to renew the token for security reasons, click RENEW.

    Note

    To generate a token without going into the web app, type the following URL in your browser:

    http://localhost:8081/api/settings/api/generate
  4. Click REST API Reference to view the list of operations and API documentation.

To pass the token, you must add the token to the X-Api-Key header (X-Api-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX) with the following attributes:

Attribute

Mandatory

Description

iat

Yes

The time the token was generated and issued. The value must be the number of seconds since UNIX epoch. Sisense allows up to 5 minutes clock skew.

email

Yes

Email of the Admin user initiating the request, used to uniquely identify the Admin user in Sisense.

password

Yes

Password of the Admin user initiating the request, used to validate the Admin user in Sisense.

exp

No

Expiration time of the token. After that time the token becomes invalid and all corresponding requests will fail. If not present, the token will expire after one week.The value must be the number of seconds since UNIX epoch.

aud

No

Intended audience for this token. The value can be a collection of strings or a single string; if present, it must contain the string “sisense” (lowercase).

Examples

SisenseRestJwtSample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// <summary>
/// Summary description for SisenseJwtSample
/// </summary>
public class SisenseJwtSample
{
	public SisenseJwtSample()
	{
		//
		// TODO: Add constructor logic here
		//
	}

    public void SisneseRest(HttpContext context)
    {
        TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
        int timestamp = (int)t.TotalSeconds;

        var payload = new System.Collections.Generic.Dictionary<string, object>() {
                { "iat", timestamp },
                 { "email", "[email protected]" },
		 { "password", "123456" },
                 // Optional properties
                 //{ "exp", (int)t.AddMinutes(30).TotalSeconds  }, // Expiration time
                 //{"aud", new string [] {"sisense" } } // A collection of audience strings OR a single string. must contain the string "sisense" 
            };

  	string token = JWT.JsonWebToken.Encode(payload, SHARED_KEY, JWT.JwtHashAlgorithm.HS256);

      WebClient _client = new WebClient();

      _client.Headers["X-API-KEY"] = token;

      _client.DownloadString("http://localhost/api/someApi");

      
    }
}
sisenseRestJwtSample.js
var jwt = require('jwt-simple');
var url = require('url');

function callAPI(request, response) {

    var payload = {
        iat: (new Date().getTime() / 1000),
        email: "[email protected]",
	password: "123456"
        // exp: ((new Date().getTime() + 180 * 60000 )/ 1000) // expires in 3 hours
        // aud: ["sisense"]
    };

    // encode
    var token = jwt.encode(payload, "my_shared_key");
   

   request.writeHead({
        'x-api-key': token
    });


    response.end();
}
SiSenseRestJWTSample.php
<?php
// PHP-JWT library: https://github.com/firebase/php-jwt
include_once "./lib/JWT.php";
$key = "my_shared_key";
$now = time();
$token = array(
 "iat" => $now,
 "email" => "[email protected]",
 "password" => "123456"
 // "aud" => array("sisense"), // optional: audience array (must contain the value "sisense"
 // "exp" => $now + 1000 // optional: expiration time
 );
$jwt = JWT::encode($token, $key);
header("x-api-key: " . $jwt);
 ?>
sisense_rest_jwt_example.rb
require "jwt" # get the JWT gem by 'gem install jwt'; see https://github.com/progrium/ruby-jwt
 require 'uri'
 require 'net/http'
size = 1000 #the last offset (for the range header)
 uri = URI("http://localhost/api/someApi")
 http = Net::HTTP.new(uri.host, uri.port)
 secret = "my_shared_key"
 iat = Time.now.to_i
 email = "[email protected]"
 password="123456"
payload = JWT.encode({
 :iat => iat,
 :email => email,
 :password => password
 #:exp => iat + 10000, # optional- expiration time
 #:aud => ["sisense"] # optional- audiences. a single string or an array of strings. MUST contain the value 'sisense'
 }, secret)
headers = {
 'x-api-key' => payload
 }
http.get(uri.path, headers) do |chunk|
end
sisense_rest_jwt_example.py
import sys
import time
import jwt	# JWT library for python available from https://github.com/progrium/pyjwt
import uuid
import urllib
import urllib.parse
import urllib.request

from django.http import HttpResponseRedirect

payload = {
"iat": int(time.time()),
"email": "[email protected]"
"password": "[email protected]"
#"exp" : int(time.time()) + 10000, #optional- expiration time
#"aud": "sisense"	# optional- audiences parameter. can be either string or array of strings. Must contain the value "sisense"
}

shared_key = "my_shared_key"
jwt_string = jwt.encode(payload, shared_key)
encoded_jwt = urllib.parse.quote_plus(jwt_string)	#url-encode the jwt string

headers = {'x-api-key': 'encoded_jwt }
requests.get('http://localhost/api/someAPI', headers=headers)

PHP Usage Example

The following PHP example can be used to update dashboard filters.

Index
<?PHP
include_once "JWT.php";
$key = "200491aab08ac9e519a751d3392a3643";
$now = time();
$data_string = '{"filters":[{"jaql":{"table":"Categories","column":"CategoryID","dim":"[Categories.CategoryID]","datatype":"numeric","merged":true,"title":"CategoryID","filter":{"explicit":false,"multiSelection":true,"exclude":{"members":["1"]}},"collapsed":false},"isCascading":false},{"jaql":{"table":"Customers","column":"City","dim":"[Customers.City]","datatype":"text","merged":true,"title":"City","filter":{"explicit":true,"multiSelection":true,"members":["Albuquerque","Barcelona","Berlin","Boise","Brandenburg","Bruxelles","Caracas","Campinas","Cork"]},"collapsed":true},"isCascading":false}]}';
echo strlen($data_string);
$token = array(
 "iat" => $now,
 "email" => "[email protected]",
 "password" => "sisense"
 );
$jwt = JWT::encode($token, $key);
$url = "http://localhost/api/dashboards/5448c9a8d614fcac20000035";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-Type: application/json;charset=utf-8',
	'Content-Length: ' . strlen($data_string),
	'x-api-key: '.$jwt));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS,$data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_REFERER, "http://localhost/app/main");
$response  = curl_exec($ch);
curl_close($ch);
echo $response;
JWT
<?php
/**
 * JSON Web Token implementation, based on this spec:
 * http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06
 *
 * PHP version 5
 *
 * @category Authentication
 * @package  Authentication_JWT
 * @author   Neuman Vong <[email protected]>
 * @author   Anant Narayanan <[email protected]>
 * @license  http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
 * @link     https://github.com/firebase/php-jwt
 */
class JWT
{
    public static $supported_algs = array(
        'HS256' => array('hash_hmac', 'SHA256'),
        'HS512' => array('hash_hmac', 'SHA512'),
        'HS384' => array('hash_hmac', 'SHA384'),
        'RS256' => array('openssl', 'SHA256'),
    );
    /**
     * Decodes a JWT string into a PHP object.
     *
     * @param string      $jwt           The JWT
     * @param string|Array|null $key     The secret key, or map of keys
     * @param Array       $allowed_algs  List of supported verification algorithms
     *
     * @return object      The JWT's payload as a PHP object
     *
     * @throws DomainException              Algorithm was not provided
     * @throws UnexpectedValueException     Provided JWT was invalid
     * @throws SignatureInvalidException    Provided JWT was invalid because the signature verification failed
     * @throws BeforeValidException         Provided JWT is trying to be used before it's eligible as defined by 'nbf'
     * @throws BeforeValidException         Provided JWT is trying to be used before it's been created as defined by 'iat'
     * @throws ExpiredException             Provided JWT has since expired, as defined by the 'exp' claim
     *
     * @uses jsonDecode
     * @uses urlsafeB64Decode
     */
    public static function decode($jwt, $key = null, $allowed_algs = array())
    {
        $tks = explode('.', $jwt);
        if (count($tks) != 3) {
            throw new UnexpectedValueException('Wrong number of segments');
        }
        list($headb64, $bodyb64, $cryptob64) = $tks;
        if (null === ($header = JWT::jsonDecode(JWT::urlsafeB64Decode($headb64)))) {
            throw new UnexpectedValueException('Invalid header encoding');
        }
        if (null === $payload = JWT::jsonDecode(JWT::urlsafeB64Decode($bodyb64))) {
            throw new UnexpectedValueException('Invalid claims encoding');
        }
        $sig = JWT::urlsafeB64Decode($cryptob64);
        if (isset($key)) {
            if (empty($header->alg)) {
                throw new DomainException('Empty algorithm');
            }
            if (empty(self::$supported_algs[$header->alg])) {
                throw new DomainException('Algorithm not supported');
            }
            if (!is_array($allowed_algs) || !in_array($header->alg, $allowed_algs)) {
                throw new DomainException('Algorithm not allowed');
            }
            if (is_array($key)) {
                if (isset($header->kid)) {
                    $key = $key[$header->kid];
                } else {
                    throw new DomainException('"kid" empty, unable to lookup correct key');
                }
            }
            // Check the signature
            if (!JWT::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) {
                throw new SignatureInvalidException('Signature verification failed');
            }
            // Check if the nbf if it is defined. This is the time that the
            // token can actually be used. If it's not yet that time, abort.
            if (isset($payload->nbf) && $payload->nbf > time()) {
                throw new BeforeValidException(
                    'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf)
                );
            }
            // Check that this token has been created before 'now'. This prevents
            // using tokens that have been created for later use (and haven't
            // correctly used the nbf claim).
            if (isset($payload->iat) && $payload->iat > time()) {
                throw new BeforeValidException(
                    'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat)
                );
            }
            // Check if this token has expired.
            if (isset($payload->exp) && time() >= $payload->exp) {
                throw new ExpiredException('Expired token');
            }
        }
        return $payload;
    }
    /**
     * Converts and signs a PHP object or array into a JWT string.
     *
     * @param object|array $payload PHP object or array
     * @param string       $key     The secret key
     * @param string       $alg     The signing algorithm. Supported
     *                              algorithms are 'HS256', 'HS384' and 'HS512'
     *
     * @return string      A signed JWT
     * @uses jsonEncode
     * @uses urlsafeB64Encode
     */
    public static function encode($payload, $key, $alg = 'HS256', $keyId = null)
    {
        $header = array('typ' => 'JWT', 'alg' => $alg);
        if ($keyId !== null) {
            $header['kid'] = $keyId;
        }
        $segments = array();
        $segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($header));
        $segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($payload));
        $signing_input = implode('.', $segments);
        $signature = JWT::sign($signing_input, $key, $alg);
        $segments[] = JWT::urlsafeB64Encode($signature);
        return implode('.', $segments);
    }
    /**
     * Sign a string with a given key and algorithm.
     *
     * @param string $msg          The message to sign
     * @param string|resource $key The secret key
     * @param string $alg       The signing algorithm. Supported algorithms
     *                               are 'HS256', 'HS384', 'HS512' and 'RS256'
     *
     * @return string          An encrypted message
     * @throws DomainException Unsupported algorithm was specified
     */
    public static function sign($msg, $key, $alg = 'HS256')
    {
        if (empty(self::$supported_algs[$alg])) {
            throw new DomainException('Algorithm not supported');
        }
        list($function, $algorithm) = self::$supported_algs[$alg];
        switch($function) {
            case 'hash_hmac':
                return hash_hmac($algorithm, $msg, $key, true);
            case 'openssl':
                $signature = '';
                $success = openssl_sign($msg, $signature, $key, $algorithm);
                if (!$success) {
                    throw new DomainException("OpenSSL unable to sign data");
                } else {
                    return $signature;
                }
        }
    }
    /**
     * Verify a signature with the mesage, key and method. Not all methods
     * are symmetric, so we must have a separate verify and sign method.
     * @param string $msg the original message
     * @param string $signature
     * @param string|resource $key for HS*, a string key works. for RS*, must be a resource of an openssl public key
     * @param string $alg
     * @return bool
     * @throws DomainException Invalid Algorithm or OpenSSL failure
     */
    private static function verify($msg, $signature, $key, $alg)
    {
        if (empty(self::$supported_algs[$alg])) {
            throw new DomainException('Algorithm not supported');
        }
        list($function, $algorithm) = self::$supported_algs[$alg];
        switch($function) {
            case 'openssl':
                $success = openssl_verify($msg, $signature, $key, $algorithm);
                if (!$success) {
                    throw new DomainException("OpenSSL unable to verify data: " . openssl_error_string());
                } else {
                    return $signature;
                }
            case 'hash_hmac':
            default:
                $hash = hash_hmac($algorithm, $msg, $key, true);
                if (function_exists('hash_equals')) {
                    return hash_equals($signature, $hash);
                }
                $len = min(self::safeStrlen($signature), self::safeStrlen($hash));
                $status = 0;
                for ($i = 0; $i < $len; $i++) {
                    $status |= (ord($signature[$i]) ^ ord($hash[$i]));
                }
                $status |= (self::safeStrlen($signature) ^ self::safeStrlen($hash));
                return ($status === 0);
        }
    }
    /**
     * Decode a JSON string into a PHP object.
     *
     * @param string $input JSON string
     *
     * @return object          Object representation of JSON string
     * @throws DomainException Provided string was invalid JSON
     */
    public static function jsonDecode($input)
    {
        if (version_compare(PHP_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) {
            /** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you
             * to specify that large ints (like Steam Transaction IDs) should be treated as
             * strings, rather than the PHP default behaviour of converting them to floats.
             */
            $obj = json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
        } else {
            /** Not all servers will support that, however, so for older versions we must
             * manually detect large ints in the JSON string and quote them (thus converting
             *them to strings) before decoding, hence the preg_replace() call.
             */
            $max_int_length = strlen((string) PHP_INT_MAX) - 1;
            $json_without_bigints = preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
            $obj = json_decode($json_without_bigints);
        }
        if (function_exists('json_last_error') && $errno = json_last_error()) {
            JWT::handleJsonError($errno);
        } elseif ($obj === null && $input !== 'null') {
            throw new DomainException('Null result with non-null input');
        }
        return $obj;
    }
    /**
     * Encode a PHP object into a JSON string.
     *
     * @param object|array $input A PHP object or array
     *
     * @return string          JSON representation of the PHP object or array
     * @throws DomainException Provided object could not be encoded to valid JSON
     */
    public static function jsonEncode($input)
    {
        $json = json_encode($input);
        if (function_exists('json_last_error') && $errno = json_last_error()) {
            JWT::handleJsonError($errno);
        } elseif ($json === 'null' && $input !== null) {
            throw new DomainException('Null result with non-null input');
        }
        return $json;
    }
    /**
     * Decode a string with URL-safe Base64.
     *
     * @param string $input A Base64 encoded string
     *
     * @return string A decoded string
     */
    public static function urlsafeB64Decode($input)
    {
        $remainder = strlen($input) % 4;
        if ($remainder) {
            $padlen = 4 - $remainder;
            $input .= str_repeat('=', $padlen);
        }
        return base64_decode(strtr($input, '-_', '+/'));
    }
    /**
     * Encode a string with URL-safe Base64.
     *
     * @param string $input The string you want encoded
     *
     * @return string The base64 encode of what you passed in
     */
    public static function urlsafeB64Encode($input)
    {
        return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
    }
    /**
     * Helper method to create a JSON error.
     *
     * @param int $errno An error number from json_last_error()
     *
     * @return void
     */
    private static function handleJsonError($errno)
    {
        $messages = array(
            JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
            JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
            JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON'
        );
        throw new DomainException(
            isset($messages[$errno])
            ? $messages[$errno]
            : 'Unknown JSON error: ' . $errno
        );
    }
    /**
     * Get the number of bytes in cryptographic strings.
     *
     * @param string
     * @return int
     */
    private static function safeStrlen($str)
    {
        if (function_exists('mb_strlen')) {
            return mb_strlen($str, '8bit');
        }
        return strlen($str);
    }
}

 

On this page

  • No labels