Using these APIs, you are able to programmatically work with Holistics. For example:
- You can programmatically retrieve CSV, XLSX, etc. data from any Holistics report.
- You can use our API to trigger execution of an data schedule, transform or data import. etc...
This is useful especially if you need to pass live data to your other applications. For example, you may want to feed a live CSV endpoint of your user segmentation list into your email marketing application so that you can always get fresh data upon retrieving them.
NOTE: Please note that Holistics API version does not correlate with Holistics feature version. For example, Holistics API v2 can support operations on all Holistics 2.0, 2.7 and 3.0.
API data is limited to specific regions. For example, if your want to access data from the US region, you need to use the subdomain https://us.holistics.io. Below is the API subdomain corresponding with data center's region.
Region | URL |
---|---|
Asia-Pacific (APAC) | https://secure.holistics.io/api/v2 |
Europe (EU) | https://eu.holistics.io/api/v2 |
United States (US) | https://us.holistics.io/api/v2 |
If you do not know which data center your Holistics' account is currently on, check out this docs.
Allow user API access
In order for a user to use API key, they must be allowed to use API access in User Management. Edit the User and tick the checkbox Allow API access:API Key
The allowed user can then visit User Settings and generate a new API key.Then, they can set the API key in the request header when calling Holistics APIs.
API Request Authorization
Set the HTTP header X-Holistics-Key
to your API key. Example:
curl -X POST \
-H "Accept:application/json" \
-H "Content-Type:application/json" \
-H "X-Holistics-Key:$your_api_key" \
https://secure.holistics.io/api/v2/users/me
HTTP Code | Description |
---|---|
200 - OK | Everything worked as expected. |
400 - Bad Request | The request was unacceptable due to missing request parameter or wrong request structure. |
401 - Unauthorized | No valid API key provided. |
403 - Forbidden | The API Key owner does not have permission to perform the request. |
404 - Not Found | The requested resource does not exist or cannot found. |
422 - Unprocessable Entity | Cannot process the request parameter due to semantic errors. See the message for more detail. |
429 - Too Many Requests | Too many requests were sent. |
500 - Internal Holistics Error | Something went wrong on Holistics side (rarely). |
Error type | Description |
---|---|
BaseError | Base schema for all types of errors. |
RecordError | Error when saving a record. |
InvalidParameterError | One or more parameters are missing or do not satisfy the endpoint's requirements. |
AuthError | Could not authorize current user, typically due to missing or expired authentication token. |
MaintenanceError | Your admins has set Holistics to Maintenance mode |
SubscriptionError | The subscription of the tenant does not have permission to access the resource. |
PermissionDeniedError | The API Key owner does not have permission to access a resource. |
InternalHolisticsError | Internal Holistics error. Please provide us the debug id in error message so we can investigate further. |
InvalidOperationError | Can not process your action due to system constraints. |
Base Error (All errors inherit from this):
type required | string Enum: "BaseError" "RecordError" "InvalidParameterError" "AuthError" "MaintenanceError" "SubscriptionError" "PermissionDeniedError" "InternalHolisticsError" "RateLimitExceedError" "InvalidOperationError" "InvalidEmailsInvitationError" |
message required | string |
object Details about this error. |
{- "type": "BaseError",
- "message": "string",
- "details": {
- "description": "string",
- "docs": "string"
}
}
Record Error:
type required | string Enum: "BaseError" "RecordError" "InvalidParameterError" "AuthError" "MaintenanceError" "SubscriptionError" "PermissionDeniedError" "InternalHolisticsError" "RateLimitExceedError" "InvalidOperationError" "InvalidEmailsInvitationError" "RecordError" |
object Detailed errors of the record being created/updated. | |
message required | string |
object Details about this error. |
{- "type": "BaseError",
- "record": {
- "base": [
- "string"
], - "property1": [
- "string"
], - "property2": [
- "string"
]
}, - "message": "string",
- "details": {
- "description": "string",
- "docs": "string"
}
}
To prevent DDoS attacks, every API request should go through our rate limit layer which will throttle the request if a user exceeds limit quotas. The rate limit is based on user and endpoint, quotas (per time frame) which maybe different for each endpoint are divided by levels as the table below:
Level | Quota | Note |
---|---|---|
Level 1 | 120 | At least every API request is this level |
Level 2 | 60 | Request requires a lot of resource |
Level 3 | 20 | Request that heavily affect our server's resources |
If a request is blocked because of it exceed the limit quota, status code is set to 429: Too Many Requests
Every API request returns header contains the following fields:
RateLimit-Limit: your_limit_quota_of_endpoint
RateLimit-Remaining: remaining_requests_until_reset
RateLimit-Reset: next_reset_time
Retry-After: next_reset_time(only available when status code is 429)
This short tutorial shows you how to use the Holistics APIs to get report data in raw tabular form (CSV, Excel).
This tutorial uses Ruby, but you can easily use any other language for it.
ⓘ INFO
We'll be working on client libraries wrapper around our API. Once done, using the APIs will be simpler by just making a few function calls.
Since Holistics uses a async job queuing system to process job, you can't make a single API call to retrieve the results. We need to submit an 'export request', then wait for the export job to finish, and then make an API call to download the results.
API Endpoints used:
Let's go through the steps here.
1. Setting Up API Key
Please see guide to set up and retrieve your API key.
2. Initial code structure
To make things simple and reusable, we'll wrap our code around a HolisticsAPI
class. We'll also use the httprb gem to handle making HTTP calls.
require 'http'
class HolisticsAPI
def initialize(api_key, host: 'secure.holistics.io')
@api_key = api_key
@api_url = "https://#{host}/api/v2"
@http = HTTP.headers({'X-Holistics-Key' => @api_key})
end
end
3. (Optional) Get Filters ID for your Dashboard Export
If you want to include Filters in your export, you will need to get their Filter IDs. Please follow these steps to obtain them:
1. Get your Dashboard ID
The Dashboard ID can be retrieved by looking at its URL in the browser. In this sample URL below, the Dashboard ID would be 16076.
2. Get Filter ID
Supposed that your dashboard has a sets of filters like the one below. Let's get the ID of the Date filter to include it in our export.
We will use Get Dashboard API for this purpose. Let's call the API with the Dashboard ID from step 1.
curl --location --request GET 'https://secure.holistics.io/api/v2/dashboards/{your_dashboard_id}' \
--header 'X-Holistics-Key: your_API_key' \
--header 'Content-Type: application/json' \
The response would be quite lengthy, but you just need to find the dynamic_filters field to get the Filter ID.
You can then use this Filter ID in the next step.
4. Submit widget export request
Make sure you have the DashboardWidget ID in hand. The widget ID can be retrieved by opening up the widget in the dashboard, and look at the _e
parameter in the URL. For example, 4175 is the widget ID of the below.
https://secure.holistics.io/dashboards/v3/12345-some-dashboard/?_e=4175
ⓘ INFO
(Optional) Include filter conditions in your export If you wish to include a filter condition in your export, first refer to step 3 to get your desired Filter ID.
Then, append dashboard_filter_conditions in your request body.
- dynamic_filter_id is the Filter ID from step 3.
- condition:
- operator: refer to Data Modeling Condition for all available operators.
- values: is an array of strings or integers that go with the operator.
For example, assuming that you have completed step 3, to apply a Date Filter that filters data from 2 months ago to the export, simply include this snippet to your request.
{ "dashboard_filter_conditions": [ { "dynamic_filter_id": 2335, "condition": { "operator": "matches", "values": [ "2 months ago" ] } } ] }
Then we make the call to submit widget export:
class HolisticsAPI
# ...
# output: 'csv' or 'excel'
def submit_report(widget_id, output: 'csv')
url = @api_url + "/dashboard_widgets/" + widget_id.to_s + "/submit_export"
response = @http.post(url, json: {output: output})
res = JSON.parse(response.to_s)
if response.code == 200
res['job']['id']
else
raise StandardError.new(res['message'])
end
end
end
If successful, this method returns the job ID of the job created.
5. Waiting for job to complete
The job will the go to the queue system waiting to be processed. This method below will continuously poll the job's metadata until it is either success, or failure.
class HolisticsAPI
# ...
def wait_for_job_status(job_id)
url = @api_url + "/jobs/" + job_id.to_s
while true do
response = @http.get(url)
res = JSON.parse(response.to_s)
raise StandardError.new(res['message']) if response.code != 200
status = res['job']['status']
puts "===> status: #{status}"
unless ['created', 'running', 'queued'].include?(status)
return status
end
# Wait a while before pinging again
sleep 2
end
end
end
6. Downloading the results
Once the job finishes, we make one final API call to
class HolisticsAPI
# ...
def download_export(job_id)
url = @api_url + "/exports/download"
response = @http.follow.get(url, params: {job_id: job_id})
raise StandardError.new(JSON.parse(response.to_s['message'])) if response.code != 200
response.to_s
end
end
7. Putting things together
Once the above class is defined, let's put in a short code to perform all 3 steps to get the data.
API_KEY = 'your_api_key'
WIDGET_ID = 1234 # your widget
api = HolisticsAPI.new(API_KEY)
job_id = api.submit_report(WIDGET_ID)
puts "===> job_id: #{job_id}"
job_status = api.wait_for_job_status(job_id)
puts "===> job_status: #{job_status}"
if job_status == 'success'
csv_data = api.download_export(job_id)
puts csv_data # your CSV-formatted data here!
end
7. Profit!
Save the data into CSV, convert them into array, or feed them to other applications. The potentials are limitless!
In Holistics, you can set up a system that sends you automatic notifications when data meets certain criteria, allowing you to make timely and strategic business decisions. This concept is called as Data Alert.
Holistics offers a set of public API endpoints allowing clients to work with Data Alert. This tutorial shows you how to programmatically create these data alerts using the API.
Assuming you are an e-commerce company that wants to track the number and status of orders placed on your platform. You can set up data alerts that trigger notifications when certain conditions are met, such as:
- A number of orders placed in a specific time period exceed a certain threshold.
- A certain percentage of orders are canceled or marked as "canceled".
You can receive these alerts through email or slack, and they can use this information to quickly respond to any issues or to make informed decisions about adjusting inventory or shipping processes.
Let's walk through how we can create a data alert to track your number of orders using Holistics API.
We will use the API to create email data alerts. Specifically, we'll send a POST request to Holistics create data alert API.
Before that, we need to prepare the following:
- A dashboard widget with relevant report
- Holistics API Key: We need to setup the API key. Refer to this guide for more info.
Step 1. Preparing the dashboard widget
You will need to create a dashboard widget containing the data of interest to you. In this example, I used this simple report that counts the total number of orders.
Step 2: Making the API Call
We'll be using the following endpoint:
POST https://secure.holistics.io/api/v2/data_alerts
There are some notable configuration options in this request:
schedule
: Specify how frequently the email schedule should beviz_conditions
: Specify what alert condition should be check on the report result. By configuring this, we can customize the alert for each alerting use case.dest
: Specify configurations regarding the alert delivery destination, e.g. the recipients' information.dynamic_filter_presets
: Specify what dynamic filters should be applied to the report. By configuring this, we can customize the report for each recipient.
Below is a sample request body. Refer to Holistics API docs for more information on these fields.
Dest field
dest
: Specify configurations regarding recipients' informationtitle
(string): Note that Holistics support dynamic variables in email title. For example, the titleSales report for {{$today}}
sent on 29/09/2021 will be rendered asSales report for 2021-09-29 Wed
.type
: This tells Holistics you want to receive notification via email:EmailDest
or Slack:SlackDest
- If you choose
SlackDest
, you will need to get the id and the name of your slack channel for theslack_channels
field
- If you choose
Viz conditions
viz_conditions
: Coming to the core of the alert, the condition to set data alertfield_path
: This is used to extract from a specific data modelfield_name
: field name of the field in the data model you want to apply the condition.model_id
: The id of the data model associated with thefield_name
- You can get the
field_name
andmodel_id
by following these steps- From the widget id → Get a dashboard widget (include_report=true) then extract
query_report.viz_settings.fields
, you can find the field you want to add condition then extract path_hash
to getmodel_id
andfield_name
- From the widget id → Get a dashboard widget (include_report=true) then extract
aggregation
: The aggregation that will be applied on the field when processing the condition.transformation
: The transformation that will be applied on the field when processing the condition.condition
: be applied on the Data Modeling layer to filter your data. Check out our document here for more details.Example: you have a field
id
and want to check whether the number of it is greater than 35000{ "field_path": { "field_name": "id", "model_id": 1 }, "aggregation": "count", "transformation": null, "condition": { "operator": "greater_than", "modifier": null, "values": [35000], }, }
Schedule
schedule
: This field is used to specify the schedule for your email schedule.
repeat
(string): You will need to input a crontab expression to let Holistics know how frequently you want your email schedule to run.
Dashboard Filters
dynamic-filter-presets
is where you define your filter presets.
dynamic_filter_id
: To get your filter_id
, send a request to Dashboards#Get API to get the dashboard info.
preset_conditions
: Let's go through our example to better illustrate this field.
We want to set a value for the filter by setting a preset condition. A preset condition consists of an operator and a list of values. Holistics supports various operators and provides several examples here.
In this case, we want to use operator is
and set values to customer_id
. By this, we mean the filter's default value equals exactly to customer_id
.
Finally, we also want to set up another dynamic filter preset to filter data to the whole of last week. Fortunately, Holistics allows a list of dynamic filter presets. For the Date Range filter, we similarly want to use operator is
and set values to "last 7 days"
.
Our final dynamic_filter_presets
object will look like this.
dynamic_filter_presets = [
{
"dynamic_filter_id": MY_CUSTOMER_FILTER_ID,
"preset_condition": {
"operator": "is",
"values": [
customer_id
]
}
},
{
"dynamic_filter_id": MY_DATE_RANGE_FILTER_ID,
"preset_condition": {
"operator": "is",
"values": [
"last 7 days"
]
}
}
]
Step 3: Verify to see if your data alert is created
The request should now be ready. After sending it to Holistics, the server will respond with a HTTP status response code to indicate whether the request was successful / failed.
Lastly, be sure to head over to the Holistics page to see if your data alert is created.
Example script
An example script to send requests written in Ruby is available here:
# install the neccessary dependencies for this script to work
require "bundler/inline"
require "net/http"
require "json"
gemfile do
source "https://rubygems.org"
gem "net-http"
end
# this the Holisitics API endpoint that we need to send our POST request to
DATA_ALERT_ENDPOINT = URI("https://secure.holistics.io/api/v2/data_alerts")
# Step 1: Create a POST request to the endpoint below
request = Net::HTTP::Post.new(DATA_ALERT_ENDPOINT)
# Step 2: Provide your authentication information
request["X-Holistics-Key"] = "mysecretAPIkey"
# Step 2.1: This line helps the system know that we are sending a JSON request
request.content_type = "application/json"
# Step 3: Provide information for your data alert in the request body
request.body = {
"data_alert": {
"title": "Tracking number of orders",
"source_id": 41,
"source_type": "DashboardWidget",
# Conditions for the Alert to be Triggered
"viz_conditions": [
{
"field_path": {
"field_name": "id",
"model_id": 12
},
"aggregation": "count",
"transformation": null,
"condition": {
"operator": "greater_than",
"modifier": null,
"values": [35000]
}
}
],
# Destination for the Alert
"dest": {
"type": "EmailDest",
"title": "The number of orders has just exceeded than 35000",
"recipients": [
"[email protected]"
],
"options": {
"body_text": null
}
},
# Schedule for the Alert to be Triggered
"schedule": {
# Repeat Everyday at 7:00 AM
"repeat": "0 7 * * *",
"paused": false
},
# Dynamic Filter Presets for the Alert
"dynamic_filter_presets": [
{
"preset_condition": {
"operator": "is",
"modifier": null,
"values": ["VN", "SG"],
},
"dynamic_filter_id": 1
},
{
"preset_condition": {
"operator": "is",
"modifier": null,
"values": [
"Male"
],
},
"dynamic_filter_id": 2
}
]
}
}.to_json
# Step 4: Send the request to Holistics!
response = Net::HTTP.start(
DATA_ALERT_ENDPOINT.hostname,
DATA_ALERT_ENDPOINT.port,
:use_ssl => DATA_ALERT_ENDPOINT.scheme == "https",
) do |https|
https.request(request)
end
# Optional: Output the result into the terminal
puts [response.code,response.message].join(' ')
In Holistics, you can set up schedules sending reports or dashboards to a group of recipients via email, Slack, SFTP, or Azure Blob. This concept is called Data Schedule.
Holistics offers a set of public API endpoints allowing clients to work with Data Schedule. This tutorial shows you how to use the API to create these data schedules programmatically.
Suppose you are a B2B SaaS company that has a feature to email usage statistics to your customers every week. You want to set it up such that:
- When a new customer onboards to your platform, you want Holistics to send a weekly email report to that customer.
- The weekly email reports should be customised to display information regarding the usage data of that customer only
Let's walk through how we can solve this problem using Holistics API.
We will use the API to create email reports. Specifically, we'll send a POST request to Holistics' create email schedule API.
Before that, we need to prepare the following:
- A dashboard with relevant reports. This dashboard will be emailed to the customer.
- The dashboard should have a "Customer" filter to filter down the data for a particular customer.
- Holistics API Key: We need to setup the API key. Refer to this guide for info.
You will need to create a master dashboard that contains the reports you want to send to the customers. In this example, we have a Customer Usage Data
dashboard which showcases the statistics of jobs that Holistics customers execute in our platform. We also have two filters in this dashboard, Date Range
and Customer
.
- The Customer ID filter accepts a customer ID, then passes it to the report within the dashboard. The report then replaces the ID with its placeholder in a prepared SQL query, reruns the query, and fetches only data that belongs to that customer. In other words, this filter helps filter down to the usage data of that customer only.
- Similarly, the Date Range filter's value accepts
"last 7 days"
,"last 14 days"
,"last 30 days"
, or"any time"
. This filter helps filter usage data by a date range. Note that this filter can be optional.
If you are not sure on how to create dashboards and filters, refer to Dashboard Docs.
We'll be using the following endpoint:
POST https://secure.holistics.io/api/v2/data_schedules
There are some notable configuration options in this request:
schedule
: Specify how frequent the email schedule should bedynamic_filter_presets
: Specify what dynamic filters should be applied to the reports. By configuring this, we can customise the report for each recipient.dest
: Specify configurations regarding recipients' information.- Remember to set
dest.type
to "EmailDest"
- Remember to set
Below is a sample request body. Refer to Holistics API docs for more information on these fields.
ⓘ INFO
💡 Most of the fields are straightforward which means that you can fill them out by reading our API docs. Refer to this section below for notes on trickier fields.
Common fields
id
(integer): This is used to uniquely identified your object. Holistics automatically generates an id for you if you don't specify this.source_id
(integer): This tells Holistics which dashboard you want to send email to. To determine this value, view your dashboard link. For example, the linkhttps://secure.holistics.io/dashboards/v3/16076-demo-my-beautiful-dashboard
will have thesource_id
of 16076.dest
: Specify the information regarding the recipientstitle
(string): Note that Holistics support dynamic variables in email title. For example, the titleSales report for {{$today}}
sent on 29/09/2021 will be rendered asSales report for 2021-09-29 Wed
.
Schedule frequency
schedule
is used to specify the schedule for your email schedule.
repeat
(string): You will need to input a crontab expression
here to let Holistics how frequent you want to your email schedule to run.
Dynamic filter values
dynamic-filter-presets
is where you define your filter presets here.
dynamic_filter_id
(integer): To get your filter_id
, send a GET request to Dashboards#Get API to get the dashboard info.
preset_conditions
(object): Let's go through our example to better illustrate this field.
We want to set a value for the filter by setting a preset condition. A preset condition consists of an operator and a list of values. Holistics supports various operators and provides several examples here.
In this case, we want to use operator is
and set values to customer_id
. By this, we mean the filter's default value equals exactly to customer_id
.
Finally, we also want to set up another dynamic filter preset to filter data to the whole of last week. Fortunately, Holistics allows a list of dynamic filter presets. For the Date Range filter, we similarly want to use operator is
and set values to "last 7 days"
.
Our final dynamic_filter_presets
object will look like this.
dynamic_filter_presets = [
{
"dynamic_filter_id": MY_CUSTOMER_FILTER_ID,
"preset_condition": {
"operator": "is",
"values": [
customer_id
]
}
},
{
"dynamic_filter_id": MY_DATE_RANGE_FILTER_ID,
"preset_condition": {
"operator": "is",
"values": [
"last 7 days"
]
}
}
]
Step 3: Double-check to see if your email schedule is created
The request should now be ready. After sending it to Holistics, the server will respond with a HTTP status response code to indicate whether the request was successful / failed.
Lastly, be sure to head over to Holistics page to see if your email schedule is created.
Example script
An example script to send requests written in Ruby is available here:
# install the neccessary dependencies for this script to work
require "bundler/inline"
require "net/http"
require "json"
gemfile do
source "https://rubygems.org"
gem "net-http"
end
# this the Holisitics API endpoint that we need to send our POST request to
EMAIL_SCHEDULE_ENDPOINT = URI("https://secure.holistics.io/api/v2/data_schedules")
# Step 1: Create a POST request to the endpoint below
request = Net::HTTP::Post.new(EMAIL_SCHEDULE_ENDPOINT)
# Step 2: Provide your authentication information
request["X-Holistics-Key"] = "mysecretAPIkey"
# Step 2.1: This line helps the system know that we are sending a JSON request
request.content_type = "application/json"
# Step 3: Provide information for your email schedule in the request body
request.body =
{
"data_schedule": {
"source_type": "Dashboard",
"source_id": 16076,
"schedule": {
"repeat": "* * * * *",
"paused": false,
},
"dest": {
"type": "EmailDest",
"title": "Sale report for {{$today}}",
"recipients": [
"[email protected]",
],
},
},
}.to_json
# Step 4: Send the request to Holistics!
response = Net::HTTP.start(
EMAIL_SCHEDULE_ENDPOINT.hostname,
EMAIL_SCHEDULE_ENDPOINT.port,
:use_ssl => EMAIL_SCHEDULE_ENDPOINT.scheme == "https",
) do |https|
https.request(request)
end
# Optional: Output the result into the terminal
puts [response.code,response.message].join(' ')
💡 NOTE
The current Holistics CLI version is: 0.4.0.
Requirements:
- Ruby 2.7
Holistics CLI is an interface to Holistics Data Preparation module (like data transport, data transform, import).
Linux/Mac OSX
If you are using Linux/Mac OSX, we suggest you install Ruby with a Ruby Version Manager such as rbenv or asdf.
Please follow the instructions in your RVM of choice to install Ruby 2.7.4:
- rbenv: https://github.com/rbenv/rbenv#installation.
- asdf: https://asdf-vm.com/guide/getting-started.html.
After you have Ruby installed on your computer, run:
gem install holistics -v 0.4.0
Windows
If you are using Windows, head over to: Official Ruby Download Page.
And download Ruby 2.7.4 installer. Remember to select the Devkit
option for your installer so that you
can run the gem install
command in the next step from your command line.
After you have Ruby installed on your computer, run:
gem install holistics -v 0.4.0
The next step is authentication. You first need to be granted permissions to have an API authentication token. If you are not sure how, visit: API Authentication.
Assuming that the above step is successful, you can access your token by going to ⚙️ My Account -> API Key. After that, run this in your command line to authenticate yourself.
$ holistics login <my_authentication_token>
Authenticating token...
Authentication successful. Info:
- ID: 1
- Email: admin@you.com
ⓘ IMPORTANT - INVALID AUTHENTICATION TOKEN ERROR
By default, the CLI connects to the Asia-Pacific servers. If your account is in another server (EU or US), you will have to specify the
HOLISTICS_HOST
> environment variable in your authentication command.👉 If you are not sure what server you are on, please follow this guide to find out.
Assuming you are in EU server (https://eu.holistics.io), the command will now become:
HOLISTICS_HOST=https://eu.holistics.io holistics login
You will need to prepend every command with
HOLISTICS_HOST=https://eu.holistics.io
.Alternatively, specify it only once as a global variable by running:
export HOLISTICS_HOST=https://eu.holistics.io
And you can run the commands without prepending the host everytime.
This documentation will guide you through the process of transitioning from API V1 to the new API V2. It will also provide information about the migration plan and outline what you can expect in our new API version. Our primary goal is to assist you in achieving a smooth and successful transition to Holistics’s latest API version.
For the past few months, we have considered API V1 as our legacy API. While it is still functional, it is not actively maintained. Meanwhile, we have been developing API V2 as a more powerful, flexible, and well-structured version of V1.
Now that API V2 has surpassed its predecessor in both functionality and experience, we are deprecating V1 and are here to assist you in migrating your applications to V2.
ⓘ INFO
The entire API V1 will cease to function by November 20th, 2023.
This deprecation includes all functionalities available in these two V1 kits:
Be assured that we have supported all of these functionalities API in V2.
Next steps, you will need to manually update your applications that are utilizing V1 to switch them to V2.
How will the migration affect existing applications that are utilizing API V1?
- We expect no interference in your automation workflow after the migration since all functionalities of V1 are completely covered by V2
- However, since there will be some differences in the data schema (or response structure) between the two versions, you would need to follow our documents to set up precisely
Should I do anything prior to this migration?
We suggest you check which applications will be affected by such an update, and inform your team that they will not be available during that time.
What do I do if I encounter unexpected issues?
We are committed to providing support throughout the migration. If you encounter any problems, please reach out to us at support@holistics.io for assistance.
Async (asynchronous) operations are operations that are executed within a background Job.
If an API endpoint triggers an async operation, it will return an AsyncResult response containing the background Job info.
You can use the bellow APIs to poll for the updated Job status.
List Jobs
Authorizations:
query Parameters
ids required | Array of integers IDs of the Jobs that you want to list. Non-existent IDs will be ignored. |
include_data_source_stats | boolean Include |
include_source | boolean Include |
Responses
Response samples
- 200
- 400
{- "jobs": [
- {
- "id": 0,
- "user_id": 0,
- "start_time": "string",
- "end_time": "string",
- "cancellable": true,
- "last_error_log": "string",
- "data_source_stats": [
- {
- "id": "XoBDpSVo2mMsHiQHNrPtEtfnozm",
- "cost": 1681980,
- "cost_unit": "B"
}
], - "source": {
- "type": "Dashboard",
- "id": "1",
- "action": "view_viz",
- "details": {
- "block_id": "v1",
- "block_type": "VizBlock",
- "block_display_title": "Yearly Report"
}
}, - "status": "created"
}
]
}
Get a Job
Authorizations:
path Parameters
id required | integer Resource id with type integer |
query Parameters
include_data_source_stats | boolean Include |
include_source | boolean Include |
Responses
Response samples
- 200
{- "job": {
- "id": 0,
- "user_id": 0,
- "start_time": "string",
- "end_time": "string",
- "cancellable": true,
- "last_error_log": "string",
- "data_source_stats": [
- {
- "id": "XoBDpSVo2mMsHiQHNrPtEtfnozm",
- "cost": 1681980,
- "cost_unit": "B"
}
], - "source": {
- "type": "Dashboard",
- "id": "1",
- "action": "view_viz",
- "details": {
- "block_id": "v1",
- "block_type": "VizBlock",
- "block_display_title": "Yearly Report"
}
}, - "status": "created"
}
}
Get Job result
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Responses
Response samples
- 200
- 422
{- "status": "success",
- "error": null,
- "result": {
- "type": "SubmitPublishJobResult",
- "data": {
- "status": "error",
- "error_type": "syntax_error",
- "error_details": {
- "diagnostics": [
- {
- "category": "Error",
- "code": 0,
- "message": "string",
- "file_path": "string",
- "start": 0,
- "end": 0
}
]
}, - "target_commit": "string"
}
}
}
Publish the AML Project to Production
Authorizations:
Request Body schema: application/json
object associate an deploying object with an orphan reporting object | |||
|
Responses
Request samples
- Payload
{- "object_mapping": {
- "datasets": { }
}
}
Response samples
- 200
- 403
- 404
- 422
{- "job": {
- "id": 0,
- "status": "created"
}
}
Validate AML Project
Authorizations:
Request Body schema: application/json
branch_name required | string Branch name to run validation |
commit_oid required | string Commit oid to run validation |
Responses
Request samples
- Payload
{- "branch_name": "string",
- "commit_oid": "string"
}
Response samples
- 200
- 403
- 404
- 422
{- "job": {
- "id": 0,
- "status": "created"
}
}
List Dashboards
Authorizations:
query Parameters
before | string Only get records before this cursor. |
after | string Only get records after this cursor. |
limit | integer [ 1 .. 100 ] Default: 20 Limit number of records per page. |
sort | string Default: "natural" Enum: "natural" "id_asc" "id_desc" Sort dashboards according to the specified sort order. |
include_embed_info | boolean Decide whether embed info is included or not. |
Responses
Response samples
- 200
- 403
{- "dashboards": [
- {
- "id": 0,
- "owner_id": 0,
- "title": "string",
- "category_id": 0,
- "version": 1,
- "dynamic_filters": [
- {
- "id": 0,
- "order": 0,
- "uname": "string",
- "permissions": {
- "read": true,
- "crud": true,
- "use": true
}, - "definition": {
- "id": 0,
- "label": "string",
- "default_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "filter_type": "number",
- "input_type": "single_select",
- "is_sharable": true,
- "filter_source": {
- "manual_options": [
- {
- "value": "string"
}
], - "source_type": "ManualFilterSource"
}, - "constraints": { }
}, - "drillthrough_enabled": true,
- "mappings": [
- {
- "id": 0,
- "viz_conditionable_id": 0,
- "viz_conditionable_type": "DashboardWidget",
- "field_path": {
- "field_name": "string",
- "model_id": 0,
- "data_set_id": 0,
- "is_metric": true
}, - "aggregation": "string",
- "permissions": {
- "crud": true
}
}
]
}
], - "widgets": [
- {
- "id": "string",
- "source_id": "string",
- "source_type": "QueryReport",
- "source_title": "string",
- "permissions": {
- "can_explore": true,
- "can_export": true,
- "can_export_data": true
}, - "url": "string",
- "dashboard": { },
- "query_report": {
- "id": 0,
- "title": "string",
- "data_set_id": 0,
- "viz_setting": {
- "viz_type": "data_table",
- "source_id": 0,
- "adhoc_fields": [
- { }
], - "fields": { },
- "settings": { },
- "format": { },
- "filters": [
- { }
], - "hashid": "string",
- "custom_chart_id": 0
}, - "data_source_id": 0,
- "owner_id": 0,
- "category_id": 0,
- "is_adhoc": true,
- "personal_item": {
- "id": 0,
- "owner_id": 0,
- "category_id": 0
}
}
}
], - "url": "string",
- "embed_info": {
- "hash_code": "string",
- "secret_key": "string"
}
}
], - "cursors": {
- "previous": "string",
- "next": "string"
}
}
Get a Dashboard
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Responses
Response samples
- 200
- 403
{- "dashboard": {
- "id": 0,
- "owner_id": 0,
- "title": "string",
- "category_id": 0,
- "version": 1,
- "dynamic_filters": [
- {
- "id": 0,
- "order": 0,
- "uname": "string",
- "permissions": {
- "read": true,
- "crud": true,
- "use": true
}, - "definition": {
- "id": 0,
- "label": "string",
- "default_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "filter_type": "number",
- "input_type": "single_select",
- "is_sharable": true,
- "filter_source": {
- "manual_options": [
- {
- "value": "string"
}
], - "source_type": "ManualFilterSource"
}, - "constraints": { }
}, - "drillthrough_enabled": true,
- "mappings": [
- {
- "id": 0,
- "viz_conditionable_id": 0,
- "viz_conditionable_type": "DashboardWidget",
- "field_path": {
- "field_name": "string",
- "model_id": 0,
- "data_set_id": 0,
- "is_metric": true
}, - "aggregation": "string",
- "permissions": {
- "crud": true
}
}
]
}
], - "widgets": [
- {
- "id": "string",
- "source_id": "string",
- "source_type": "QueryReport",
- "source_title": "string",
- "permissions": {
- "can_explore": true,
- "can_export": true,
- "can_export_data": true
}, - "url": "string",
- "dashboard": { },
- "query_report": {
- "id": 0,
- "title": "string",
- "data_set_id": 0,
- "viz_setting": {
- "viz_type": "data_table",
- "source_id": 0,
- "adhoc_fields": [
- { }
], - "fields": { },
- "settings": { },
- "format": { },
- "filters": [
- { }
], - "hashid": "string",
- "custom_chart_id": 0
}, - "data_source_id": 0,
- "owner_id": 0,
- "category_id": 0,
- "is_adhoc": true,
- "personal_item": {
- "id": 0,
- "owner_id": 0,
- "category_id": 0
}
}
}
], - "url": "string",
- "embed_info": {
- "hash_code": "string",
- "secret_key": "string"
}
}
}
Build a Dashboard URL with preset filter states
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Request Body schema: application/json
Array of objects (DynamicFilterCondition) | |||||
Array
|
Responses
Request samples
- Payload
{- "filter_states": [
- {
- "dynamic_filter_id": 0,
- "condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}
}
]
}
Response samples
- 200
- 403
- 404
- 422
{- "dashboard_url": "string",
- "fstate_hash": "string"
}
Preload a Dashboard
Preload a Dashboard by executing its widgets (using the submitted filter conditions, or default filter conditions if not submitted) and storing the widgets' results into Holistics cache.
Read more about Data Caching at https://docs.holistics.io/docs/data-caching.
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Request Body schema: application/json
Array of objects (DynamicFilterCondition) | |
bust_cache | boolean Default: false If set to True, ignore existing cache and always execute the widgets. Otherwise, do not execute the widgets that are already cached. |
Responses
Request samples
- Payload
{ }
Response samples
- 200
- 403
- 404
{- "job": {
- "id": 0,
- "status": "created"
}
}
Get a Dashboard Widget
Authorizations:
path Parameters
id required | integer Resource id with type integer |
query Parameters
include_dashboard | boolean Decide whether dashboard is included or not. |
include_report | boolean Decide whether report is included or not. |
include_url | boolean Decide whether dashboard url, widget url is included or not. |
Responses
Response samples
- 200
- 403
- 404
{- "dashboard_widget": {
- "id": "string",
- "source_id": "string",
- "source_type": "QueryReport",
- "source_title": "string",
- "permissions": {
- "can_explore": true,
- "can_export": true,
- "can_export_data": true
}, - "url": "string",
- "dashboard": {
- "id": 0,
- "owner_id": 0,
- "title": "string",
- "category_id": 0,
- "version": 1,
- "dynamic_filters": [
- {
- "id": 0,
- "order": 0,
- "uname": "string",
- "permissions": {
- "read": true,
- "crud": true,
- "use": true
}, - "definition": {
- "id": 0,
- "label": "string",
- "default_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "filter_type": "number",
- "input_type": "single_select",
- "is_sharable": true,
- "filter_source": {
- "manual_options": [
- {
- "value": "string"
}
], - "source_type": "ManualFilterSource"
}, - "constraints": { }
}, - "drillthrough_enabled": true,
- "mappings": [
- {
- "id": 0,
- "viz_conditionable_id": 0,
- "viz_conditionable_type": "DashboardWidget",
- "field_path": {
- "field_name": "string",
- "model_id": 0,
- "data_set_id": 0,
- "is_metric": true
}, - "aggregation": "string",
- "permissions": {
- "crud": true
}
}
]
}
], - "widgets": [
- { }
], - "url": "string",
- "embed_info": {
- "hash_code": "string",
- "secret_key": "string"
}
}, - "query_report": {
- "id": 0,
- "title": "string",
- "data_set_id": 0,
- "viz_setting": {
- "viz_type": "data_table",
- "source_id": 0,
- "adhoc_fields": [
- { }
], - "fields": { },
- "settings": { },
- "format": { },
- "filters": [
- { }
], - "hashid": "string",
- "custom_chart_id": 0
}, - "data_source_id": 0,
- "owner_id": 0,
- "category_id": 0,
- "is_adhoc": true,
- "personal_item": {
- "id": 0,
- "owner_id": 0,
- "category_id": 0
}
}
}
}
Export a Dashboard Widget
See more details on how to export a widget at Get Data. When the Job is finished, you can download the exported file using the download export API.
Authorizations:
path Parameters
required | string or integer Resource id. |
Request Body schema: application/json
output required | string Enum: "csv" "xlsx" "pdf" Output file type. |
Array of objects (DynamicFilterCondition) |
Responses
Request samples
- Payload
{- "output": "csv",
- "dashboard_filter_conditions": [
- {
- "dynamic_filter_id": 0,
- "condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}
}
]
}
Response samples
- 200
{- "job": {
- "id": 0,
- "status": "created"
}
}
Create a Data Schedule
Authorizations:
Request Body schema: application/json
required | object (DataSchedule) | ||||||||||||
|
Responses
Request samples
- Payload
{- "data_schedule": {
- "id": 1,
- "source_type": "Dashboard",
- "source_id": 1,
- "schedule": {
- "repeat": "* * * * *",
- "paused": false
}, - "dynamic_filter_presets": [
- {
- "id": 1,
- "dynamic_filter_id": 1,
- "public_hidden": true,
- "preset_condition": {
- "modifier": null,
- "operator": "is",
- "values": [
- "alice"
]
}
}
], - "dest": {
- "type": "EmailDest",
- "title": "Sale report for {{$today}}",
- "options": {
- "preview": true,
- "include_header": true,
- "include_report_link": true,
- "include_filters": false,
- "dont_send_when_empty": true,
- "body_text": "Report",
- "attachment_formats": [
- "pdf",
- "csv"
]
}
}
}
}
Response samples
- 201
- 403
- 422
{- "data_schedule": {
- "id": 0,
- "source_type": "Dashboard",
- "source_id": 0,
- "schedule": {
- "repeat": "string",
- "paused": true
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "dest": {
- "title": "string",
- "options": {
- "preview": true,
- "include_header": true,
- "include_report_link": true,
- "include_filters": true,
- "dont_send_when_empty": true,
- "body_text": "string",
- "attachment_formats": [
- "csv"
]
}, - "type": "EmailDest"
}
}
}
List Data Schedules
Authorizations:
query Parameters
before | string Only get records before this cursor. |
after | string Only get records after this cursor. |
limit | integer [ 1 .. 100 ] Default: 20 Limit number of records per page. |
dest_type | string Enum: "EmailDest" "SlackDest" "Adls2Dest" "SftpDest" Filter by destination type. |
source_type | string Enum: "QueryReport" "Dashboard" Filter by source type. |
source_id | integer Filter by source id. |
Responses
Response samples
- 200
- 401
{- "data_schedules": [
- {
- "id": 0,
- "source_type": "Dashboard",
- "source_id": 0,
- "schedule": {
- "repeat": "string",
- "paused": true
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "dest": {
- "title": "string",
- "options": {
- "preview": true,
- "include_header": true,
- "include_report_link": true,
- "include_filters": true,
- "dont_send_when_empty": true,
- "body_text": "string",
- "attachment_formats": [
- "csv"
]
}, - "type": "EmailDest"
}
}
], - "cursors": {
- "previous": "string",
- "next": "string"
}
}
Get a Data Schedule
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Responses
Response samples
- 200
- 403
- 404
{- "data_schedule": {
- "id": 0,
- "source_type": "Dashboard",
- "source_id": 0,
- "schedule": {
- "repeat": "string",
- "paused": true
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "dest": {
- "title": "string",
- "options": {
- "preview": true,
- "include_header": true,
- "include_report_link": true,
- "include_filters": true,
- "dont_send_when_empty": true,
- "body_text": "string",
- "attachment_formats": [
- "csv"
]
}, - "type": "EmailDest"
}
}
}
Update a Data Schedule
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Request Body schema: application/json
required | object (DataSchedule) | ||||||||||||
|
Responses
Request samples
- Payload
{- "data_schedule": {
- "id": 0,
- "source_type": "Dashboard",
- "source_id": 0,
- "schedule": {
- "repeat": "string",
- "paused": true
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "dest": {
- "title": "string",
- "options": {
- "preview": true,
- "include_header": true,
- "include_report_link": true,
- "include_filters": true,
- "dont_send_when_empty": true,
- "body_text": "string",
- "attachment_formats": [
- "csv"
]
}, - "type": "EmailDest"
}
}
}
Response samples
- 200
{- "data_schedule": {
- "id": 0,
- "source_type": "Dashboard",
- "source_id": 0,
- "schedule": {
- "repeat": "string",
- "paused": true
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "dest": {
- "title": "string",
- "options": {
- "preview": true,
- "include_header": true,
- "include_report_link": true,
- "include_filters": true,
- "dont_send_when_empty": true,
- "body_text": "string",
- "attachment_formats": [
- "csv"
]
}, - "type": "EmailDest"
}
}
}
Create a Data Alert
Authorizations:
Request Body schema: application/json
required | object (DataAlert) | ||||||||||||||||
|
Responses
Request samples
- Payload
{- "data_alert": {
- "id": 0,
- "title": "string",
- "source_id": 0,
- "source_type": "DashboardWidget",
- "dest": {
- "title": "string",
- "options": {
- "body_text": "string"
}, - "type": "EmailDest"
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "viz_conditions": [
- {
- "id": 0,
- "field_path": {
- "field_name": "string",
- "model_id": 0,
- "data_set_id": 0,
- "is_metric": true
}, - "aggregation": "sum",
- "transformation": "datetrunc year",
- "condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}
}
], - "schedule": {
- "repeat": "string",
- "paused": true
}
}
}
Response samples
- 201
- 400
- 403
- 422
{- "data_alert": {
- "id": 0,
- "title": "string",
- "source_id": 0,
- "source_type": "DashboardWidget",
- "dest": {
- "title": "string",
- "options": {
- "body_text": "string"
}, - "type": "EmailDest"
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "viz_conditions": [
- {
- "id": 0,
- "field_path": {
- "field_name": "string",
- "model_id": 0,
- "data_set_id": 0,
- "is_metric": true
}, - "aggregation": "sum",
- "transformation": "datetrunc year",
- "condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}
}
], - "schedule": {
- "repeat": "string",
- "paused": true
}
}
}
List Data Alerts
Authorizations:
query Parameters
before | string Only get records before this cursor. |
after | string Only get records after this cursor. |
limit | integer [ 1 .. 100 ] Default: 20 Limit number of records per page. |
search_term | string Search records by its name, title... |
dest_type | string Enum: "EmailDest" "SlackDest" Filter by destination type. |
integer or string Filter by source id. | |
source_type | string Enum: "DashboardWidget" "VizBlock" Filter by source type. |
Responses
Response samples
- 200
- 401
{- "data_alerts": [
- {
- "id": 0,
- "title": "string",
- "source_id": 0,
- "source_type": "DashboardWidget",
- "dest": {
- "title": "string",
- "options": {
- "body_text": "string"
}, - "type": "EmailDest"
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "viz_conditions": [
- {
- "id": 0,
- "field_path": {
- "field_name": "string",
- "model_id": 0,
- "data_set_id": 0,
- "is_metric": true
}, - "aggregation": "sum",
- "transformation": "datetrunc year",
- "condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}
}
], - "schedule": {
- "repeat": "string",
- "paused": true
}
}
], - "cursors": {
- "previous": "string",
- "next": "string"
}
}
Get a Data Alert
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Responses
Response samples
- 200
- 403
- 404
{- "data_alert": {
- "id": 0,
- "title": "string",
- "source_id": 0,
- "source_type": "DashboardWidget",
- "dest": {
- "title": "string",
- "options": {
- "body_text": "string"
}, - "type": "EmailDest"
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "viz_conditions": [
- {
- "id": 0,
- "field_path": {
- "field_name": "string",
- "model_id": 0,
- "data_set_id": 0,
- "is_metric": true
}, - "aggregation": "sum",
- "transformation": "datetrunc year",
- "condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}
}
], - "schedule": {
- "repeat": "string",
- "paused": true
}
}
}
Update a Data Alert
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Request Body schema: application/json
required | object (DataAlert) | ||||||||||||||||
|
Responses
Request samples
- Payload
{- "data_alert": {
- "id": 0,
- "title": "string",
- "source_id": 0,
- "source_type": "DashboardWidget",
- "dest": {
- "title": "string",
- "options": {
- "body_text": "string"
}, - "type": "EmailDest"
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "viz_conditions": [
- {
- "id": 0,
- "field_path": {
- "field_name": "string",
- "model_id": 0,
- "data_set_id": 0,
- "is_metric": true
}, - "aggregation": "sum",
- "transformation": "datetrunc year",
- "condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}
}
], - "schedule": {
- "repeat": "string",
- "paused": true
}
}
}
Response samples
- 200
- 422
{- "data_alert": {
- "id": 0,
- "title": "string",
- "source_id": 0,
- "source_type": "DashboardWidget",
- "dest": {
- "title": "string",
- "options": {
- "body_text": "string"
}, - "type": "EmailDest"
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "viz_conditions": [
- {
- "id": 0,
- "field_path": {
- "field_name": "string",
- "model_id": 0,
- "data_set_id": 0,
- "is_metric": true
}, - "aggregation": "sum",
- "transformation": "datetrunc year",
- "condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}
}
], - "schedule": {
- "repeat": "string",
- "paused": true
}
}
}
Execute a Test Data Alert
Authorizations:
Request Body schema: application/json
required | object (DataAlert) | ||||||||||||||||
|
Responses
Request samples
- Payload
{- "test_data_alert": {
- "id": 0,
- "title": "string",
- "source_id": 0,
- "source_type": "DashboardWidget",
- "dest": {
- "title": "string",
- "options": {
- "body_text": "string"
}, - "type": "EmailDest"
}, - "dynamic_filter_presets": [
- {
- "id": 0,
- "dynamic_filter_id": "string",
- "preset_condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}, - "public_hidden": false
}
], - "viz_conditions": [
- {
- "id": 0,
- "field_path": {
- "field_name": "string",
- "model_id": 0,
- "data_set_id": 0,
- "is_metric": true
}, - "aggregation": "sum",
- "transformation": "datetrunc year",
- "condition": {
- "modifier": "string",
- "operator": "string",
- "values": [
- "string"
]
}
}
], - "schedule": {
- "repeat": "string",
- "paused": true
}
}
}
Response samples
- 200
{- "job": {
- "id": 0,
- "status": "created"
}
}
Condition that can be applied on the Data Modeling layer to filter your data. See the examples in the Example panel.
required | Array of any |
modifier | string or null |
operator required | string |
{- "operator": "is",
- "values": [
- "string",
- "Bob"
], - "modifier": "string"
}
Get ids of objects which are dependent on the object you input. The response schema varies based on the input type and its current dependants.
Get object's downstream dependencies
Authorizations:
query Parameters
id required | integer Object id. |
type required | string Enum: "DataSource" "DataModel" "DataSet" Object type. |
Responses
Response samples
- 200
- 403
- 404
{- "dependants": {
- "data_model_ids": [
- 1,
- 2,
- 3
], - "data_set_ids": [
- 5,
- 6
]
}
}
List Users
Authorizations:
query Parameters
before | string Only get records before this cursor. |
after | string Only get records after this cursor. |
limit | integer [ 1 .. 100 ] Default: 20 Limit number of records per page. |
search_term | string Search by User |
status | string Enum: "active" "deleted" "pending" Filter by User status. |
role | string (UserRole) Enum: "user" "explorer" "analyst" "admin" "growth_admin" "it_admin" Filter by User |
has_authentication_token | boolean Whether or not to include users who have API key. Note: the result also includes users even when their API access has been revoked. |
exclude_deleted | boolean Whether or not to exclude deleted Users. |
sort | string Default: "natural" Enum: "natural" "id_asc" "id_desc" "name_asc" "name_desc" "initials_asc" "initials_desc" Sort the Users according to the specified sort order. If multiple records have the same value, the corresponding order of User |
Responses
Response samples
- 200
{- "counters": {
- "total": 0,
- "by_role": {
- "viewer": 0,
- "explorer": 0,
- "analyst": 0,
- "admin": 0,
- "growth_admin": 0
}
}, - "users": [
- {
- "group_ids": [
- 0
], - "id": 0,
- "email": "string",
- "name": "string",
- "initials": "string",
- "role": "user",
- "is_deleted": true,
- "is_activated": true,
- "has_authentication_token": true,
- "allow_authentication_token": true,
- "enable_export_data": true,
- "current_sign_in_at": "2019-08-24T14:15:22Z",
- "last_sign_in_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "title": "string",
- "job_title": "string"
}
], - "groups": {
- "1": {
- "id": 1,
- "name": "string"
}, - "2": {
- "id": 2,
- "name": "string"
}
}, - "cursors": {
- "previous": "string",
- "next": "string"
}
}
Update a User
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Request Body schema: application/json
object | |||||||||||||||||
|
Responses
Request samples
- Payload
{- "user": {
- "password": "string",
- "name": "string",
- "title": "string",
- "job_title": "string",
- "role": "user",
- "allow_authentication_token": true,
- "enable_export_data": true,
- "group_ids": [
- 0
]
}
}
Response samples
- 200
- 403
- 422
{- "id": 0,
- "email": "string",
- "name": "string",
- "initials": "string",
- "role": "user",
- "is_deleted": true,
- "is_activated": true,
- "has_authentication_token": true,
- "allow_authentication_token": true,
- "enable_export_data": true,
- "current_sign_in_at": "2019-08-24T14:15:22Z",
- "last_sign_in_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "title": "string",
- "job_title": "string"
}
Delete a User (soft-delete)
Revoke a User from accessing and using Holistics.
Note: The soft-deleted User will still retain ownership of their resources. You can contact support@holistics.io to request for an ownership transfer.
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Responses
Response samples
- 200
- 403
- 404
- 422
{- "message": "string"
}
Invite Users
Authorizations:
Request Body schema: application/json
emails required | Array of strings List of User emails to invite. |
role required | string Enum: "user" "explorer" "analyst" "admin" "growth_admin" "it_admin" User role. |
allow_authentication_token | boolean Allow Users to have API access. |
enable_export_data | |
group_ids | Array of integers List of Group ids that the Users will be assigned to. |
message | string Greeting message that will be sent to all User emails. |
Responses
Request samples
- Payload
{- "emails": [
- "string"
], - "role": "user",
- "allow_authentication_token": true,
- "enable_export_data": true,
- "group_ids": [
- 0
], - "message": "string"
}
Response samples
- 200
- 403
- 422
{- "job": {
- "id": 0,
- "status": "created"
}
}
Check if email address is used
Check if the specified email address is already used for a User in your Holistics workspace.
Authorizations:
query Parameters
string Query parameter for email attribute. |
Responses
Response samples
- 200
- 403
{- "is_already_user": true
}
Response samples
- 200
- 401
{- "user": {
- "id": 0,
- "email": "string",
- "name": "string",
- "initials": "string",
- "role": "user",
- "is_deleted": true,
- "is_activated": true,
- "has_authentication_token": true,
- "allow_authentication_token": true,
- "enable_export_data": true,
- "current_sign_in_at": "2019-08-24T14:15:22Z",
- "last_sign_in_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "title": "string",
- "job_title": "string"
}
}
Create a Group
Authorizations:
Request Body schema: application/json
required | object | ||
|
Responses
Request samples
- Payload
{- "group": {
- "name": "string"
}
}
Response samples
- 201
- 403
- 422
{- "group": {
- "id": 0,
- "name": "string",
- "user_ids": [
- 0
]
}
}
List Groups
Authorizations:
query Parameters
before | string Only get records before this cursor. |
after | string Only get records after this cursor. |
limit | integer [ 1 .. 100 ] Default: 20 Limit number of records per page. |
sort | string Default: "natural" Enum: "natural" "id_asc" "id_desc" Sort groups according to the specified sort order. |
include_users | boolean Include users in the response. |
Responses
Response samples
- 200
- 403
{- "groups": [
- {
- "id": 1,
- "name": "sample_group",
- "user_ids": [
- 1,
- 2
]
}
], - "users": {
- "1": {
- "id": 1,
- "name": "admin_user",
- "initials": "string",
- "role": "user",
- "is_deleted": false,
- "is_activated": true,
- "has_authentication_token": true,
- "allow_authentication_token": true,
- "enable_export_data": true,
- "current_sign_in_at": "2019-08-24T14:15:22Z",
- "last_sign_in_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "title": "admin_user",
- "job_title": "admin"
}, - "2": {
- "id": 2,
- "name": "analyst_user",
- "initials": "string",
- "role": "user",
- "is_deleted": false,
- "is_activated": true,
- "has_authentication_token": true,
- "allow_authentication_token": true,
- "enable_export_data": true,
- "current_sign_in_at": "2019-08-24T14:15:22Z",
- "last_sign_in_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "title": "analyst_user",
- "job_title": "analyst"
}
}, - "cursors": {
- "previous": "string",
- "next": "string"
}
}
Get a Group
Authorizations:
path Parameters
id required | integer Resource id with type integer |
query Parameters
include_users | boolean Whether to include Users information. |
Responses
Response samples
- 200
- 403
- 404
{- "group": {
- "id": 0,
- "name": "string",
- "user_ids": [
- 0
]
}
}
Update a Group
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Request Body schema: application/json
required | object | ||
|
Responses
Request samples
- Payload
{- "group": {
- "name": "string"
}
}
Response samples
- 200
- 403
- 404
- 422
{- "group": {
- "id": 0,
- "name": "string",
- "user_ids": [
- 0
]
}
}
Create a Shortened embed token
Use this API to shorten the embed token if the URL exceeds the browser's size limit.
path Parameters
hashcode required | string The embed code of the dashboard for shortening the token. |
Request Body schema: application/json
token required | string |
Responses
Request samples
- Payload
{- "token": "string"
}
Response samples
- 201
- 400
- 401
- 404
{- "shortened_token": "string"
}
Get a Data Source
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Responses
Response samples
- 200
- 403
- 404
{- "data_source": {
- "id": 0,
- "name": "string",
- "dbtype": "string",
- "settings": {
- "require_ssl": true,
- "query_timeout": 0,
- "enable_schema_info": true,
- "use_connection_str": true,
- "timezone": "string"
}, - "is_sample": true,
- "is_default": true
}
}
Update a Data Source
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Request Body schema: application/json
required | object | ||||||
|
Responses
Request samples
- Payload
{- "data_source": {
- "name": "string",
- "settings": {
- "require_ssl": true,
- "query_timeout": 0,
- "enable_schema_info": true,
- "use_connection_str": true,
- "timezone": "string"
}, - "dbconfig": {
- "database": "string",
- "host": "string",
- "port": "string",
- "username": "string",
- "password": "string"
}
}
}
Response samples
- 200
- 403
- 404
{- "data_source": {
- "id": 0,
- "name": "string",
- "dbtype": "string",
- "settings": {
- "require_ssl": true,
- "query_timeout": 0,
- "enable_schema_info": true,
- "use_connection_str": true,
- "timezone": "string"
}, - "is_sample": true,
- "is_default": true
}
}
Bust Exploration Cache (Beta)
This feature is currently in Beta.
Bust (invalidate) all exploration/report cache of the specified Data Source. After a successful busting, all explorations/reports running on the specified Data Source will return fresh data.
Please note that this does not bust or trigger the Data Source's Model Storages. Hence, even after calling this API, the explorations/reports can only be as fresh as the data persisted in the Model Storages.
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Responses
Response samples
- 200
- 403
- 404
{- "job": {
- "id": 0,
- "status": "created"
}
}
Get a Data Set
Authorizations:
path Parameters
id required | integer Resource id with type integer |
query Parameters
include_models | boolean Decide whether data models are included or not. |
include_reports | boolean Decide whether query reports are included or not. |
Responses
Response samples
- 200
- 403
- 404
- 429
{- "data_set": {
- "data_models": [
- {
- "id": 0,
- "data_source_id": 0,
- "name": "string",
- "label": "string",
- "fields": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "dimensions": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "measures": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "params": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "category_id": 0,
- "metadata": { },
- "sql": "string",
- "table_name": "string"
}
], - "reports": [
- {
- "id": 0,
- "title": "string",
- "data_set_id": 0,
- "viz_setting": {
- "viz_type": "data_table",
- "source_id": 0,
- "adhoc_fields": [
- { }
], - "fields": { },
- "settings": { },
- "format": { },
- "filters": [
- { }
], - "hashid": "string",
- "custom_chart_id": 0
}, - "data_source_id": 0,
- "owner_id": 0,
- "category_id": 0,
- "is_adhoc": true,
- "personal_item": {
- "id": 0,
- "owner_id": 0,
- "category_id": 0
}
}
], - "id": 0,
- "name": "string",
- "label": "string",
- "description": "string",
- "owner_id": 0,
- "owner": "string",
- "tenant_id": 0,
- "data_source_id": 0,
- "category_id": 0,
- "related_joins": [
- {
- "id": 0,
- "name": "string",
- "link_type": "string",
- "join_on": "string",
- "data_source_id": 0,
- "source_model_id": 0,
- "dest_model_id": 0,
- "source_model": {
- "id": 0,
- "name": "string"
}, - "dest_model": {
- "id": 0,
- "name": "string"
}, - "missing_source_fields": [
- "string"
], - "missing_dest_fields": [
- "string"
]
}
], - "join_configs": [
- {
- "id": 0,
- "data_set_id": 0,
- "join_id": 0,
- "active": true,
- "direction": "string",
- "join": {
- "name": "string",
- "source_model": "string",
- "dest_model": "string",
- "link_type": "string",
- "join_on": "string"
}
}
], - "permission": {
- "can_crud": true,
- "can_read": true
}, - "uname": "string",
- "from_aml": true,
- "project_id": 0
}
}
Delete a Data Set.
We do not support deleting data set created from AML yet, try deleting it from AML Studio. Send your request to support@holistics.io if you have any concern.
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Responses
Response samples
- 200
- 403
- 404
- 422
{- "message": "string"
}
List Data Models
Authorizations:
query Parameters
project_id required | integer AML Project Id |
branch_name | string Branch name to get list of models. branch_name param will be ignore if commit_oid is available. |
commit_oid | string Commit oid to get list of models. |
Responses
Response samples
- 200
- 403
- 404
{- "data_models": [
- {
- "id": 0,
- "data_source_id": 0,
- "name": "string",
- "label": "string",
- "fields": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "dimensions": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "measures": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "params": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "category_id": 0,
- "metadata": { },
- "sql": "string",
- "table_name": "string"
}
]
}
Get a Query Report
Authorizations:
path Parameters
id required | integer Resource id with type integer |
query Parameters
include_data_set | boolean Decide whether Data Set is included or not. |
Responses
Response samples
- 200
- 403
- 404
{- "query_report": {
- "data_set": {
- "id": 0,
- "name": "string",
- "label": "string",
- "description": "string",
- "owner_id": 0,
- "owner": "string",
- "tenant_id": 0,
- "data_source_id": 0,
- "category_id": 0,
- "related_joins": [
- {
- "id": 0,
- "name": "string",
- "link_type": "string",
- "join_on": "string",
- "data_source_id": 0,
- "source_model_id": 0,
- "dest_model_id": 0,
- "source_model": {
- "id": 0,
- "name": "string"
}, - "dest_model": {
- "id": 0,
- "name": "string"
}, - "missing_source_fields": [
- "string"
], - "missing_dest_fields": [
- "string"
]
}
], - "join_configs": [
- {
- "id": 0,
- "data_set_id": 0,
- "join_id": 0,
- "active": true,
- "direction": "string",
- "join": {
- "name": "string",
- "source_model": "string",
- "dest_model": "string",
- "link_type": "string",
- "join_on": "string"
}
}
], - "data_models": [
- {
- "id": 0,
- "data_source_id": 0,
- "name": "string",
- "label": "string",
- "fields": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "dimensions": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "measures": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "params": [
- {
- "aggregation_type": "avg",
- "custom_label": "string",
- "field_format": "string",
- "description": "string",
- "is_custom": true,
- "is_custom_measure": true,
- "label": "string",
- "model": {
- "id": "string",
- "name": "string"
}, - "name": "string",
- "sql": "string",
- "transform_type": "datetrunc year",
- "type": "date",
- "syntax": "sql"
}
], - "category_id": 0,
- "metadata": { },
- "sql": "string",
- "table_name": "string"
}
], - "permission": {
- "can_crud": true,
- "can_read": true
}, - "uname": "string",
- "from_aml": true,
- "project_id": 0
}, - "id": 0,
- "title": "string",
- "data_set_id": 0,
- "viz_setting": {
- "viz_type": "data_table",
- "source_id": 0,
- "adhoc_fields": [
- { }
], - "fields": { },
- "settings": { },
- "format": { },
- "filters": [
- { }
], - "hashid": "string",
- "custom_chart_id": 0
}, - "data_source_id": 0,
- "owner_id": 0,
- "category_id": 0,
- "is_adhoc": true,
- "personal_item": {
- "id": 0,
- "owner_id": 0,
- "category_id": 0
}
}
}
Create a User Attribute
Authorizations:
Request Body schema: application/json
required | object (UserAttributeInput) | ||||||||
|
Responses
Request samples
- Payload
{- "user_attribute": {
- "name": "string",
- "attribute_type": "string",
- "label": "string",
- "description": "string"
}
}
Response samples
- 200
- 401
- 422
{- "user_attribute": {
- "id": 0,
- "name": "string",
- "attribute_type": "string",
- "label": "string",
- "description": "string",
- "is_system_attribute": false
}, - "status": "created"
}
List User Attributes
List User Attributes including System Attributes
Authorizations:
query Parameters
before | string Only get records before this cursor. |
after | string Only get records after this cursor. |
limit | integer [ 1 .. 100 ] Default: 20 Limit number of records per page. |
Responses
Response samples
- 200
- 401
{- "user_attributes": [
- {
- "id": 0,
- "name": "string",
- "attribute_type": "string",
- "label": "string",
- "description": "string",
- "is_system_attribute": false
}
], - "cursors": {
- "previous": "string",
- "next": "string"
}
}
Update a User Attribute
Authorizations:
path Parameters
id required | integer Resource id with type integer |
Request Body schema: application/json
required | object (UserAttributeInput) | ||||||||
|
Responses
Request samples
- Payload
{- "user_attribute": {
- "name": "string",
- "attribute_type": "string",
- "label": "string",
- "description": "string"
}
}
Response samples
- 200
- 401
- 403
- 422
{- "user_attribute": {
- "id": 0,
- "name": "string",
- "attribute_type": "string",
- "label": "string",
- "description": "string",
- "is_system_attribute": false
}
}
List User Attribute Entries
Authorizations:
query Parameters
subject_type required | string Enum: "User" "Group" Subject type. |
subject_id required | number Subject Id. |
Responses
Response samples
- 200
- 401
- 403
{- "user_attribute_entries": [
- {
- "user_attribute_id": 0,
- "input_type": "manual",
- "subject_type": "User",
- "subject_id": 0
}
], - "cursors": {
- "previous": "string",
- "next": "string"
}
}
Compute User Attribute Values
Authorizations:
query Parameters
subject_type required | string Enum: "User" "Group" Subject type. |
subject_id required | number Subject Id. |
Responses
Response samples
- 200
- 401
- 403
{- "user_attribute_values": {
- "user_attribute_name_1": [
- "value_1",
- "value_2"
]
}
}
Upsert User Attribute Entries
Authorizations:
Request Body schema: application/json
required | Array of with User Attribute name (object) or with User Attribute ID (object) The number of entries that can be processed at once is limited to 100. | ||||||||||
Array Any of
|
Responses
Request samples
- Payload
{- "user_attribute_entries": [
- {
- "input_type": "manual",
- "values": [
- "string"
], - "subject_type": "User",
- "subject_id": 0,
- "user_attribute_id": 0
}
]
}
Response samples
- 200
- 400
- 401
- 403
- 404
- 422
{- "user_attribute_entries": [
- {
- "user_attribute_id": 0,
- "input_type": "manual",
- "subject_type": "User",
- "subject_id": 0
}
]
}