NAV
cURL JavaScript

Provisioning API

Resource types provide a link to set of tasks that can run on the group of resources. It can also be used to define a metrics interface (which is linked to the sensory information) and a command interface which allows you to abstract actual actuators implementation (see later). With most of the IoT platforms, you would find a ResourceType called a “template”, since they refer to this sort of modelling as a way to model different device categories using the same JSON template. In our case, we use a template in the rules context. More importantly, our abstraction allows to model both “object templating” together with rules associations, as described further.

The provisioning API allows you to associate metadata with a resource. Resources are either discovered by Waylay (as soon as data is pushed towards Waylay Broker), or you can create them using REST call.

Next to the resource CRUD related calls, Waylay allows you to Type entities, and let you link resource to a type using metadata (please see example below). As soon as a resource is linked to a resource type, all metadata values of that type are inherited by that resource. Resource can still overwrite any specific attribute in its metadata model.

Waylay also allows you to associate a resource to a parent resource (by setting the parentId). Using this feature, you can organise your resources in a hierarchical structure. Currently, Waylay does NOT check for cyclic references. Also parentId can NOT be inherited from the linked resource type.

Let’s see how api works in practice:

Resources

Create resource

In this example, we create a resource mydevice_id and add two additional attributes: customer and label:

curl --user apiKey:apiSecret \
 -X POST "https://tenant.waylay.io/api/resources" \
 -H "Content-Type: application/json" \
 -d '{
       "id": "mydevice_id", 
       "customer": "tenant1", 
       "label": "helloWorld"
    }'

Example of creating a resource and immediately linking it to the resource type:

curl --user apiKey:apiSecret \
 -X POST "https://tenant.waylay.io/api/resources" \
 -H "Content-Type: application/json" \
 -d '{
       "id": "myDevice_id",
       "resourceTypeId": "resourceType_Id",
       "customer": "tenant1",
       "name": "helloWorld"
     }'

Reserved keywords for metadata:

Symbol Type Meaning
resourceTypeId optional[String] id of the linked resource type
parentId optional[String] id of the parent resource
name optional[String] name of the resource, like testresource
alias optional[String] alias for the name of the resource, like testresource-alias
owner optional[String] owner of the resource
provider optional[String] LoRA, Sigfox..
providerId optional[String] provder_123
customer optional[String] customer tenant name
tags optional[List[String]] (sequence of strings) // example [“Proximus”, “myTag”, “locationC”]
location optional [Location type] see below
firmware optional[String] 1.2_1234
lastMessageTimestamp optional[Integer] (epoch time of the last contact)
metrics optional[list[ResourceMetric]] see below
commands optional[Commands] see Commands
sensors optional[Sensors] see Sensors

Example of creating a resource with location:

curl --user apiKey:apiSecret \       
 -X POST "https://tenant.waylay.io/api/resources" \
 -H "Content-Type: application/json" \
 -d '{
       "id": "mydevice_id4",
       "customer": "tenant1",
       "label": "helloWorld",
       "location" : {
         "lat" : 51,
         "lon": 3.71
       }
    }'

Reserved keywords for Location type

Symbol Type
lat Double
lon Double

Reserved keywords for ResourceMetric

Symbol Type Example
name String Temperature
valueType String integer, double, boolean, string, enum
valueChoices optional[list[String]] [“OK”, “NOK”]
metricType String count / gauge / counter / timestamp (for events) default gauge
unit optional[String] SI units or non-SI units like Fahrenheit…
maximum optional[Double] 0
minimum optional[Double] 60

Example of creating a resource with a metric in the request:

curl --user apiKey:apiSecret \
 -X POST "https://tenant.waylay.io/api/resources" \
 -H "Content-Type: application/json" \ 
 -d '{
       "id":"mydevice_id3",
       "customer":"tenant1",
       "label":"helloWorld",
       "metrics" : [
         {
           "name" : "Temperature",
           "unit":"C",
           "valueType": "double",
           "metricType": "counter" 
         }
       ]
     }' 

Reserved keywords for Metric type:

Symbol Meaning
rate a number per second (implies that unit ends on ‘/s’)
count a number per a given interval (such as a statsd flushInterval)
gauge values at each point in time
counter keeps increasing over time (but might wrap/reset at some point) i.e. a gauge with the added notion of “i usually want to derive this to see the rate”
timestamp value represents a unix timestamp. so `sically a gauge or counter but we know we can also render the “age” at each point.

More about metric types you can find here metric20org

Commands for resource

Commands feature allows you to specify generic set of actuators for a resource, which at runtime get resolved to a specific actuator.

‘Create a resource with a SayHi command’

curl --user apiKey:apiSecret \       
 -X POST "https://tenant.waylay.io/api/resources" \
 -H "Content-Type: application/json" \
 -d '{
       "id" : "my_friendly_device",
       "greeter" : "Friendly device",
       "commands" : [{
          "SayHi" : {
            "actuator" : {
               "name": "debugDialog",
               "version": "latest",
               "properties" : {
                 "message": "Hello, says the {{greeter}} !"
               }
            }
          }
       }]
  }' 

The commands property must be an array of objects. Each object must have one property which is the name of the command. The value must be an actuator definition with following properties:

Property Value
name Name of an actuator
version Exact version of the actuator or latest
properties Json object with default values for the properties of the actuator

When a command is sent to the broker for the resource and with name SayHi, the engine will check the commands property of the resource’s metadata and see if there is a command SayHi mapped to an actuator. If there is such a property and the mapped actuator could be found, the properties for the actuator are merged with the actual message sent to broker and the actuator is executed for the resource and the merged properties.

It is possible, in the properties of the actuator, to reference the metadata properties of the resource. They will be resolved to the actual value of the property at the moment of command execution. You can reference a metadata property by enclosing its name with {{ and }}. This is especially useful if you define commands at the resource type level, but need resource specific values.

‘Send a SayHi command for resource testresource’

curl --user apiKey:apiSecret \  
 -X POST "https://data.waylay.io/resources/testresource/commands" \  
 -H "Content-Type: application/json" 
 -d '{
    "name": "SayHi",
    "message": "Hello from this friendly resource"
  }' 

An interesting thing to note is that commands are sent over the broker and they are queued by the broker. That means that you can easily fan out all actuations this way, in case you need to send a lot of actuations in a short period of time, without worrying whether sandbox can follow sudden high loads. Broker will make sure that they are all delivered with fastest pace, while at the same time, making sure they all have a chance to get executed by the sandbox.

Sensors for resource

You can also specify set of sensors that are applicable for a given resource. Please note that there is no explicit action taken by the Waylay platform on this meta key, unlike for commands, where the Waylay platform resolves a particular actuator for a given command call. Idea behind this abstraction is to assist integrations where an architect of the digital twin can specify which sensors from waylay library are applicable for a given resource (or resource type). For instance, you may have one sensor per metric, or multiple sensors for a given metric, or one sensor that is using multiple metrics. When calling a REST interface for meta, UI can be dynamically built based on set of capabilities for a resource both for actuations (using commands) and also associate set of sensors, next to supported metrics.

Create a resource with events sensor (which represents GoogleCalendar sensor)

curl --user apiKey:apiSecret \
 -X POST "https://tenant.waylay.io/api/resources" \ 
 -H "Content-Type: application/json" 
 -d '{
    "id" : "my_friendly_device",
    "sensors" : [
      {
        "name": "events",
        "sensor": {
          "name": "GoogleCalendarStreamSensor",
          "version": "0.1.5"
        }
      }
    ]
  }' 

The sensors property must be an array of objects. Each object must have a name property that describes the sensor along with a sensor property which is an object containing following properties:

Property Value
name Name of a sensor
version Exact version of the sensor or latest
properties Json object with default values for the properties of the sensor

Sensor properties in meta

[
  {
    "name": "<custom-name-for-sensor>",
    "sensor": {
      "name": "<sensor-name>",
      "version": "<sensor-version>",
      "properties": {
        "<some-sensor-property>": "<property-value>",
        "<another-sensor-property>": "<property-value>"
      }
    }
  }
]

Building resource referencing a Weather Station resource

{
  "id": "e0d7b1cd-5bb7-4dfd-aa63-5ab1a5d5e3fa",
  "name": "Waylay Offices",
  "address": "Blekersdijk 33a",
  "city": "Ghent",
  "weatherStation": {
    "$ref": "/resources/04592b9a-e0c2-4e64-8c9a-202e50cd9275",
    "name": "Gents weer" 
  }
}

Resource references

The Waylay Engine will also recognise metadata keys which are json objects with a $ref keyword as references to other resource if the value for the $ref is a URI that starts with /resources/.

When you reference these keys, using the META.$.<key> syntax, in the resource field of sensor nodes in a task definition, the Waylay Engine will “resolve” these at the start of the task and include the referenced resource as one of the task resources.

Update resource

curl --user apiKey:apiSecret \  
 -X PUT "https://tenant.waylay.io/api/resources/myDevice_id" \
 -H "Content-Type: application/json" \
 -d '{
       "resourceTypeId": "resourceType_Id", 
       "customer":"tenant1", 
       "name": "helloWorld"
     }'

In order to update a resource, you need to put your resourceId in the path.

Partial resource update

curl --user apiKey:apiSecret \
 -X PATCH "https://tenant.waylay.io/api/resources/myDevice_id" \
 -H "Content-Type: application/json" \ 
 -d '{ 
        "resourceTypeId":"resourceType_Id"
      }'

Partial updates allow you to add/modify individual fields on a resource.

curl --user apiKey:apiSecret \
 -X PATCH "https://tenant.waylay.io/api/resources/myDevice_id" \
 -H "Content-Type: application/json" \
 -d '{
       "customer": null 
     }'

If you want to remove a field from a resource, you can do so by setting the field to null in the payload of the PATCH call

Delete resource

curl --user apiKey:apiSecret \
 -X DELETE "https://tenant.waylay.io/api/resources/mydevice_id"

In order to delete a resource, you need to put your resource Id in the path

Retrieve resource

curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resources/[resourceId]"

This would return something like

{
  "id": "testresource",
  "resourceTypeId": "SampleResourceType",
  "metrics":[{
    "name": "Temperature",
    "valueType": "double",
    "metricType": "counter",
    "unit": "C"
  }],
  "customField": "value"
}

In order to get a resource, you need to put your resourceId in the path

This will give you a denormalized view of a resource where properties that are inherited from the resourceType are merged with the properties specified at resource level.

HAL representation

curl -i --user apiKey:apiSecret -H "Accept: application/hal+json" \
  "https://tenant.waylay.io/api/resources/[resourceId]"

This would return something like

{
  "id": "Ground floor",
  "name": "Ground floor",
  "#desks": 0,
  "_links": {
    "self": {
      "href": "/api/resources/Ground%20floor"
    },
    "children": {
      "href": "/api/resources/Ground%20floor/children"
    },
    "parent": {
      "href": "/api/resources/Office",
      "id": "Office"
    },
    "resourceType": {
      "href": "/api/resourcetypes/4539e0c2-578e-4470-8f14-2ed81d576e3a",
      "id": "4539e0c2-578e-4470-8f14-2ed81d576e3a"
    }
  }
}

To retrieve a more “enriched” representation of the resource, specify the Accept header as application/hal+json

The _links property provides hyperlinks to api endpoints to retrieve more information about the resource. Following are provided:

Retrieve normalized resource

curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resources/[resourceId]?denormalized=false"

This would return something like

{
  "id": "testresource",
  "resourceTypeId": "SampleResourceType"
}

In order to get the normalized view of a resource, i.e. get only the properties that are specified on the resource level and not the ones inherited from the resource type level, set the query parameter denormalized to false.

This endpoint also supports the HAL resource representation by specifying the Accept: application/hal+json request header.

Query resources

Filtered resource list request

curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resources?filter=car"

Paging is handled by skip and limit parameters. If you have a large volume of resources, you can iterate of them like this:

curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resources?limit=1&skip=0"
curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resources?limit=1&skip=1"
curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resources?limit=1&skip=2
  etc

Resources can be queried by doing a GET request, if needed you can filter on these fields using the query string:

This endpoint also supports the HAL resource representation by specifying the Accept: application/hal+json request header. Resources will be returned in HAL format in the _embedded.values member. The result will next to the paging information (count, total, limit and skip) and the _embedded member, also contain a _links member that contains the links to

Geo distance query

Find all resources within 10km from point (51.05,3.73)

curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resources?lat=51.05&lon=3.73&distance=10km"

If your resources have coordinates specified in the location property (see Create resource), you find all resources within a specified distance from a point (specified by a lat and lon). See Distance units for the specification of distance.

Retrieve resource change log

curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resources/[resourceId]/changes"

This returns the history of changes to a resource sorted by change time descending. By default only the 10 most recent changes are returned.

If you want more changes, specify using the limit query parameter. If you want to skip some changes, use the skip query parameter.

If you want to history to be returned as a paged list (so with values, total, limit and skip), set the Accept header to application/vnd.waylay.paged+json.

Retrieve resource’s children

curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resources/[resourceId]/children"

Retrieves the child resources of the specified resource, i.e. all resources that have the specified resource as (direct) parent.

Page with skip and limit query parameters. Use ?denormalized=false to retrieve the normalized representation of the children.

This endpoint also supports the HAL resource representation by specifying the Accept: application/hal+json request header.

Retrieve resource command log

curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resources/[resourceId]/commands"

will return something like

{
  "values": [
    {
      "name": "Say hi",
      "executionTime": "2018-09-24T13:59:10.377Z",
      "actuator": "debugDialog:LATEST",
      "result": {
          "success": true,
          "message": "Hi from resourcetype",
          "rawData": {}
      }
    },
    {
      "name": "Say his",
      "executionTime": "2018-09-24T13:58:56.075Z",
      "errorMessage": "Command 'Say his' not found"
    },
    {
      "name": "Say hi",
      "executionTime": "2018-09-24T10:47:59.739Z",
      "actuator": "debugDialog:LATEST",
      "result": {
          "success": true,
          "message": "resource brunocommand says hi",
          "rawData": {}
      }
    },
    ...
  ],
  "skip": 0,
  "limit": 10,
  "total": 16
}

This returns a paged list with the command executions. Page with skip and limit query parameters.

Resource types

Create resource type

In this example, we create a resource type and at the same time, we define metric types:

curl -i --user apiKey:apiSecret \
 -X POST "https://tenant.waylay.io/api/resourcetypes" \
 -H "Content-Type: application/json" \
 -d '{ 
        "id":"resourceType_Id", 
        "customField":"value", 
        "metrics" : [
          { 
            "name":"Temperature", 
            "unit": "C", 
            "valueType": "double", 
            "metricType": "counter" 
          }
        ]
    }'

Reserved keywords for resource type:

Symbol Type Example
id String D12345 or UUID
name optional[String] device_123
provider optional[String] Proximus
providerId optional[String] 123
customer optional[String] customer1
metrics optional[List[ResourceMetric]] list of metrics
commands optional[Command] Definition of commands
templates optional[List[templates]] Automatically create tasks by associating a template with a resource type
$constraints optional[List[constraints]] Applying resource constraint to resource type
$bulkOperation optional[String] Will be ignored when reading input, but will be returned to indicate a asynchronous operation is busy for the resource type

Update resource type

In order to update a resource type, you need to put your resource type Id in the path

curl -i --user apiKey:apiSecret \
 -X PUT "https://tenant.waylay.io/api/resourcetypes/resourceType_Id" \
 -H "Content-Type: application/json" \
 -d '{
        "resourceTypeId": "resourceType_Id", 
        "customer":"tenant1", 
        "name": "myResourceType"
    }'

Partial resource type update

curl -i --user apiKey:apiSecret \
 -X PATCH "https://tenant.waylay.io/api/resourcetypes/resourceType_Id" \
 -H "Content-Type: application/json" \
 -d '{
        "customer":"tenant2",
        "customField":"value"
    }'

Partial updates allow you to add/modify individual fields on a resource type.

curl --user apiKey:apiSecret \
 -X PATCH "https://tenant.waylay.io/api/resourcetypes/resourceType_Id" \
 -H "Content-Type: application/json" \
 -d '{
       "customer": null 
     }'

If you want to remove a field from a resource type, you can do so by setting the field to null in the payload of the PATCH call

Delete resource type

curl -i --user apiKey:apiSecret \
 -X DELETE "https://tenant.waylay.io/api/resourcetypes/resourceType_Id"

Retrieve resource type

curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resourcetypes/[resourceType_Id]"

In order to get a resource type, you need to put your resource type Id in the path

Query resource types

Paging is handled by skip and limit parameters

curl -i --user apiKey:apiSecret \
  "https://tenant.waylay.io/api/resourcetypes?filter=car"

Resources can be queried by doing a GET request, if needed you can filter on these fields using the query string:

Retrieve resource type change log

curl -i --user apiKey:apiSecret \
 "https://tenant.waylay.io/api/resourcetypes/[resourceType_Id]/changes"

This returns the history of changes to a resource type sorted by change time descending. By default only the last 10 most recent changes are returned.

If you want more changes, specify using the limit query parameter. If you want to skip some changes, use the skip query parameter

If you want to history to be returned as a paged list (so with values, total, limit and skip), set the Accept header to application/vnd.waylay.paged+json.

Automatically create tasks by associating a template with a resource type

The waylay task engine can automatically provision tasks for each new resource. This is configured in the metadata of the resource type. All you need to add is a field templates that contains what templates should be used and what task configuration should be applied to these managed tasks.

Resource type definition:

{
    "id": "4b80d00a-89f0-41a0-b6e5-d4423caca844",
     ...
     "templates": [
        {
            "templateName": "templatex",
            "type": "periodic",
            "frequency": 60000
        },
        {
            "templateName": "templatey",
            "type": "scheduled",
            "cron": "0 0 12 * * ?"
        }
     ]
}

If for example an existing resource’s type is set to the above type then 2 tasks will be created.

In general these managed tasks are created/removed for these actions:

Resource constraints

Add resource constraint

curl -i --user apiKey:apiSecret -X POST \
 "https://tenant.waylay.io/api/resourceconstraints" \
 -H "Content-Type: application/json" \
 -d '{ 
        "name": "Mandatory customer",
        "description" : "This constraints makes the customer attribute mandatory",
        "attributes" : [
          { 
            "name":"customer", 
            "required": true, 
            "type": {
                "type" : "string"
                "minLength" : 1
            }
          }
        ]
    }'

A resource constraint has, next to a name and a description, an array of attributes description. Each of these attributes description has the following properties:

When a resource constraint is created, it is validated that the attributes do not redefined the resource reserved keywords in an incompatible way (e.g. defining provider as a number). It is possible however to make the definition more strict, e.g. by making an attribute required or e.g. by defining that customer should have a minLength of 5.

The result of a successful POST call will contain a uri with the uri of the just created resource constraint and an entity field which contains the resource constraint including the (generated) id for the constraint.

Following attribute type are supported:

Numeric attribute

String attribute

Boolean attribute

Enum attribute

curl -i --user apiKey:apiSecret -X POST \
 "https://tenant.waylay.io/api/resourceconstraints" \
 -H "Content-Type: application/json" \
 -d '{ 
        "name": "Technology choice",
        "description" : "This constraints defines a technology attribute with predefined possible values", 
        "attributes" : [
          { 
            "name":"technology", 
            "required": false, 
            "type": {
                "type" : "enum",
                "enumType" : "string",
                "items" : [ "LORA", "SIGFOX", "2G", "3G"]
            }
          }
        ]
    }'
curl -i --user apiKey:apiSecret -X POST \
 "https://tenant.waylay.io/api/resourceconstraints" \
 -H "Content-Type: application/json" \
 -d '{ 
        "name": "Weather Station choice",
        "description" : "This constraints defines weatherStation attribute" 
        "attributes" : [
          { 
            "name":"weatherStation", 
            "required": true, 
            "type": {
                "type" : "resourceRef",
                "resourceTypes" : [ "weatherStation" ],
                "exists" : true
            }
          }
        ]
    }'

ResourceRef attribute

curl -i --user apiKey:apiSecret -X POST \
 "https://tenant.waylay.io/api/resourceconstraints" \
 -H "Content-Type: application/json" \
 -d '{ 
        "name": "Address field",
        "description" : "address attribute with subfields",
        "attributes" : [
          { 
            "name":"address", 
            "required": true, 
            "type": {
                "type": "object",
                "attributes": [
                    {
                        "name": "street",
                        "required" : true,
                        "type" : {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 255
                        }
                    },
                    {
                        "name": "postal",
                        "required" : true,
                        "type" : {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 10
                        }
                    },
                    {
                        "name": "city",
                        "required" : true,
                        "type" : {
                            "type": "string",
                            "minLength": 1
                        }
                    }
                ] 
            }
          }
        ]
    }'

Object attribute

curl -i --user apiKey:apiSecret -X POST \
 "https://tenant.waylay.io/api/resourceconstraints" \
 -H "Content-Type: application/json" \
 -d '{ 
        "name": "tags field definition",
        "description" : "tags attribute expressed as a constraint", 
        "attributes" : [
          { 
            "name":"tags", 
            "required": false, 
            "type": {
                "type": "array",
                "elementType" : {
                    "type" : "string",
                    "minLength": 1
                },
                "minLength": 1,
                "uniqueValues": true
            }
          }
        ]
    }'

Array attribute

Update resource constraint

Adding a possible value to technology constraint

curl -i --user apiKey:apiSecret -X PUT \
 "https://tenant.waylay.io/api/resourceconstraints/b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909" \
 -H "Content-Type: application/json" \
 -d '{ 
        "id" : "b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909",
        "name": "Technology choice",
        "description" : "This constraints defines a technology attribute with predefined possible values", 
        "attributes" : [
          { 
            "name":"technology", 
            "required": false, 
            "type": {
                "type" : "enum",
                "enumType" : "string",
                "items" : [ "LORA", "SIGFOX", "2G", "3G", "BLE" ]
            }
          }
        ]
    }'

You can update an existing resource constraint by PUT the complete, updated resource constraint.

When updating a resource constraint, next to the compatibility check with the default reserved keywords definition, it is also checked that the resource constraint is not used by a resource type for which there are already resources.

Delete resource constraint

curl -i --user apiKey:apiSecret -X DELETE\
 "https://tenant.waylay.io/api/resourceconstraints/b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909"

You can delete a resource constraint that is not assigned to any resource type.

Get resource constraint

You can retrieve a resource constraint by the id.

curl -i --user apiKey:apiSecret -X GET \
 "https://tenant.waylay.io/api/resourceconstraints/b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909" 

returns

{ 
    "id" : "b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909",
    "name": "Technology choice",
    "description" : "This constraints defines a technology attribute with predefined possible values" ,
    "attributes" : [
      { 
        "name":"technology", 
        "required": false, 
        "type": {
            "type" : "enum",
            "enumType" : "string",
            "items" : [ "LORA", "SIGFOX", "2G", "3G", "BLE" ]
        }
      }
    ]
}

You can also retrieve the resource constraint as a json schema by setting the Accept header of the GET request to application/schema+json

Requesting as Json schema

curl -i --user apiKey:apiSecret -X GET \
 "https://tenant.waylay.io/api/resourceconstraints/b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909" \
 -H "Accept: application/schema+json"

returns

{
    "type": "object",
    "properties": {
        "technology": {
            "type": "string",
            "enum": [
                "2G",
                "3G",
                "LORA",
                "SIGFOX",
                "BLE"
            ]
        }
    },
    "required": []
}

List all resource constraints

curl -i --user apiKey:apiSecret -X GET \
 "https://tenant.waylay.io/api/resourceconstraints?skip=0&limit=5

You can retrieve the list of defined resource constraints.

Pagination can be done with the query parameters skip and limit.

Applying resource constraint to resource type

curl -i --user apiKey:apiSecret -X PATCH \
 "https://tenant.waylay.io/api/resourcetypes/resourceType_Id" \
 -H "Content-Type: application/json" \
 -d '{
        "$constraints": [ 
            "b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909",
            "a826cbee-6871-415e-911d-1c87d2c77aef"
        ]   
    }'

Multiple resource constraints can be applied to a resource type. You can do that by specifying the $constraints key as an array of resource constraint ids in the body of an update or partial update request on a resource type.

The system will check if the constraints that are applied are compatible with each other, e.g. that they do not define the same attribute with conflicting types. It is however possible that a constraint makes a definition more strict. The most strict definition will then be applied, e.g. one constraint defines the customer attribute to be mandatory, another constraint defines the customer attribute to be optional (required=false), but specifies a minLength of 5. When both are applied to a resource type, any resource of that type will need to have a customer attribute (so mandatory) and the value for it has to be at least 5 characters.

Result of the above call

{
    "id": "resourceType_Id",
    "name": "Example resourceType",
    "$constraints": [
        {
            "status": "applying",
            "constraintId": "b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909"
        },
        {
            "status": "applying",
            "constraintId": "a826cbee-6871-415e-911d-1c87d2c77aef"
        }
    ],
    "$bulkOperation": "32657dc2-71e0-46b7-a4f1-11deee5111dd"
}

In the result of that call, the $constraints will be an array of object with key status: applying next to the constraintId. There will also be a $bulkOperation key in the result indicating that an asynchronous operation is busy. In that asynchronous operation, the resource constrains are validated on all resources of that resource type.

When the asynchronous operation has finished, the result of a retrieve request will not contain $bulkOperation anymore and the status for each of the $constraints will either be

Some resources do not fulfill all constraints

{
    "id": "resourceType_Id",
    "name": "Example resourceType",
    "$constraints": [
        {
            "status": "ineffect",
            "constraintId": "b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909"
        },
        {
            "status": "failed",
            "errors": [
                {
                    "error": "Property address missing.",
                    "errorPath": "/address",
                    "resources": [
                        "714bbf92-5dfc-4c42-9623-1c6e72708126",
                        "c2ff6672-bee7-4849-9280-daac910eb348",
                        "9c8dd188-201e-458a-b1ce-4264d862bb61"
                    ]
                }
            ],
            "constraintId": "a826cbee-6871-415e-911d-1c87d2c77aef"
        }
    ]
}

When some resources do not fulfil the constraints, the errors will contain per unique error, next to the indication of which attribute, the list of resourceIds of the failing resources (for that error).

Retrieve constraints for a resource type

curl --user apiKey:apiSecret -X GET \
 "https://tenant.waylay.io/api/resourcetypes/resourceType_Id/constraints"

Above would return:

{
    "id": "merged",
    "name": "Constraints for resourceType 'resourceType_id'",
    "attributes": [
        { "name": "name", ... },
        { "name": "tags", ... },
        { "name": "firmware", ... },
        {
            "name": "technology",
            "required": false,
            "type": {
                "type": "enum",
                "enumType": "string",
                "items": [
                    "LORA",
                    "SIGFOX",
                    "2G",
                    "3G",
                    "BLE"
                ]
            }
        },
        { "name": "alias", ... },
        { "name": "customer", ... },
        {
            "name": "address",
            "required": true,
            "type": {
                "type": "object",
                "attributes": [
                    ...
                ]
            }
        },
        { "name": "metrics", ... },
        { "name": "resourceTypeId",... },
        { "name": "location", ... },
        { "name": "provider", ... },
        { "name": "lastMessageTimestamp", ... },
        { "name": "providerId", ... },
        { "name": "id", ... },
        { "name": "sensors", ... },
        { "name": "owner", ... },
        { "name": "parentId", ... },
        { "name": "commands", ... }
    ]
}

You can retrieve the merged constraints that are applicable for a certain resource type. This will give the reserved keywords for metadata expressed as resource constraint merged with all user defined resource constraints applied on the resource type.

curl --user apiKey:apiSecret -X GET \
 "https://tenant.waylay.io/api/resourcetypes/resourceType_Id/constraints" \
 -H "Accept: application/schema+json" 

You can also retrieve the merged constraint as json schema by setting the Accept header as application/schema+json

Revalidate the constraints for a resource type

curl --user apiKey:apiSecret -X POST \
 "https://tenant.waylay.io/api/resourcetypes/resourceType_Id/revalidate"

You can request to revalidate all resources of a resource type

Failed resource constraint validation on resource

{
    "statusCode": 400,
    "error": "/address <- Property address missing.",
    "details": [
        {
            "schemaPath": "#",
            "errors": {},
            "keyword": "required",
            "msgs": [
                "Property address missing."
            ],
            "value": {
                "id": "714bbf92-5dfc-4c42-9623-1c6e72708126",
                "resourceTypeId": "bruno",
                "name": "bruno",
                "customer": "bruno_customer",
                "array": [
                    {
                        "coucou": true,
                        "customer": "bravo"
                    },
                    {
                        "coucou": false
                    }
                ]
            },
            "instancePath": "/address"
        }
    ]
}

Resource constraints will be validated for any operation (create/update/delete) on a resource. If any constraint would not be fulfilled, the operation will return a failure result (http status code 400). details will contain detailed information for each constraint that was violated.

Bulk interface

Bulk delete of resources/resource types

Delete resources myDevice_id, mydevice_id3 and myWrongDevice in bulk

curl --user apiKey:apiSecret \
 -X POST "https://tenant.waylay.io/api/batch" \
 -H "Content-Type:application/json" \
 -d '{ 
       "entity": "resource",
       "action": "delete",
       "query" : {
         "ids" : ["myDevice_id", "mydevice_id3", "myWrongDevice"]
       } 
     }'

Using the batch endpoint it is also possible to delete multiple resources or resource types in one api call.

To do this, you can POST a batch operation with delete action and
resource or resourcetype as entity to the /api/batch/ endpoint.

You need to specify the ids of the resources or resource types in the query key of the bulk operation.