Aggregation API

Watershed receives data from various data sources via xAPI, aggregates that data and then displays it in insightful reports and visualizations. Sometimes clients want to make use of that aggregated data outside of Watershed. This guide explains how.

The Aggregation API allows you to fetch aggregated data from Watershed where there is not an existing report to aggregate this data. Like report data, Aggregation API data is cached to avoid performance issues relating to multiple requests for the same data.

API

This section outlines the allowed resources and methods of the Aggregation API.

Connecting to the Aggregation API

Our family of REST APIs are made accessible through a secure SSL connection over HTTPS, using basic authentication. To connect to Watershed’s API you need a set of credentials and organization id (unless you are creating an organization, then you don’t need the id).

To create a set of credentials, see How do I add an activity provider to Watershed? You are able to choose if credentials have access to the LRS API, the Reporting API or both.

This is passed to the API using Basic HTTPS Authentication. In addition to the Authorization header required for Basic Authentication, all POST and PUT requests must have a Content-Type header with the value application/json.

The easiest way to find the organization id is to log in to Watershed and go to the Settings/Data page. The organization id is included within the Watershed LRS Endpoint URL. For example if the endpoint URL is https://watershedlrs.com/api/organizations/1234/lrs/ then the organization id is 1234.

Get aggregated data as a csv

Request URL: /api/organizations/[org-id]/aggregation/csv

Method: GET

Expected response code: 200 OK

Request parameters

Parameter

Details

config

A configuration object with filter, dimension and measure properties, much like the advanced configuration of a leaderboard report. The dimension defines the rows of the aggregated data whilst the measures define the columns.

name

The name of the csv file Watershed will return.

Response

A successful response will return a csv file containing the requested data. The first row of this file after the headers will contain an average for each measure.

Using a leaderboard report to create the configuration object

One way to create the configuration object for use with Aggregation API requests is to create a Leaderboard report that generate the data you require and then copy the configuration from that. To do this you should:

  1. Create and save a Leaderboard report displaying the data you want.
  2. Copy the Leaderboard's configuration by configuring the report then choosing Advanced configuration.
  3. For each measure, delete the id and fingerprint properties.

Example

This is an advanced configuration from a basic leaderboard:

{
"filter": {
"activityIds": {
"ids": [
"http://video.portal.example.com/search"
]
},
"personIds": null,
"groupIds": null,
"dateFilter": {
"dateType": "none",
"trailingAmount": 1,
"trailingType": "days",
"olderThanAmount": 0,
"olderThanType": "none",
"fieldName": "timestamp"
},
"includeRelatedActivities": false,
"verbIds": {
"ids": [
"http://activitystrea.ms/schema/1.0/search"
]
},
"activityTypes": null
},
"quickFilters": {
"activities": {
"type": "all"
},
"people": {
"type": "all"
},
"verbs": {
"type": "all"
},
"dates": {
"type": "all"
}
},
"cardText": {
"cardView": {
"dimension": "Search Term"
},
"detailView": {
"dimension": "Search Term"
}
},
"version": 3,
"cachingMinutes": 1440,
"colors": [],
"dimensions": [
{
"type": "STATEMENT_PROPERTY",
"statementProperty": "result.response",
"caseSensitive": true
}
],
"measures": [
{
"name": "Count",
"aggregation": {
"type": "COUNT"
},
"valueProducer": {
"type": "STATEMENT_PROPERTY",
"statementProperty": "object.id",
"caseSensitive": true
}
},
{
"name": "People",
"aggregation": {
"type": "DISTINCT_COUNT"
},
"valueProducer": {
"type": "STATEMENT_PROPERTY",
"statementProperty": "actors.person.id",
"caseSensitive": true
}
}
],
"includePeopleWithoutStatements": false,
"displayAxisDecimals": true,
"hiddenMeasures": [],
"showSentence": false,
"hideDimension": false,
"type": "leaderboard"
}

 

We want to edit that configuration to only contain the filter, dimension, and measures objects.  While the above example doesn't have any fingerprint or id values, we would want to delete those as well.  What we're left with is the following:

{
"filter": {
"activityIds": {
"ids": [
"http://video.portal.example.com/search"
]
},
"personIds": null,
"groupIds": null,
"dateFilter": {
"dateType": "none",
"trailingAmount": 1,
"trailingType": "days",
"olderThanAmount": 0,
"olderThanType": "none",
"fieldName": "timestamp"
},
"includeRelatedActivities": false,
"verbIds": {
"ids": [
"http://activitystrea.ms/schema/1.0/search"
]
},
"activityTypes": null
},
"dimensions": [{
"type": "STATEMENT_PROPERTY",
"statementProperty": "result.response",
"caseSensitive": true
}],
"measures": [{
"name": "Count",
"aggregation": {
"type": "COUNT"
},
"valueProducer": {
"type": "STATEMENT_PROPERTY",
"statementProperty": "object.id",
"caseSensitive": true
}
},
{
"name": "People",
"aggregation": {
"type": "DISTINCT_COUNT"
},
"valueProducer": {
"type": "STATEMENT_PROPERTY",
"statementProperty": "actors.person.id",
"caseSensitive": true
}
}
]
}

 

Using Python 3 we can formulate our API Request:

import requests

# Assign the config to a variable
config = '''
{
"filter": {
"activityIds": {
"ids": [
"http://video.portal.example.com/search"
]
},
"personIds": null,
"groupIds": null,
"dateFilter": {
"dateType": "none",
"trailingAmount": 1,
"trailingType": "days",
"olderThanAmount": 0,
"olderThanType": "none",
"fieldName": "timestamp"
},
"includeRelatedActivities": false,
"verbIds": {
"ids": [
"http://activitystrea.ms/schema/1.0/search"
]
},
"activityTypes": null
},
"dimensions": [{
"type": "STATEMENT_PROPERTY",
"statementProperty": "result.response",
"caseSensitive": true
}],
"measures": [{
"name": "Count",
"aggregation": {
"type": "COUNT"
},
"valueProducer": {
"type": "STATEMENT_PROPERTY",
"statementProperty": "object.id",
"caseSensitive": true
}
},
{
"name": "People",
"aggregation": {
"type": "DISTINCT_COUNT"
},
"valueProducer": {
"type": "STATEMENT_PROPERTY",
"statementProperty": "actors.person.id",
"caseSensitive": true
}
}
]
}
'''

key = "your_watershed_key"
secret = "your_watershed_secret"

url = "https://sandbox.watershedlrs.com/api/organizations/3093/aggregation/csv?"
r = requests.get(url, auth=(key, secret), params=f"config={config}")

# The result of r.text will look like the following:
print(r.text)
Dimension 1,Count,People
customer service,24616,120
leadership,20749,120
process,17186,120
delight,17097,120
relocation,16957,120
intranet forum,16906,120
operations,16895,120
ethics,16854,120
what is otd,13126,120
standard contract,12996,120
production,12949,120

POST method

In addition to the GET method outlined above, it is also possible to interact with this resource using the POST method. In this case the config is passed in the body of the request instead of as a query string parameter.

Both methods still require the name parameter and the response is the same for both methods.

 

Please note: you will need to ensure that each measure includes the full configuration for that measure, not just the measure name and id. Saving and re-editing the report normally causes the full measure configuration to be pulled in to the report configuration.

Was this article helpful?
1 out of 2 found this helpful

If you can't find what you need or you want to ask a real person a question, please contact customer support.