REST API¶
Overview¶
The Serenytics API gives you access to most of the Serenytics platform features, including:
- generate PDF reports from dashboards
- create users and organisations
- create data sources
- obtain secure URLs to embed in iFrames within your application
- execute a script
All the routes from this API starts with "api/".
REST API to extract data from datasources
Warning: there is another REST API in Serenytics. When you create a datasource, you can enable its data to be available in a REST API. This is an automatically generated REST API created for you. And you can manage and share custom API KEYs for this API to partners, colleagues or customers. Routes from this API start with "data-api/". The description to enable this data API is available here.
When to use the API vs our Python client¶
We advise you to use the REST API only 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 client includes error handling and is usually easier to use.
Authentification¶
Our API uses a key authentication. Each API key is associated to a single user. Your personal API key can be found in the Account menu.
The key must be passed in the field X-Api-Key
of headers.
For example, in Python, with the requests
module the way to GET the list of webapps of your organization using the
route /api/web_app
is:
import requests
route = "https://api.serenytics.com/api/web_app"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.get(route, headers=headers)
if r.status_code == 200:
web_apps = r.json()
print(web_apps)
else:
print("Failed to get webapps")
The same call in Javascript with Node/Axios would be:
var axios = require('axios');
route = "https://api.serenytics.com/api/web_app"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
axios.get(route, {headers:headers}).then(response => {
console.log(response.data);
console.log('DONE');
}).catch((e)=>{
console.log(e);
console.log('FAILED');
});
Hint
The Serenytics frontend is a simple REST API client. This means it's possible to open your browser console network tab to inspect the API calls.
Do not share your API key
Your API key is very powerful. It lets you execute all the actions that can be made by our frontend. So keep it secret and do not commit it in your code repository. If you just need to get data from your datasources with an API (or share data to your partners through an API), use the dedicated data-api. It is safer as the keys you use can be managed and be restricted to a set of datasources. Documentation is here.
Examples¶
Here is an example you can use to get your jobs and datasources and backup them in files. This can be useful to backup your python jobs in a folder that you put in a Git repository. If you re-run it after a while, you can see your changes with your previous versions.
YOUR_API_KEY= "xxxxxxx"
import requests
import os
from pprint import pprint
DESTINATION_FOLDER = f"./serenytics_backup"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
def get_obj_from_route(obj_name:str):
route = f"https://api.serenytics.com/api/{obj_name}"
r = requests.get(route, headers=headers)
if r.status_code == 200:
objects = r.json()["objects"]
else:
print(f"Failed to get {obj_name}")
exit(1)
return objects
def get_folders():
route = "https://api.serenytics.com/api/folder"
r = requests.get(route, headers=headers)
if r.status_code == 200:
folders = r.json()["objects"]
else:
print("Failed to get jobs")
exit(1)
return folders
def backup_objects(object_name:str):
objects = get_obj_from_route(object_name)
print(f"Backup {object_name}s")
folders = get_folders()
folders = {f["uuid"]: f for f in folders}
for obj in objects:
folder_uuid = obj["folder_uuid"]
folder = folders.get(folder_uuid)
local_folder = f"{DESTINATION_FOLDER}/{object_name}s/{folder['name']}"
if not os.path.exists(local_folder):
print(f"Create folder {local_folder}")
os.makedirs(local_folder)
# extract code field as it must be written in another file.
code = obj.get("code")
if "code" in obj:
del obj["code"]
filename = obj['name'].replace('/','_')
local_file = f"{local_folder}/{filename}.json"
with open(local_file, 'w') as file:
pprint(obj, stream=file)
if code:
local_file = f"{local_folder}/{filename}.py"
with open(local_file, 'w') as file:
file.write(code)
print("done")
backup_objects("script")
backup_objects("data_source")
WebApp
¶
GET /api/web_app
¶
Get the list of web_app (i.e. dashboards).
import requests
route = "https://api.serenytics.com/api/web_app"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.get(route, headers=headers)
if r.status_code == 200:
web_apps = r.json()
print(web_apps)
else:
print("Failed to get web_apps")
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:
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:
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:
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:
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. Must be> 0
and<= 3600 * 24 * 5
(5 days). Once this delay is over, the app will refuse to open this URL and all the queries sent by the dashboard will be refused.payload
(object): The payload used to instantiate a template dashboard.nb_max_embed
(integer) [optional]: number of times the obtained dynamic URL can be used. Must be an integer value greater or equal to 1. We strongly advise you to use 1 as a safe value. See "security" note below to get more details.
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.
Expire_in details
When the expire_in
delay is expired, two things happen. First, you won't be able to open this URL. The Serenytics
app will detect that this URL is not valid anymore. So, for this first point, you could set expire_in
to
a few seconds (i.e. the delay between your call to /embed and the time you open the dashboard in the iFrame should
be short).
The second point is that once the expire_in
delay is expired, all the data-queries sent by the dashboard will be
rejected. Let's say that your user opens your app at t1
. Before t1 + expire_in
, everything will be ok.
But if he tries
to use a filter in the dashboard after t1 + expire_in
, the query will be refused. So we advise you to choose
a long enough expiration delay (such as 24 hours).
Security
When you use this API route to embed a dashboard, you embed the obtained embeddedUrl
in an iFrame. A malicious
user can open the source code of your app in the browser and extract this URL.
Then he can pass it to another user who could open the dashboard (until the expire_in
delay is expired).
To avoid this malicious use case, there is an option named nb_max_embed
.
If set to 1, the first time the embeddedUrl
is opened, everything will work (and
this first time will be when the embedded dashboard is displayed in your application). If a malicious user copies
this URL from your page source code, and then tries to open it in another tab/browser (or passes it to another
person), the dashboard won't be displayed as it has already been displayed once.
Python example:
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": 86400, # 24 hours
"payload": {'quarter': 'Q2'},
"nb_max_embed": 1
}
r = requests.post(route, data=json.dumps(data), headers=headers)
Result:
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:
// 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);
content.put("nb_max_embed", 1);
StringEntity entity = new StringEntity(content.toString(), "UTF-8");
entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
request.setEntity(entity);
POST /api/web_app/:uuid/dashboard_variables
¶
Set the variables of a dashboard. The dictionary passed as parameter is merged into the existing one defined in the dashboard. You cannot remove a variable in the existing dashboard variables. You can only update a list of variables or add new ones.
URL parameters:
uuid
: uuid of the web app (dashboard)
Payload
Pass the new variables as a JSON, ina field named dashboard_variables
.
Returns: the modified dashboard.
Python example:
import requests
import json
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
url = 'https://api.serenytics.com/api/web_app/' + DASH_UUID + '/dashboard_variables'
payload = {
'dashboard_variables' : {
'date_of_data': '2022-06-24',
'business_unit': 'UK'
}
}
r = requests.post(url,data=json.dumps(payload), headers=headers)
if r.status_code != 201:
print("Failed to set the new variables")
Script
¶
GET /api/script
¶
Get the list of scripts (i.e. jobs).
import requests
route = "https://api.serenytics.com/api/script"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.get(route, headers=headers)
if r.status_code == 200:
jobs = r.json()
print(jobs)
else:
print("Failed to get jobs")
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:
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:
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:
HTTP 200 OK
Content-type: application/json
{"status": "ok", "text": "Script launched"}
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
¶
Get the list of datasources.
import requests
route = "https://api.serenytics.com/api/data_source"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.get(route, headers=headers)
if r.status_code == 200:
data_sources = r.json()
print(data_sources)
else:
print("Failed to get data_sources")
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:
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:
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:
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:
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:
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:
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:
HTTP 200 OK
Content-type: application/json
{"status": "ok", "task_id": "57727bb1b321731d9439b8bd"}
HTTP 400 Bad Request
There are three different actions supported:
insert
: Insert new rows in the datawarehouse. Therows
attribute must contain a list of data rows.insertOrUpdate
: Insert or update an existing row. You need to set theprimaryKey
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. Therows
attribute contains a list of data rows and each one must have a value in the primary key column.delete
: Delete existing rows. Same asinsertOrUpdate
, you need to set theprimaryKey
attribute. Therows
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. You can execute simple query but you can also add groupbys and filters.
Use the data-api to get data
The formatted_data API is the internal API used by the Serenytics frontend. If you need to get data from your datasources with an API (or share data to your partners through an API), use the dedicated data-api. It is safer as the keys you use can be managed and be restricted to a set of datasources. Documentation is here.
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.
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:
{
'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. You have to pass the names of the columns
to select in the data_processing_pipeline
field (to be precise, in the first value of this array).
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': [{
'select': ["Country","Date"]
}]
}
r = requests.post(route, headers=headers, data=json.dumps(data))
print(r.json())
Example:
This example shows how to add groupbys, select, filters and a limit.
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())
Tip
If you struggle to define the correct options to pass to the API. Create a table widget in the Serenytics studio with the groupby/filter/limits options you need. Then open the browser developer console in the Network section to inspect the payload passed to this API (search for the formatted_data API call).
Example:
This example shows how to get the data from a formula defined in the datasource. To query a formula, you need
to get its unique identifier and pass it in the measureUuid
field.
This identifier is available in the formula editor, in the documentation section of your formula.
In this example, the formula is used in the select
fields. But you can use a formula in the groupbys or filters
in the same way.
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': [{
'select': [
{"name": "Country"},
{"name": "MyFormula", "measureUuid": "697c7a7d0ffd5254"}]
}]
}
r = requests.post(route, headers=headers, data=json.dumps(data))
print(r.json())
Field name for a formula
When querying a formula, you need to pass both its name and unique identifier. The name is only used in
the output of the API. You can use any value but it must be defined (in the future, this field may become
optional). The field measureUuid
is mandatory.
Task
¶
GET /api/task/:task_id
¶
Get the status of the specified task.
URL parameters:
task_id
: id of the task
Example:
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:
HTTP 200 OK
Content-type: application/json
{"status": "pending"}
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:
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 (indatasource
,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:
import requests
import json
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())
User
¶
GET /api/user
¶
Returns the list of users in your organization.
Returns: a json object with a field objects
contains a list of users.
Python example:
import requests
route = "https://api.serenytics.com/api/user"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.get(route, headers=headers)
if r.status_code == 200:
users = r.json()["objects"]
for user in users:
print(f'{user["username"]} --> {user["category"]}')
GET /api/user/<user_uuid>
¶
Returns a given user (using its uuid).
Returns: the user as a json object.
Python example:
import requests
route = "https://api.serenytics.com/api/user/93251f96-acbb-4bb7-b101-ca628c5c21b8"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.get(route, headers=headers)
print(r.status_code)
print(r.json())
GET /api/user/byname/
¶
Returns a given user (using its username).
Returns: the user as a json object.
Python example:
import requests
route = "https://api.serenytics.com/api/user/byname"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.get(route, headers=headers, params={'username':'john@doe.com'})
print(r.status_code)
print(r.json())
POST /api/user
¶
Creates a new user.
Returns:
- 201 code and the json object of the created user if the user was created.
- 400 code if the user already exists.
- 401 code if your not authorized to create users (you must be an admin user).
Body parameters:
username
: The username of the user to create.password
: The password of the user to create.category
: The type of the new user (inviewer
,studio_dashboard
,studio
,admin
).
The type studio_dashboard is used for Business Analyst.
Python example:
import requests
import json
route = "https://api.serenytics.com/api/user"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
data = {
"username": "john@doe.com",
"password": "myStrongPassword",
"category": "viewer"
}
r = requests.post(route, headers=headers, data=json.dumps(data))
print(r.status_code)
print(r.json())
PUT /api/user/<user_uuid>
¶
Modifies category and meta_data fields of a given user. Metadata are per-login values which can be used to filter dashboards in viewer mode (e.g. to filter a dashboard by user's business unit).
Returns:
- 200 code and the json object of the modified user.
Body parameters:
category
: The category of the user (inviewer
,studio_dashboard
,studio
,admin
).
The body parameter must only contains the fields you want to update in the user object.
Python examples:
import requests
import json
route = "https://api.serenytics.com/api/user/93251f96-acbb-4bb7-b101-ca628c5c21b8"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
new_params = {
"category": "studio",
"login_metadata": {"business_unit": "france"}
}
r = requests.put(route, headers=headers, data=json.dumps(new_params))
print(r.status_code)
print(r.json())
Here is a full example to modify the metadata of a user.
import json
import requests
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
# Get the user
route1 = 'https://api.serenytics.com/api/user/byname'
r1 = requests.get(route1, headers=headers, params={'username':'john@doe.com'})
print(r1.status_code)
# Modify its metadata
if r1.status_code == 200:
user_uuid = r1.json()["uuid"]
route2 = 'https://api.serenytics.com/api/user/' + user_uuid
new_params = {
"login_metadata": {"business_unit": "france"}
}
r2 = requests.put(route2, headers=headers, data=json.dumps(new_params))
print(r2.status_code)
print(r2.json())
DELETE /api/user/<uuid>
¶
Delete the User object from its uuid.
URL parameters:
uuid
: uuid of the user to delete
Returns: a 204 code if the User was deleted
Python example:
import requests
route = "https://api.serenytics.com/api/user/%s" % USER_UUID
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.delete(route, headers=headers)
print(r.status_code)
Usersgroup
¶
A usersgroup
object is a group of user. When sharing a dashboard to a list of viewers, it is advised
to create a group with those users and then to share the dashboard to this group.
GET /api/usersgroup
¶
Returns the list of usersgroup in your organization.
Returns: a json object with a field objects
contains a list of usersgroup.
Python example:
import requests
route = "https://api.serenytics.com/api/usersgroup"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.get(route, headers=headers)
if r.status_code == 200:
groups = r.json()["objects"]
for g in groups:
print(g["name"])
GET /api/usersgroup/<user_uuid>/list_of_users
¶
Returns a the list of users in a given group (using its uuid).
Returns: the user as a json object.
Python example:
import requests
route = "https://api.serenytics.com/api/usersgroup/8dee7842-3596-494b-8fa6-c81c50e9574d"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.get(route, headers=headers)
print(r.status_code)
print(r.json())
users = r.json()["objects"]
for u in users:
print(u["username"])
GET /api/usersgroup/byname
¶
Returns a given usersgroup (using its name).
Returns: the usersgroup as a json object.
Python example:
import requests
route = "https://api.serenytics.com/api/usersgroup/byname"
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.get(route, headers=headers, params={'name':'marketing team'})
print(r.status_code)
print(r.json())
POST /api/usersgroup/<group_uuid>/adduser
¶
Add a user (by its username) to a group.
Returns:
- 201 when the user is added to the group.
- 400 if the user is already in the group (check the json content in response to get detailed message).
Body parameters:
username_to_add
: The username of the user to add to the group.
Python example:
import requests
import json
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
# get the group object from its name
route1 = "https://api.serenytics.com/api/usersgroup/byname"
r1 = requests.get(route, headers=headers, params={'name':'marketing team'})
print(r1.status_code)
print(r1.json())
group_uuid = r1.json()["uuid"]
# add the user to the group
route2 = "https://api.serenytics.com/api/usersgroup/" + group_uuid + "/adduser"
r2 = requests.post(route2, headers=headers, data=json.dumps({'username_to_add': 'john@doe.com'}))
print(r2.status_code)
print(r2.json())
POST /api/usersgroup/<group_uuid>/removeuser
¶
Remove a user (by its username) from a group.
Returns:
- 204 if the user is removed from the group.
- 400 if the user is not in the group.
Body parameters:
username_to_remove
: The username of the user to remove from the group.
Python example:
import requests
import json
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
# get the group object from its name
route1 = "https://api.serenytics.com/api/usersgroup/byname"
r1 = requests.get(route, headers=headers, params={'name':'marketing team'})
print(r1.status_code)
print(r1.json())
group_uuid = r1.json()["uuid"]
# remove the user from the group
route2 = "https://api.serenytics.com/api/usersgroup/" + group_uuid + "/removeuser"
r2 = requests.post(route2, headers=headers, data=json.dumps({'username_to_remove': 'john@doe.com'}))
print(r2.status_code)
print(r2.json())
DELETE /api/usersgroup/<uuid>
¶
Delete the Usersgroup object from its uuid.
URL parameters:
uuid
: uuid of the usersgroup to delete
Returns: a 204 code if the Usersgroup was deleted
Python example:
import requests
route = "https://api.serenytics.com/api/usersgroup/%s" % USERSGROUP_UUID
headers = {
'X-Api-Key': YOUR_API_KEY,
'Content-type': 'application/json'
}
r = requests.delete(route, headers=headers)
print(r.status_code)