NAV Navigation

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-07-26T08:15:50.935Z",
"updatedTime": "2024-07-26T08:15:50.935Z",
"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:

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-07-26T08:15:50.935Z",
"updatedTime": "2024-07-26T08:15:50.935Z",
"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:

Commissioning is split into two parts:

  1. Check if the devices are in working order: prepare
  2. 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