Introduction
Welcome to the Cumulus API reference documentation. This documentation will guide you through all the API endpoints. The main purpose of the Cumulus API is to serve asset information. Secondly, it can serve additional context information like geographical data. The API is flexible to use and can be highly customized regarding user access.
Transport
All endpoints use HTTPS with https://cumulus.undagrid.com/v1/
as the BaseAddress
. You can use traditional HTTP 1.1, but also H2 or Spdy are supported. Usage of compression is highly recommended.
All endpoints produce and consume JSON unless otherwise stated.
Rate limiting
Several rate limiting headers are present to show clients when they reach API limits:
Header | Description |
---|---|
x-ratelimit-period | The window in seconds within which the rate limiting is applied |
x-ratelimit-limit | The total amount of calls available within the window |
x-ratelimit-remaining | The amount of calls still available within the window |
x-ratelimit-tokenconcurrentlimit | The amount of concurrent calls one can do with a single authentication token |
In case of non-adherence to these limits, a HTTP 429 is issued.
Also, the amount of errors is tracked. If a client makes too many errors, it may be barred from communicating to the API.
Concepts
The basic concept of the Cumulus API translates very well to database tables in a conventional database. Every group of endpoints gives access to the equivalent of a database table. From this table you can read, query, insert and delete. These tables are called Objects
in Cumulus. Most major operations can be executed on all Objects
with only a few minor exceptions.
These objects are grouped by ObjectType
. Some of these are native to Cumulus and have additional functionality, others can be created and used more freely as additional database objects.
Multi-tenancy
for example:
https://cumulus.undagrid.com/v1/customerx/assets
To separate customers and their data, every customer has its own set of endpoints marked by the customers TenantName. This makes the endpoint URL always something along the lines of:
{BaseAddress}{TenantName}/{ObjectType}
Authentication
A simple way to get a token is this:
curl https://undagrid.eu.auth0.com/oauth/token
-X POST
-d '{\
"realm":"{Realm}",\
"audience":"https://cumulus.undagrid.com",\
"client_id":"{ClientId}",\
"grant_type":"http://auth0.com/oauth/grant-type/password-realm",\
"username":"{Username}",\
"password":"{Password}"\
}'
Access to the API is granted via JWT bearer token on the Authorization
HTTP header. Since Undagrid uses an external authentication provider, you’ll need to access it to get the token. Depending on the platform you are working on, there are various options to get a token. Please have a look at the auth0 documentation for more details.
Authorization
Once you have a token, it can be used to access the endpoints. Depending on the users authorization access to the specific endpoints is granted. Basic access policies cover the following paradigms:
Action | Description |
---|---|
CREATE |
Able to create an object |
UPDATE |
Able to update the mutable object data |
READ |
Able to read the object data |
DELETE |
Able to delete an object |
Some ObjectTypes
have additional paradigms, which will be described when relevant.
If access is not allowed Cumulus will report a HTTP 403 error.
Objects
The basic structure of all of these Objects is the same and can be found in the Base Object layout as described below.
Example JSON structure:
{
"id": "foobar",
"name": "foobar",
"mutable": {
"customProperties": {},
"type": "foobar"
},
"metadata": {
"createdBy": "foobar",
"updatedBy": "foobar",
"createdTime": "2024-09-20T10:01:17.904Z",
"updatedTime": "2024-09-20T10:01:17.904Z",
"tenant": "foobar"
}
}
Base object
https://cumulus.undagrid.com/schema/baseobject.schema.json
Basic Cumulus object definition
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
id | string |
yes | The unique id of the object, server generated | |
name | string |
yes | The unique name of the object | |
mutable | object |
yes | An object containing data that can be mutated from the public API See Base object : mutable |
|
metadata | object |
yes | The metadata object contains information about when the object was created and changed See Base object : metadata |
Base object : mutable
An object containing data that can be mutated from the public API
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
customProperties | object |
no | An object containing data that is application specific | |
type | enumerated string |
no | The type of the object | possible values: asset , gateway , anchor |
Base object : metadata
The metadata object contains information about when the object was created and changed
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
createdBy | string |
yes | The user that created the object | |
updatedBy | string |
yes | The user that last updated the object | |
createdTime | string |
yes | ISO time of when the object was created | ISO formated date |
updatedTime | string |
yes | ISO time of when the object was last updated | ISO formated date |
tenant | string |
no | The tenant this object belongs to |
Note that only the mutable object can contain user data that can be directly manipulated by the Cumulus API. The data in the customProperties
is freely usable by the application, while the mutable part may be dictated for internal functionality.
All of these object have specific endpoints in common which will be described in the following sections
Generic Endpoints
Most ObjectTypes
have a basic set of generic endpoints. These endpoints are described in this section.
Get multiple objects
Retrieve multiple objects at once
Action: READ
HTTP Request
GET {BaseAddress}{TenantName}/{ObjectTypePlural}
Query Parameters
Parameter | Default | Description |
---|---|---|
q |
A query to filter and sort results. see query language | |
p |
An ISO formatted timestamp to indicate from when the full data object should be returned. objects updated before this timestamp will be returned with only the metadata. This can be used to poll the endpoint for changes without the need to transfer the full set of data every time. |
Returns
An array of object data in the form of Base Object matching the optional query.
Get a single object
Retrieves a single object from the system by id or name.
Action: READ
HTTP Request
GET {BaseAddress}{TenantName}/{ObjectType}/{name or id}
Since both name and id are unique, both can be used to identify the object
Query Parameters
none
Returns
The object matching the name or id
Create an object
Action: CREATE
HTTP Request
Body:
{
"mutable": {
"customProperties" : {
"foo": "bar",
"x": 1
}
}
}
PUT {BaseAddress}{TenantName}/{ObjectType}/{name}
So when creating an object you can set the mutable data.
Query Parameters
none
Returns
The object created
Update an object
Action: UPDATE
HTTP Request
Body:
{
"customProperties" : {
"life": 42
}
}
POST {BaseAddress}{TenantName}/{ObjectType}/{name or id}
The POST is a bit different from the PUT. It will only let you update the mutable data and therefore the post body contains the mutable data directly. Note that it merges objects with the data already present. So in order to update only a single property, only that property needs to be delivered.
Query Parameters
none
Returns
The updated object
Delete an object
Deletes an object from the system.
Action: DELETE
HTTP Request
DELETE {BaseAddress}{TenantName}/{ObjectType}/{name or id}
##Query Parameters none
Returns
Example:
{
"status": "OK",
"message": "[foo] deleted from [assets]"
}
An ok message
Object history
Get the history of one or more objects
Action: HISTORY
HTTP Request
History of a single object:
GET {BaseAddress}{TenantName}/{ObjectType}/{name or id}/history
or multiple:
GET {BaseAddress}{TenantName}/{ObjectTypePlural}/history
Query Parameters
Parameter | Default | Description |
---|---|---|
q |
A query to filter and sort results. see query language |
Returns
An array of previous versions of the objects
Object values
This call is an aggregate call that gives you the distinct values of properties and their occurrences. You can also specify multiple properties, in which case, all combinations will be returned.
Action: READ
HTTP Request
GET {BaseAddress}{TenantName}/{ObjectTypePlural}/values/{property}
or for multiple:
GET {BaseAddress}{TenantName}/{ObjectTypePlural}/values/{property}/{property}/...
Example:
mutable.customProperties.group
Where property is the path to the property in dot notation. A list of properties can be given
Query Parameters
Parameter | Default | Description |
---|---|---|
q |
A query to filter and sort results. see query language |
Returns
Example:
{
"property":"mutable.customProperties.group",
"values":[
{"Terminal": 11},
{"Non-motorised": 22},
{"Motorised": 25}
]
}
An object describing the aggregated data
Query Language
Multiple endpoints make use of the q
parameter to specify a query. This query can be used to narrow down the amount of object, or even limit the amount of information in the returned objects. It also provides some sorting features.
For example:
{
"mutable": {
"customProperties" : {
"foo": "bar"
}
}
}
Can be accessed via the following example query:
eq(mutable.customProperties,Bar)
The language uses various operators that can be applied to data in the object. Nested data can be accessed via the dot notation.
The following operations are possible:
Property | Description |
---|---|
sort(<+|->{property}) |
Sorts by the given property in order specified by the prefix (+ for ascending, - for descending) |
select({property},{property},...) |
Trims each object down to the set of properties defined in the arguments |
in({property},{array-of-values}) |
Filters for objects where the specified property’s value is in the provided array |
out({property},{array-of-values}) |
Filters for objects where the specified property’s value is not in the provided array |
contains({property},{value | expr}) |
Filters for objects where the specified property’s value is an array and the array contains any value that equals the provided value or satisfies the provided expression |
excludes({property},{value | expr}) |
Filters for objects where the specified property’s value is an array and the array does not contain any of value that equals the provided value or satisfies the provided expression |
limit({count},{start},{maxCount}) |
Returns the given range of objects from the result set |
and({query},{query},...) |
Applies all the given queries |
or({query},{query},...) |
The union of the given queries |
eq({property},{value}) |
Filters for objects where the specified property’s value is equal to the provided value |
lt(<property>,{value}) |
Filters for objects where the specified property’s value is less than the provided value |
le({property},{value}) |
Filters for objects where the specified property’s value is less than or equal to the provided value |
gt({property},{value}) |
Filters for objects where the specified property’s value is greater than the provided value |
ge({property},{value}) |
Filters for objects where the specified property’s value is greater than or equal to the provided value |
ne({property},{value}) |
Filters for objects where the specified property’s value is not equal to the provided value |
match({property},{value}) |
Filters for objects where the specified property’s value is string matched. This is equivalent to an SQL LIKE |
and(or(eq(foo,3),eq(foo,bar)),lt(price,10))
One can also nest these properties to create complex queries
Objects
Assets
The assets endpoint group is the first of the standard ObjectTypes. An Asset is the digital twin of a thing in the real world. This thing has properties and metadata, but it also has sensors and a location.
Supported generic endpoints:
- Get multiple objects
- Get a single object
- Create an object
- Update an object
- Delete an object
- Object history
- Object values
ObjectType | ObjectTypePlural |
---|---|
asset |
assets |
Sensors
An Asset can contain sensor data. This sensor data comes from Undagrid supported hardware devices. This sensor data can be various things, ranging from temperature or movement to inclination or a battery status. The value of the sensor data is specific to the type of sensor. Please refer to your tenant specific documentation for more detailed more information. To couple the hardware device to the logical asset, a commissioning step is needed. For this a special set of endpoints is available.
Location
As with sensor data, an Undagrid supported hardware device can also deliver a location for the Asset. A location is provided when the location sensor is commissioned to the asset.
Asset schema
Example JSON structure:
{
"id": "foobar",
"name": "foobar",
"mutable": {
"customProperties": {},
"type": "foobar"
},
"metadata": {
"createdBy": "foobar",
"updatedBy": "foobar",
"createdTime": "2024-09-20T10:01:17.904Z",
"updatedTime": "2024-09-20T10:01:17.904Z",
"tenant": "foobar"
},
"sensors": {
"metadata": [
{
"name": "temperature",
"sources": [
{
"nodeName": "UGA18110DA",
"alias": "AD10DA",
"index": 3,
"sensorTypeName": [
"TEMP",
"STATE"
]
}
]
}
],
"latestEvents": [
{
"name": "temperature",
"source": {
"nodeName": "UGA18110DA",
"sensorTypeName": [
"TEMP",
"STATE"
]
},
"valueTime": "2020-10-12T21:01:37.000Z",
"value": 25,
"updateTime": "2020-10-12T21:01:37.000Z"
}
]
},
"location": {
"locationTime": "2021-07-19T11:12:10.000Z",
"updateTime": "2021-07-19T11:12:10.000Z",
"stationary": "boolean",
"valid": true,
"source": "GPS",
"namedLocation": "There",
"potentialField": {},
"accuracy": 5,
"position": {
"type": "Point",
"coordinates": [
6.7965072,
52.2644958
]
},
"correctedPosition": [
5.047657,
52.072569
],
"floor": "F0",
"geoFeatures": [],
"altitude": 24.2
}
}
Asset
https://cumulus.undagrid.com/schema/asset.schema.json
Definition of the Asset object
Asset
extends Base object
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
sensors | no | See sensors | ||
location | no | See location |
Sensors
https://cumulus.undagrid.com/schema/sensors.schema.json
Sensors defines two things: the metadata describing the virtual sensor, and the current values of the configured virtual sensors
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
metadata | array of object |
no | An array of active virtual sensors on the asset with commissioned nodes. It defines the source of the virtual sensor information See Sensors : metadata |
|
latestEvents | array of object |
no | An array of virtual sensor values representing the current state of these sensors See Sensors : latestEvents |
Sensors : metadata
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
name | string |
no | The name of virtual sensor | |
sources | array of object |
no | The sources used for this data. It is possible to have multiple sources for a single virtual sensor See Sensors : metadata : sources |
|
required | no |
Sensors : metadata : sources
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
nodeName | string |
yes | The name of the source node | |
alias | string |
no | The alias of the source node | |
index | integer |
no | The index of the source node, usedfull to indicate order of sensors for certain use cases | |
sensorTypeName | array of string |
yes | The logical sensors needed to feed the virtual sensor. Business logic dictates how the translation takes place |
Sensors : latestEvents
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
name | string |
yes | The name of the virtual sensor | |
source | object |
yes | See Sensors : latestEvents : source | |
valueTime | string |
yes | The moment at which the values was set | ISO formated date |
value | any |
yes | The value of the sensor. Contents is dependant on the type of sensor. This can be a single value, but also a json object | |
updateTime | string |
yes | The moment at which the values was updated | ISO formated date |
Sensors : latestEvents : source
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
nodeName | string |
yes | The name of the source node | |
sensorTypeName | array of string |
yes | The logical source sensors |
Location
https://cumulus.undagrid.com/schema/location.schema.json
Describes the logical location of an asset in various degreed of precision. Note that all fields are optional.
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
locationTime | string |
no | The moment the asset was at this location | |
updateTime | string |
no | The moment the location information was updated | |
stationary | boolean |
no | True if asset is stationary. In that case locationTime points to the moment the asset became stationary |
|
valid | boolean |
no | Show if the system is sure the asset is currently still at the given position. For instance, when moving, it will show invalid because the asset will not be at the shown location anymore. When stationary a location can be invalid when for instance there was not enough information to comprise a new location. In that case the previous location is retained | |
source | string |
no | The source of the location, Could be GPS, Cell, UG or hybrid | |
namedLocation | string |
no | A string that can identify a location | |
potentialField | object |
no | A GeoJSON multi-polygon describing one or multiple areas of where the asset could be | |
accuracy | number |
no | The horizontal accuracy in meters | |
position | object |
no | A GeoJSON point describing a single point location of the asset | |
correctedPosition | array of number |
no | A corrected position based on snapping configuration on one of the matching geos minimum nr of items: 2 maximum nr of items: 2 |
|
floor | string |
no | Floor level inside of a building | |
geoFeatures | array of string |
no | Names of the matched geos for this location | |
altitude | number |
no | height above sea level |
Commissioning
To assign sensors to an asset, you’ll need to commission them. This is a largely automated process that does the following:
- check that the devices are in working order
- setup comminications paths to your account
- assign the correct sensors for the device in you’d like to add
Commissioning is split into two parts:
- Check if the devices are in working order: prepare
- Perform the actual commissioning action: commission
Nr 1. is optional, since 2 will also perform these actions in the background. Yet for convenience this process can be done seperately.
Prepare
POST {BaseAddress}{TenantName}/asset/prepare/{DeviceA}/{DeviceB}/...
An arbitrary list of devices can be given.
Commission
POST {BaseAddress}{TenantName}/asset/{AssetNameOrId}/commission/{DeviceA}/{DeviceB}/...
An arbitrary list of devices can be given. The list of devices will replace all currently commissioned sensors. An empty list will remove all sensors.
In both cases the response is similar:
Example JSON structure:
{
"status": "foobar",
"statusText": "Sensor xyz has fairlure abc",
"devices": [
{
"device": "UG2387123",
"alias": "2387123",
"type": "Undagrid Nestor",
"status": "failed",
"timestamp": "2021-07-19T11:12:10.000Z",
"sensors": [
"ignition",
"movement",
"battery"
],
"data": {
"ignition": true,
"movement": false,
"battery": 0.9
}
}
],
"location": {
"lat": 52.42322123,
"lon": 4.54323,
"timestamp": "2021-07-19T11:12:10.000Z"
}
}
Commission Prepare Result
https://cumulus.undagrid.com/schema/commissionPreparePresult.schema.json
The result of a commissioning prepare or commission call.
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
status | enumerated string |
yes | The status of the commissioning call | possible values: passed , warning , failed |
statusText | array of string |
no | A human readable text describing the status. Generally used to display error messages | |
devices | array of object |
yes | A list of devices commissioned or prepared See Commission Prepare Result : devices |
|
location | object |
no | The last known location of the sensor See Commission Prepare Result : location |
Commission Prepare Result : location
The last known location of the sensor
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
lat | number |
no | Sensor location latitude | |
lon | number |
no | Sensor location longitude | |
timestamp | string |
no | Sensor location timestamp |
Commission Prepare Result : devices
Property | Type | Required | Description | Constraints |
---|---|---|---|---|
device | string |
yes | The primary serial number of the device | |
alias | string |
yes | The alias of the device used in the commissioning or prepare call | |
type | string |
yes | The type of the device | |
status | enumerated string |
yes | The status of the sensor health check | possible values: passed , warning , failed |
timestamp | string |
no | Latest sensor data timestamp of the sensor | |
sensors | array of string |
yes | A human readable text describing the status. Generally used to display error messages | |
data | object |
no | Optional data retrieved from the sensor |