REST API

Getting started

You should only use the REST API if you are working with another language than Python or for advanced needs which are not yet available in our Python client. If you are working in the Python language, please check if the feature you need is available in our python client before using the API.

The Serenytics API gives you access to most of the Serenytics platform features, including:

  • generating PDF reports from dashboards
  • creating users and organisations
  • creating data sources
  • obtaining secure URLs to embed in iFrames within your application
  • executing a script

WebApp

GET /api/web_app/:uuid

Returns the WebApp object from its uuid.

URL parameters:

  • uuid: uuid of the web app (dashboard) you want to obtain

Returns: the json object of the queried WebApp.

Warning

Contact us if you need details about the WebApp model.

Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import requests

route = "https://api.serenytics.com/api/web_app/%s" % YOUR_WEB_APP_UUID

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

r = requests.get(route, headers=headers)
if r.status_code == 200:
    web_app = r.json()
    print(web_app["name"])

PUT /api/web_app/:uuid

Modify a WebApp.

URL parameters:

  • uuid: uuid of the web app (dashboard) to modify

Body parameters:

  • The entire WebApp JSON or only the fields you want to modify.

Returns: the json object of the modified WebApp.

Warning

Contact us if you need details about the WebApp model.

Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import requests
import json

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

route = "https://api.serenytics.com/api/web_app/%s" % YOUR_WEB_APP_UUID

# get the webapp
r = requests.get(route, headers=headers)
if r.status_code != 200:
    print('Failed to get dashboard')
    exit(1)

web_app = r.json()

# modify the local object
web_app["name"] = "My New Name"


# save the modified object
r = requests.put(route, headers=headers, data=json.dumps(web_app))
if r.status_code != 200:
    print('Failed to update dashboard')
    exit(1)
print(r.json()["name"])

DELETE /api/web_app/:uuid

Delete the WebApp object from its uuid.

URL parameters:

  • uuid: uuid of the web app (dashboard) to delete

Returns: a 204 code if the WebApp was deleted

Warning

Use with caution, the deleted WebApp cannot be recovered.

Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import requests

route = "https://api.serenytics.com/api/web_app/%s" % YOUR_WEB_APP_UUID

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

r = requests.delete(route, headers=headers)
print(r.status_code)

POST /api/web_app/:uuid/clone

Clone a WebApp.

URL parameters:

  • uuid: uuid of the web app (dashboard) to clone

Returns: the json object of the cloned WebApp.

Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import requests
import json

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

route = "https://api.serenytics.com/api/web_app/%s/clone" % YOUR_WEB_APP_UUID

# get the webapp
r = requests.post(route, headers=headers)
if r.status_code != 200:
    print('Failed to clone dashboard')
    exit(1)

cloned_web_app = r.json()

POST /api/web_app/:uuid/embed

Generate a secure URL for a given dashboard. If your dashboard is a template dashboard, this API also lets you define the values of the global filter variables you defined.

URL parameters:

  • uuid: uuid of the web app (dashboard) you want to embed

Body parameters:

  • expire_in (integer): Validity of the obtained url in seconds.
  • payload (object): The payload used to instantiate a template dashboard.

Returns: a json object with the URL to use to load this dashboard.

In the result, the embeddedUrl is the secure URL to embed in an iFrame.

Warning

You need to be the owner of the dashboard to call this API.

Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import json
import requests

route = "https://api.serenytics.com/api/web_app/%s/embed" % YOUR_WEB_APP_UUID

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

data = {
    "expire_in": 120,
    "payload": {'quarter': 'Q2'}
}

r = requests.post(route, data=json.dumps(data), headers=headers)

Result:

1
2
3
4
5
6
7
8
HTTP 200 OK
Content-type: application/json

{
  "embeddedPayload": "e8d5d2cd-60cb-453a-97e7-0eb43cc7d67f",
  "embeddedUrl": "https://app.serenytics.com/api/web_app/7eef1661-6390-40c3-b326-f3056c1d4287?embeddedPayload=e8d5d2cd-60cb-453a-97e7-0eb43cc7d67f",
  "status": "ok"
}

Java example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// See https://github.com/Serenytics/serenytics-demo-java-client for a complete running
// example, including maven config and imports

String apiKey = "YOUR_API_KEY";
String webAppUuid = "YOUR_WEB_APP_UUID";

String urlTemplate = "https://api.serenytics.com/api/web_app/%s/embed";

HttpPost request = new HttpPost(String.format(urlTemplate, webAppUuid));
request.setHeader("X-Api-Key", apiKey);
request.setHeader("Content-type", "application/json");

JSONObject content = new JSONObject();
content.put("payload", (new JSONObject()).put("quarter", "Q2"));
content.put("expire_in", 3600);

StringEntity entity = new StringEntity(content.toString(), "UTF-8");
entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
request.setEntity(entity);

Script

POST /api/script/:script_uuid/run

Run a Serenytics script (with or without parameters).

URL parameters:

  • uuid: uuid of the script to run

Body parameters:

  • async[optional] (boolean): Whether the API call returns immediately or waits for the script execution to be finished. Default: true.

Python example with params:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import json
import requests

route = "https://api.serenytics.com/api/script/%s/run" % YOUR_SCRIPT_UUID

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

data = {
    "param1": 120,
    "param2": {'quarter': 2}
}

r = requests.post(route, data=json.dumps(data), headers=headers)
# note : use client.script_args in the Serenytics script to retrieve this data

Python example without params:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import json
import requests

route = "https://api.serenytics.com/api/script/%s/run" % YOUR_SCRIPT_UUID

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

r = requests.post(route, headers=headers)

Result:

1
2
3
4
HTTP 200 OK
Content-type: application/json

{"status": "ok", "text": "Script launched"}
1
HTTP 400 Bad Request

This URL lets you run a script you defined in the Serenytics studio. By default the script is run in an asynchronous way. The return of the API call only indicates that the script execution is queued in the Serenytics server.

You can pass a JSON with parameters to the script (see example above). In the Serenytics script, you can retrieve this JSON by calling the property `client.script_args.

If you specify async=false in the JSON parameters or in the url (.../run?async=false) the script is run in a synchronous way. The API call waits for the script to be finished before returning the exit code, and the stdout and stderr outputs of the script.

Running the script as a webhook

You can also run the script as a webhook (for instance to use as a Slack command or to integrate with Zapier).

In this case you first need to generate a token for your script in the Serenytics studio. Then use an url of the form: https://api.serenytics.com/api/script/:script_uuid/run?token=YOUR_SCRIPT_TOKEN as a webhook.


DataSource

GET /api/data_source/:uuid

Returns the DataSource object from its uuid.

URL parameters:

  • uuid: uuid of the DataSource you want to obtain

Returns: the json object of the queried DataSource.

Warning

Contact us if you need details about the DataSource model.

Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import requests

route = "https://api.serenytics.com/api/data_source/%s" % YOUR_DATA_SOURCE_UUID

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

r = requests.get(route, headers=headers)
if r.status_code == 200:
    data_source = r.json()
    print(data_source["name"])

PUT /api/data_source/:uuid

Modify a DataSource.

URL parameters:

  • uuid: uuid of the DataSource to modify

Body parameters:

  • The entire DataSource JSON or only the fields you want to modify.

Returns: the json object of the modified DataSource.

Warning

Contact us if you need details about the DataSource model.

Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import requests
import json

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

route = "https://api.serenytics.com/api/data_source/%s" % YOUR_DATA_SOURCE_UUID

# get the data_source
r = requests.get(route, headers=headers)
if r.status_code != 200:
    print('Failed to get the data source')
    exit(1)

data_source = r.json()

# modify the local object
data_source["name"] = "My New Name"


# save the modified object
r = requests.put(route, headers=headers, data=json.dumps(data_source))
if r.status_code != 200:
    print('Failed to update data_source')
    exit(1)
print(r.json()["name"])

DELETE /api/data_source/:uuid

Delete the DataSource object from its uuid.

URL parameters:

  • uuid: uuid of the DataSource to delete

Returns: a 204 code if the DataSource was deleted

Warning

Use with caution, the deleted DataSource cannot be recovered.

Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import requests

route = "https://api.serenytics.com/api/data_source/%s" % YOUR_DATA_SOURCE_UUID

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

r = requests.delete(route, headers=headers)
print(r.status_code)

POST /api/data_source/:uuid/invalidate_cache

Invalidate data source cache.

All future calls to get data (for instance when loading a dashboard using this source) won't use current cache. Works whatever the cache config of the source.

URL parameters:

  • uuid: uuid of the data source

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import requests

route = "https://api.serenytics.com/api/data_source/%s/invalidate_cache" % YOUR_DATA_SOURCE_UUID

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

r = requests.post(route, headers=headers)

Result:

1
2
3
4
HTTP 200 OK
Content-type: application/json

{"status": "ok"}

POST /api/data_source/:uuid/batch

Insert, update, or delete several rows in the datawarehouse in one call. All operations are executed in the given order.

URL parameters:

  • uuid: uuid of the data source

Body parameters:

  • async[optional] (boolean): Whether the API call returns immediately or waits for the data operations to be finished. Default: true.
  • operations (object): Operations to execute on data source (insert/update/delete).

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import json
import requests

route = "https://api.serenytics.com/api/data_source/%s/batch" % YOUR_DATA_SOURCE_UUID

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

data = {
   "async": True,
   "operations": [
       {
           "action": "insert",
           "rows": [
               {'id': 1, 'country': 'FR', 'name': 'John', 'quantity': 10},
               {'id': 2, 'country': 'US', 'name': 'Mark', 'quantity': 2},
               {'id': 3, 'country': 'UK', 'name': 'John', 'quantity': 1},
               {'id': 4, 'country': 'US', 'name': 'David', 'quantity': 8}
           ]
       },
       {
           "action": "insertOrUpdate",
           "primaryKey": "id",
           "rows": [
               {'id': 1, 'country': 'FR', 'name': 'John', 'quantity': 50},
               {'id': 5, 'country': 'US', 'name': 'Peter', 'quantity': 13}
           ]
       },
       {
           "action": "delete",
           "primaryKey": "id",
           "rows": [2, 4]
       }
   ]
}

r = requests.post(route, headers=headers, data=json.dumps(data))

Result:

1
2
3
4
HTTP 200 OK
Content-type: application/json

{"status": "ok", "task_id": "57727bb1b321731d9439b8bd"}
1
HTTP 400 Bad Request

There are three different actions supported:

  • insert: Insert new rows in the datawarehouse. The rows attribute must contain a list of data rows.
  • insertOrUpdate: Insert or update an existing row. You need to set the primaryKey attribute to indicate which column is the primary key used to determine if the row already exists and must be updated or if the row doesn't exist and must be inserted. The rows attribute contains a list of data rows and each one must have a value in the primary key column.
  • delete: Delete existing rows. Same as insertOrUpdate, you need to set the primaryKey attribute. The rows attribute must contain a list of the primary key values to delete.

When calling the API with async=true, the result contains a task_id (see example above). You can then check the results of the task by using the task API.

Warning

The new inserted or updated data should have the same structure as old data (i.e. same columns). If not, new columns will be ignored and existing columns in the datawarehouse will be filled with NULL.

Warning

Only use column names in lower case without accentuated characters. This is a restriction from our internal datawarehouse. You can later use our source mapper in the user interface to rename your columns for the user designing dashboards.

Formatted Data

The formatted data route lets you query data from a datasource.

POST /api/data_source/formatted_data/:data_source_uuid

Obtain data from a datasource. This route can also be used to get only columns info of a given datasource.

The number of rows returned by this API is capped to 20 000. If the queried datasource is close to this limit, you must check the number of rows obtained by your API call. If the API returned exactly 20 000 rows, it means the result has been capped and you got only a subset of the dataset.

If you query an invalid datasource, or if you're not allowed to access this datasource, you will receive the corresponding status code from the API (e.g. 401 or 403).

In all other cases, the API will return a 200 http code. You need to check the field status from the received data. It contains ok if everything went well and error if an error occured. In this case, the field errors contains details about the errors.

URL parameters:

  • uuid: uuid of the data source

Example:

This example shows how to get columns info for a given datasource.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import requests

SOURCE_UUID = 'YOUR_SOURCE_UUID'

route = 'https://api.serenytics.com/api/formatted_data/' + SOURCE_UUID

headers = {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-type': 'application/json'
}

data = {
    "only_headers": "true"
}
r = requests.post(route, headers=headers, data=json.dumps(data))

print(r.json())

Result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
'columns_titles': [
    {'name': 'Date', 'type': 'datetime', 'datetime_format': '%Y-%m-%d'},
    {'name': 'Country', 'type': 'str'}, {'name': 'Category', 'type': 'str'},
    {'name': 'SubCategory', 'type': 'str'},
    {'name': 'Quantity', 'type': 'int'},
    {'name': 'Price', 'type': 'float'},
    {'name': 'Cost of Goods', 'type': 'float'}
],
'status': 'ok'}

Example:

This example shows how to get the actual data from a given datasource.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests

SOURCE_UUID = 'YOUR_SOURCE_UUID'

route = 'https://api.serenytics.com/api/formatted_data/' + SOURCE_UUID

headers = {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-type': 'application/json'
}

data = {
        'order': 'row_by_row',
        'data_processing_pipeline': [{
            'group_by': ['Country'],
            'select': [{'name': 'Country'},
                       {'name': 'Quantity', 'agg_function': 'sum'}],
            'where': [{'name': 'Price', 'op': '>', 'value': '20'}],
            'limit': 100,
        }]
    }
r = requests.post(route, headers=headers, data=json.dumps(data))

print(r.json())

Result:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{'data':
    [['Austria', 1179],
     ['Denmark', 2207],
     ['France', 5398],
     ['Germany', 3700],
     ['Ireland', 3489],
     ['Italy', 323],
     ['Portugal', 3129],
     ['Spain', 3538],
     ['Switzerland', 931],
     ['UK', 3530],
     ['USA', 71618]],
 'columns_titles':
    [
    {'type': 'str', 'name': 'Country'},
    {'type': 'int', 'name': 'Quantity', 'agg_function': 'sum'}
    ],
'status': 'ok'
}

Tip

If your struggle to define the correct options to pass to the API. Create a widget in the Serenytics studio and open the browser developer console in the Network section to inspect the options passed to this API.

Task

GET /api/task/:task_id

Get the status of the specified task.

URL parameters:

  • task_id: id of the task

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import json
import requests

route = "https://api.serenytics.com/api/task/%s" % YOUR_TASK_ID

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

r = requests.get(route, headers=headers)

Result:

1
2
3
4
HTTP 200 OK
Content-type: application/json

{"status": "pending"}
1
2
3
4
HTTP 200 OK
Content-type: application/json

{"status": "ok"}

Folder

GET /api/folder

Returns the list of folders.

Returns: a json object with a field objects contains a list of folders.

Warning

Contact us if you need details about the Folder model.

Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import requests

route = "https://api.serenytics.com/api/folder"

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

r = requests.get(route, headers=headers)
if r.status_code == 200:
    folders = r.json()["objects"]
    for f in folders:
        print(f["name"], "--> ", f["resource_type"])

POST /api/folder

Create a folder.

Returns: the json object of the created folder.

Body parameters:

  • name: The name of the folder to create.
  • resource_type: The type of resource for this folder (in datasource, webapp, script).

Warning

Contact us if you need details about the Folder model. Folders with the word home in their name are very specific. Do not use this keyword in the folders your create.

Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import requests

route = "https://api.serenytics.com/api/folder"

headers = {
    'X-Api-Key': YOUR_API_KEY,
    'Content-type': 'application/json'
}

data = {
   "name": "My new folder",
   "resource_type": "datasource"
   }

r = requests.post(route, headers=headers, data=json.dumps(data))
if r.status_code == 201:
    print(r.json())