This document proposes the basis of a common model to describe the virtual counterpart of physical objects in the Web of Things. It defines a model and Web API for Things to be followed by anyone wanting to create a product, device, service, or application for the Web of Things. This document considers the definition of the Web of Things (WoT) proposed in [[WoTPaper]] and [[WoTBook]], i.e., the Application layer of the Internet of Things. The model and protocols proposed here aim at making the interaction between Things in the Internet of Things accessible through Web standards to facilitate the implementation of Web applications making use or retrieving data from real-world objects.

This document is based on work undertaken within the COMPOSE European project and submitted to W3C as a possible starting point for a future Working Group chartered to work on the Web of Things.

Introduction

The following guidelines and recommendations aim at ensuring interoperability across all entities on the Web of Things. Unlike custom (non-Web) protocols used for machine-to-machine communications that create a “parallel universe” to the existing Web; the Web of Things is designed to be seamlessly integrated to the existing Web so it can fully leverage its infrastructure and standards to minimize integrations across applications and systems.

The proposal is composed of three sub-parts:

While the Web Things Requirements are described with the HTTP and WebSockets protocols using JSON because they are well supported on the Web of browsers, the Web Thing Model can also be applied to describe the models and interactions of Things supported via other RESTful protocols such as CoAP [[!RFC7252]] or even pub/sub protocols such as [[!MQTT]].

Web Thing Model levels build on top of each other, from a Web Thing that implement the requirements to the Extended Web Thing and Semantic Web Thing
Web Thing Model levels (source: [[WoTBook]])

This specification has two classes of products:

Web Thing
A Web Thing (or simply Thing) is a digital representation of a physical object accessible via a RESTful Web API. Examples of Web Things are: an Arduino board, a garage door, a bottle of soda, a building, a TV, etc. The API of the Web Thing can be hosted on the Thing itself or on an intermediate host in the network such as a Gateway or a Cloud service (for Things that aren't accessible through the Internet).

A Web Thing conforms to this specification if it follows the statements defined in .

Extended Web Thing
An Extended Web Thing is a Web Thing that additionally supports the REST API and data model defined in this specification, thus enabling its automatic inclusion in more complex systems.

An Extended Web Thing conforms to this specification if it follows the statements defined in and .

Terminology

The following terms are considered in this proposal:

Client
A Client refers to any physical or digital entity that can interact with a Web Thing. This can be a mobile application, a Web browser, a proxy, a desktop application, but also another Web Things (e.g., in the case of Machine to Machine communication).
Property
A Property is a variable of a Web Thing. Properties represent the internal state of a Web Thing. Clients can subscribe to properties to receive a notification message when specific conditions are met (e.g. value of one or more properties changed).
Action
An Action is a function offered by a Web Thing. A Client invokes a function on a Web Thing which initiates a state transition by sending it an Action. Examples of Actions are “open” or “close” for a garage door; “enable” or “disable” for a smoke alarm; “check-in” or “scan” for a bottle of soda or a place. The direction of an Action is from the Client to the Web Thing.

Web Things integration patterns

This part looks into the different ways of integrating physical objects to the Web to make them Web Things. Once a pattern has been choosen, the server of a Web Thing should follow the Web Things Requirements and the resources and payloads it uses should follow the Web Things Model .

Some physical entities might not expose a Web API themselves for various reasons (e.g., a ZigBee sensor node, or a heart rate monitor accessible over Bluetooth only), in which case they are not Web Things as such, but they can use another Web Thing as a proxy or gateway to provide a Web API for them, therefore turning them into Web Things.

While the three integration patterns described below need to be taken into account, it is worth noting that the requirements and model apply regardless of the integration pattern of choice.

Direct Connectivity

In the most straightforward case, a Web Thing is simply a Web API that Clients send requests to. In some cases, the Client and the Web Thing can be on the same network or on different networks. In both cases, you are sending the same request to a Web Thing. The only difference is the URL to which you are sending the request (and obviously how the Web Thing gets the message).

When a Web Thing exposes a Web API, Clients can directly connect to it, potential through a local address if they are both on the same network
Direct connectivity between a Client and a Web Thing (source: [[WoTBook]])

Gateway-Based Connectivity

Gateway-based connectivity is used when a Thing cannot offer a Web API directly. In this case an intermediate Web Thing - the gateway - exposes a Web API on the Thing's behalf. The Web Thing therefore acts as a proxy for the Thing (or gateway depending on the complexity/layer of the translation).

When a Web Thing cannot expose a Web API directly, Clients connect to it through a Gateway that exposes the Web API on their behalf
Gateway-based connectivity between a Client and a Web Thing (source: [[WoTBook]])

Cloud-Based Connectivity

This third case is similar to . However, in this case the gateway is a cloud service and not another device in situ.

A cloud service may expose the Web API of a Web Thing for Clients to connect to it
Cloud-based connectivity between a Client and a Web Thing (source: [[WoTBook]])

Web Things requirements

This part defines a set of rules for implementing Web Things. It assumes that an Integration Pattern was chosen.

Level 0 – MUST

This section defines the Level 0 requirements – all of which MUST be in place in any Web Thing implementation, as all Clients will expect these constraints.

R0.1 – A Web Thing MUST at least be an HTTP/1.1 server

All Web Things MUST support communication over HTTP/1.1 [[!RFC2616]]. When possible, Web Things SHOULD also support HTTP/2 [[!RFC7540]].

HTTP/1.1 is the most widely spread protocol over the Web and virtually any HTTP client or server implementation supports it, therefore it is likely that the majority of clients might not support HTTP/2 as of yet. This can be implemented directly on the Web Thing or can be provided via a proxy (see Integration Patterns).

As a consequence, while Clients should not expect support for HTTP/2, communication with a Web Thing using HTTP/1.1 is always possible.

R0.2 – A Web Thing MUST have a root resource accessible via an HTTP URL

A Web Thing MUST have a so-called “root resource” identified by a HTTP URL (uses the HTTP protocol, therefore starts with http:// or https://) that acts as the entry point for the Web Thing and enables the interaction with it. This root resource makes the Web Thing both uniquely identifiable and addressable over a network so that Clients can interact with it.

If the Web Thing is a device connected on a LAN (e.g. a printer, a lamp, etc.), the root URL of a Web Thing SHOULD be its IP address and standard HTTP port, so that, knowing only the IP address of a networked device that is a Web Thing, a Client can send an HTTP GET request on that IP address over the default port (80 for HTTP, 443 for HTTPS) to retrieve a representation of the Web Thing. This feature is envisioned to facilitate discovery of devices at the network level, without requiring an additional protocol.

A Web Thing does not need to be publicly accessible over the Internet, as some Web of Things scenarios might only work within a local area network (LAN) as defined above. This means a root URL does not need to be public and can be simply the local IP address of a device. The Root URL of a Web Thing is referred to as {wt} throughout this document.

            http://gateway.api.com/devices/TV
            http://kitchen-raspberry.device-lab.co.uk
            https://192.168.10.10:9002
            https://kitchen:3000/fridge/root
          

R0.3 – A Web Thing MUST support GET, POST, PUT and DELETE HTTP verbs

The Web of Things aims to maximise interoperability by exposing the services of Things using REST [[REST]]. For this idea to come to reality, supporting certain HTTP verbs of the specification is required. Considering that the REST paradigm is based on resources and CRUD operations on them, a Web Thing MUST support GET for reading operations, POST for creation, PUT for updates and state changes, and DELETE for removal.

R0.4 – A Web Thing MUST implement HTTP status codes 200, 400, 500

Proper usage of HTTP/1.1 error codes is advisable. However, considering that some devices are restricted, only the following subset is mandatory:

  • 2XX Success. Returned for any successful action. The Web Thing MUST at least support the 200 OK response.
  • 4XX Client Error. This should be returned for any error due to the client that sent the request (from a wrong URL, to invalid authentication, or incorrect parameter). The Web Thing MUST at least support the 400 Bad Request error code.
  • 5XX Server Error. This should be used for any error on the Web Thing side when a request was valid but cannot be processed at this time for any reason, e.g. the Web Thing has a server error, etc. The Web Thing MUST at least support the 500 Internal Server Error error code.

R0.5 – A Web Thing MUST support JSON as default representation

A Web Thing MUST always accept a valid JSON document [[!RFC7159]] as input payload for requests and always return a JSON representation when requested. If no Accept: HTTP header is specified in the request (or if the format is unknown or not supported), the Web Thing SHOULD return an appropriate error code, but it also MAY return JSON as default. Fields in JSON objects should follow the camelCase convention starting with a lowerCase letter (e.g., backColor) or a special character (e.g., _customRelation).

A Web Thing MAY support additional formats.

A consequence of supporting JSON is that UTF-8 is the default encoding for payloads (see Character Encoding in the JSON specification [[!RFC7159]])

R0.6 – A Web Thing MUST support GET on its root URL

Because they all have a unique root URL and sometimes it is all we know about them, Web Things MUST respond to HTTP GET requests on their root URL with their basic representation, so that Clients can use and understand it.

The basic representation returned by an Extended Web Thing is defined in

Level 1 – SHOULD

Unless there are technical or practical limitations for not adhering to Level 1 constraints, Web Things SHOULD support the following constraints.

R1.1 – A Web Thing SHOULD use secure HTTP connections (HTTPS)

Ideally, Web Thing SHOULD support secure connections with HTTP over TLS [[!RFC5246]]. The ideal case for security is to support only HTTP over TLS. Web Thing that are exposed on the Internet MUST always implement HTTP over TLS.

Web Things MAY use other security mechanisms if they want to (in addition or in place of HTTPS). In some cases, it might be impossible or impractical to implement HTTPS over TLS (for example in pure intranet scenario), in which case using another security mechanism is still highly recommended.

R1.2 – A Web Thing SHOULD implement the WebSocket Protocol

Clients SHOULD be able to subscribe to notifications from Web Thing using a Publish/Subscribe (Pub/Sub) pattern implemented using the WebSocket protocol [[!RFC6455]].

R1.3 – A Web Thing SHOULD support the Web Things model

If possible, every Web Thing SHOULD implement the Web Things Model. It is not essential to use it for a device to be part of the Web of Things, but implementing it will lead to a higher degree of interoperability.

An Extended Web Thing fulfills this requirement by definition. In other words, while this specification acknowledges the usefulness of the Web Thing level to accommodate legacy devices and very restricted scenarios, implementers are encouraged to implement Extended Web Things.

R1.4 – A Web Thing SHOULD return a 204 for all write operations

By default, all PUT, POST, and DELETE requests to a Web Thing should not return the payload of the object that was created/modified, therefore should return a 204 NO CONTENT response and no response body.

R1.5 – A Web Thing SHOULD provide a default human-readable documentation

To interact with a Web Thing, a Client needs to know how to use a Web Thing. The format of the API documentation is left to implementers, but should describe the resources offered, the verbs they support, the payloads accepted and returned, and possible status codes that can be returned and when.

Level 2 – MAY

A Web Thing MAY support these rules, but is not expected to. It depends on the device capabilities and other implementation aspects.

R2.1 – A Web Thing MAY support the HTTP OPTIONS verb for each of its resources

Any resource of a Web Thing should implement the OPTIONS verb to describe what verbs are supported by each resource.

R2.2 – A Web Thing MAY provide additional representation mechanisms (RDF, XML, JSON-LD)

A Web Thing MAY provide additional representations of its data and descriptions. JSON is the only mandatory representation. Additional formats are up to the implementers if needed for additional purposes. The discovery of additional representation SHOULD be supported via HTTP content-negotiation [[!content-negotiation]].

R2.3 – A Web Thing MAY offer a HTML-based user interface

A Web Thing MAY expose a UI in HTML, CSS and JavaScript. For example, the UI may be a HTML widget to integrate the Web Thing in dashboard environments.

R2.4 – A Web Thing MAY provide precise information about the intended meaning of individual parts of the model

A Web Thing MAY provide additional meta data to precisely describe the meaning of individual building blocks of a model in a machine-understandable way.

Web Things model

This part defines the model, JSON payloads and REST API that an Extended Web Thing MUST implement to allow Clients to automatically discover and use its properties. It assumes an Integration Pattern and that the Web Thing follows the Web Things Requirements. As such, the Web Things model is a contract between clients and Things in the IoT.

An Extended Web Thing has a root resource accessible via an HTTP URL and supports HTTP GET requests on that URL (see and ).

An Extended Web Thing MUST create a URL endpoint for all the resources that it exposes, including itself. Relative URLs are to be resolved against the URL of the resource that includes them. Implementers are encouraged to create a logical tree structure for resources and to use relative URLs to keep JSON payloads short, for instance:

URL Description
{wt} The root resource URL
{wt}/model/ The model of a Web Thing
{wt}/properties/ The list of properties
{wt}/properties/{id} A specific property
{wt}/actions/ The list of actions
{wt}/actions/{id} A specific action
{wt}/actions/{id}/{actionId} A specific execution of an action
{wt}/.../ ...

Common Constructs

In response to an HTTP GET request on one of its resources (including the root resource), an Extended Web Thing MUST return a JSON representation of that resource that follows the JSON schema defined in the table below:

Field name Type Description
id String The URL of this resource following the URI format [[!RFC3986]]. Relative URLs are resolved against the URL of the enclosing resource.
This field is required.
createdAt String Timestamp when this resource was created, following the ISO8601 notation [[!ISO8601]].
updatedAt String Timestamp when this resource was last updated, following the ISO8601 notation [[!ISO8601]].
name String A short human-readable name for the resource.
description String A human-readable description of the resource.
tags [String] An array of tags.
customFields Object A JSON object with key-value pairs to store custom information about this resource (e.g. {"key":"value",...}).
links Object A JSON object that lists the sub-resources that this resource links to. See for details.
{
  "id": "myCar",
  "name": "My great car",
  "description": "This is such a great car.",
  "createdAt": "2012-08-24T17:29:11.683Z",
  "updatedAt": "2012-08-24T17:29:11.683Z",
  "tags": [
    "cart",
    "device",
    "test"
  ],
  "customFields": {
    "size": "20",
    "color": "blue"
  },
  "links": {
    "model": {
      "link": "model/",
      "title": "Model this Web Thing."
    },
    "properties": {
      "link": "properties/",
      "title": "Properties of this Web Thing."
    },
    "actions": {
      "link": "actions/",
      "title": "Actions of this Web Thing."
    },
    ...
  }
}
        

The JSON response MAY contain additional fields, depending on the type of resource being considered, check the for details.

Pagination

Requests on things of a gateway, on properties that store the history of value changes or on executed actions return many items will be paginated to 30 items by default. You can specify any further page to be returned using the ?page parameter. For example, set a custom page size up to 100 with the ?perPage parameter with: GET {wt}/properties/acceleration?page=3&perPage=100 Extra pagination data is sent in response headers.
        Result-Count: 562
        Link: <http://webofthings.io/properties/acceleration?page=3&perPage=100<; rel="next",
        <http://webofthings.io/properties/acceleration?page=56&perPage=100<; rel="last"

            
The Result-Count header contains the total number of results. The pagination info is included in the Link header.
rel value Description
next The URL of the last page of results.
first The URL of the first page of results.
prev The URL of the immediate previous page of results.

Links

A resource may link to a number of sub-resources. To enable the discovery of these sub-resources (as required by the HATEOAS constraint of the REST application architecture), an Extended Web Thing SHOULD expose sub-resources associated with a given resource using the HTTP Link header field [[!RFC5988]].

In particular, each link is defined by a relation type (the "link type"), the actual URL of the sub-resource (the "link"), and a human-readable identifier for the relation (the "title"). Relation types defined in [[!RFC5988]] may be used to characterize the relation with the sub-resource. Additionally, the Web Things model defines the following relation types:

Relation name Description Section
model A link to an Extended Web Thing compliant description of a resource. Model Resource
properties The properties of this resource. Properties Resource
actions The actions that this resource can perform. Actions Resource
things The Web things proxied by this resource (if applicable). Things Resource
subscriptions The endpoint to manage subscriptions to this resource. Subscriptions Resource
type Can be used to indicate that the context resource is an instance of the resource identified by the target external URL.
product A link to authoritative product information for this Web Thing. Product
help A link to the online manual page for this Web Thing. 4.8.4.4 Link type "help"
ui A link to the HTML-based user interface for this Web Thing. External Resource
<_customRelType> A link to a custom resource. Custom Resource

An Extended Web Thing MAY use custom relation types using URLs as described in [[!RFC5988]]. As a convention, custom relation types start with an underscore _.

In addition to exposing them in the HTTP Header of each resource, links SHOULD be exposed from the Model resource of a Extended Web Thing using the links field of the JSON payload. The keys of this object represent the relation type while each value describes the actual link as illustrated below.

        {
          ...
          "links":{
            "<relType>":{
              "link": "<String>",
              "title": "<String>"
            }
            "<_customRelType>":{
              "link": "<String>",
              "title": "<String>"
            },
            ...     
          }
          ... 
        }
        

The following fields define the actual link:

Field name Type Description
link String The URL of the destination of the link.
This field is required.
title String A human-readable label of the destination of the link.
This field is required.
          {
              "model": {
                "link": "model/",
                "title": "Model of this Web Thing."
              },
              "properties": {
                "link": "properties/",
                "title": "Properties of this Web Thing."
              },
              "actions": {
                "link": "actions/",
                "title": "Actions of this Web Thing."
              },
              "product": {
                "link": "https://www.raspberrypi.org/products/raspberry-pi-2-model-b/",
                "title": "Product this Web Thing is an instance of"
              },
              "type": {
                "link": "http://webofthings.org/schemas/web-thing/",
                "title": "External information about the instance type of this Thing"
              },
              "help": {
                "link": "http://webofthings.org/docs/pi/",
                "title": "Documentation"
              },
              "ui": {
                "link": "ui/",
                "title": "User Interface"
              },
              "_myCustomLinkRelType": {
                "link": "custom/",
                "schema": "http://webofthings.org/schemas/custom.html",
                "title": "My custom resource"
              },
              "_..." : {"..." : {"..."}}
          }
        

A GET request on any resource of a Web Thing should return the list of all related resources as "Link" HTTP headers, which allows to use the same standard model regardless of the representation chosen. This is an example of the headers returned after a GET {wt}/ on the root URL of a Web Thing:

            Link: <model/>; rel="model"
            Link: <properties/>; rel="properties"
            Link: <actions/>; rel="actions"
            Link: <product/>; rel="product"
            Link: <type/>; rel="type"
            Link: <help/>; rel="help"
            Link: <ui/>; rel="ui"
        

Values

Several resources support values (particularly Actions and Properties). A values object contains the description of a set of values identified by their name. The description includes the value type, unit, and possible concrete values that the value can take. A values object is typically used to define the parameters a Client can use when it issues an Action or accesses the channels of a Property.

The following fields MAY be used to describe a values object:

Field name Type Description
<valueName> String The identifier of this value
This field is required.
name String A human-readable caption for this value.
description String A human-readable description of this value.
type String The type of this value. The supported types are integer, float, boolean, string.
unit String The unit of this value using one the (case-insensitive) full names defined in the International System of Units [[!SI]].
Example: "meter per second squared"
required Boolean Specifies whether this value is required or optional. If omitted, the default is true.
minValue Number The minimal concrete value that this value can take.
maxValue Number The maximal concrete value of this value
enum Object Specifies a set of concrete values that this value can take, e.g.
{"LOCK":"Locks the door.", "UNLOCK":"unlocks the door."}
          {
            ...
            "values": {
              "<valueName>":{
                "name":"<String>",
                "description":"<String>",
                "type":"<String>",
                "unit":"<String>",
                "required":"<Boolean>",
                "minValue":"<Numeric>",
                "maxValue":"<Numeric>"
              },
              ...
            }
            ...
          }
        

The value name timestamp is reserved. An Extended Web Thing MUST append a timestamp, set to the current date and time, whenever it creates a value unless that timestamp is already provided. The timestamp field follows the ISO8601 notation [[!ISO8601]]. The createdAt is different from timestamp because it used to refer when a resource has been created (server side information only), whereas the timestamp indicates when a value (property) has been measured (by the client or the Web Thing).

Resources

HTTP verbs support

Ideally, an Extended Web Thing SHOULD support all end-points. The letters D,G,C refer to and is here as an indication of which type of integration would typically implement these resources. A D means that the resource should be implemented on Web Things using the the Direct integration pattern, a G means the resource should be implemented when using the Gateway integration pattern, a C means the resource should be implemented when using the Cloud integration pattern.

The URLs used in this table are indicative as an Extended Web Thing may choose to use other URLs for them. The actual URLs are to be reported in the representation of the in Link HTTP Headers and in the JSON links field as described in of the Model resource.

REST URL POST GET PUT DELETE OPTIONS Details
{wt} G,C D,G,C D,G,C G,C D,G,C Thing Resource
{wt}/model - D,G,C G,C - D,G,C Model Resource
{wt}/properties G,C D,G,C - - D,G,C Properties Resource
{wt}/properties/{id} - D,G,C G,C - D,G,C Properties Resource
{wt}/actions G,C D,G,C - - D,G,C Actions Resource
{wt}/actions/{id} D,G,C D,G,C - - D,G,C Actions Resource
{wt}/actions/{id}/{actionId} - D,G,C - D,G,C D,G,C Actions Resource
{wt}/things G,C G,C - - G,C Things Resource
{wt}/things/{id} - G,C G,C G,C G,C Things Resource
{wt}/subscriptions - D,G,C - D,G,C D,G,C Subscriptions Resource

Web Thing Resource

A Web Thing is the virtual representation of a physical object. It is the root resource of the Web Things model.

The Web Thing URL is either the root URL of the API or, in the case of a proxy for other Web Things, the result of resolving the id returned in the representation of the Web Things resource.

Retrieve a Web Thing

In response to an HTTP GET request on the root URL of a Thing, an Extended Web Thing MUST return an object that its representation.

            --> REQUEST
            GET {wt}
 
            <-- RESPONSE
            200 OK
            Link: <model/>; rel="model"
            Link: <properties/>; rel="properties"
            Link: <actions/>; rel="actions"
            Link: <product/>; rel="product"
            Link: <type/>; rel="type"
            Link: <help/>; rel="help"
            Link: <ui/>; rel="ui"
            Link: <_myCustomLinkRelType/>; rel="_myCustomLinkRelType"

            {
              "id": "myCar",
              "name": "My super great car",
              "description": "This is such a great car.",
              "createdAd": "2012-08-24T17:29:11.683Z",
              "updatedAd": "2012-08-24T17:29:11.683Z",
              "tags":["cart", "device", "test"],
              "customFields":{
                  "size": "20",
                  "color":"blue"
              }
            }
            

Update a Web Thing

In response to an HTTP PUT request on a Web Thing URL with a Web Thing object as request body, an Extended Web Thing MUST either reject the request with the appropriate status code (e.g. because the Client is unauthenticated or because the Thing is read-only) or store the provided value(s) by updating the Web Thing. Partial updates are authorized and result in updating the fields that were provided in the request body.

            --> REQUEST
            PUT {wt}
    
            {
              "name":"My really super great car"
            }

            <-- RESPONSE
            204 NO CONTENT
            

Model Resource

A Model describes the values of properties and actions that can be performed on Things.

The Model URL is the result of resolving the id returned in the representation of a Property against the destination URL of the properties link that gave birth to it.

Retrieve the model of a Thing

In response to an HTTP GET request on the destination URL of a model link, an Extended Web Thing MUST return an object containing the model of the Thing.

                --> REQUEST
                GET {wt}/model

                <-- RESPONSE
                200 OK

{
  "id": "pi",
  "name": "My WoT Raspberry PI",
  "description": "A simple WoT-connected Raspberry PI for the WoT Label.",
  "tags": [
    "raspberry",
    "pi",
    "WoT"
  ],
  "customFields" : {
    "port" : 8484
  },
  "links": {
    "product": {
      "link": "https://www.raspberrypi.org/products/raspberry-pi-2-model-b/",
      "title": "Product this Web Thing is based on"
    },
    "properties": {
      "link": "/properties",
      "title": "List of Properties",
      "resources": {
        "temperature": {
          "name": "Temperature Sensor",
          "description": "An ambient temperature sensor.",
          "values": {
            "temp": {
              "name": "Temperature sensor",
              "description": "The temperature in celsius",
              "unit": "celsius",
              "customFields": {
                "gpio": 21
              }
            }
          },
          "tags": [
            "sensor",
            "public",
            "indoors"
          ]
        },
        "humidity": {
          "name": "Humidity Sensor",
          "description": "An ambient humidity sensor.",
          "values": {
            "h": {
              "name": "Humidity",
              "description": "Percentage of Humidity",
              "unit": "percent",
              "customFields": {
                "gpio": 21
              }
            }
          },
          "tags": [
            "sensor",
            "public"
          ]
        },
        "pir": {
          "name": "Passive Infrared",
          "description": "A passive infrared sensor.",
          "values": {
            "p": {
              "name": "Presence",
              "description": "Current sensor value (true=motion detected)",
              "type": "boolean",
              "customFields": {
                "gpio": 20
              }
            }
          },
          "tags": [
            "sensor",
            "public"
          ]
        },
        "leds": {
          "name": "LEDs",
          "description": "The LEDs of this device.",
          "values": {
            "1": {
              "name": "LED 1",
              "customFields": {
                "gpio": 17
              }
            },
            "2": {
              "name": "LED 2",
              "customFields": {
                "gpio": 19
              }
            }
          },
          "tags": [
            "sensor",
            "public"
          ]
        }
      }
    },
    "actions": {
      "link": "/actions",
      "title": "Actions of this Web Thing",
      "resources": {
        "ledState": {
          "values": {
            "ledId": {
              "type": "string",
              "required": true
            },
            "state": {
              "type": "boolean",
              "required" : true
            }
          }
        }
      }
    },
    "type": {
      "link": "http://w3c.org/schemas/webthing/",
      "title": "Instance type of the Pi"
    },
    "help": {
      "link": "http://webofthings.org/docs/pi/",
      "title": "Documentation"
    },
    "ui": {
      "link": "/ui",
      "title": "User Interface"
    }
  }
}
            

Update the model of a Thing

In response to an HTTP PUT request on a Model URL with a Model object as request body, an Extended Web Thing MUST either reject the request with the appropriate status code (e.g. because the Client is unauthenticated or because the Model is read-only) or store the provided value(s) by updating the Model. Partial updates are authorized and result in updating the fields that were provided in the request body.

Usually, the model will be hardcoded in the device and generally cannot be altered by clients. If the Web Thing is hosted on a cloud service, the model can be updated by sending an HTTP PUT request to the same URL, with the new model document in the request body.

Properties Resource

A Property keeps track of a set of variables about a device (its location, the temperature sensor reading, etc.).

The Property URL is the result of resolving the id returned in the representation of a Property against the destination URL of the properties link that gave birth to it.

Retrieve a list of properties

In response to an HTTP GET request on the destination URL of a properties link, an Extended Web Thing MUST return an array of Property that the initial resource contains.

              --> REQUEST
              GET {wt}/properties


              <-- RESPONSE
              200 OK
              Link: <http://webofthings.io/properties>; rel="type"

              [
                {
                  "id":"temperature",
                  "name":"Kitchen Temperature Sensor",
                  "values":{
                    "temp":22,
                    "timestamp":"2015-06-14T14:30:00.000Z"
                  }
                },
                {
                  "id":"status",
                  "name":"Device Status",
                  "values":{
                    "status":"OK",
                    "timestamp":"2015-06-14T14:30:00.000Z"
                  }
                },
                {
                  "id":"acceleration",
                  "name":"Acceleration",
                  "values":{
                    "x":22,
                    "y":22.56,
                    "z":1.4,
                    "timestamp":"2015-06-14T14:30:00.000Z"
                  }
                },
                {
                  "id":"engineAngle",
                  "name":"Engine Angle",
                  "values":{
                    "theta":2,
                    "rho":-0.1,
                    "timestamp":"2015-06-14T14:30:00.000Z"
                  }
                }
              ]
            

Retrieve the value of a property

In response to an HTTP GET request on a Property URL, an Extended Web Thing MUST return an array that lists recent values of that Property.

Some Web Things might not store the history of sensor readings but only the most recent value of a given property, in which case the array will always contain one object. However, Web Things on clouds and gateway are likely to store many past values of the property, in which case they can be retrieved using pagination.

              --> REQUEST
              GET {wt}/properties/acceleration

              <-- RESPONSE
              200 OK
              Link <model/>; rel="model"

              [
                {
                  "x":11,
                  "y":1,
                  "z":-4.4,
                  "timestamp":"2015-06-14T14:30:00.000Z"
                },
                {
                  "x":3.4,
                  "y":-1,
                  "z":-4.6,
                  "timestamp":"2015-06-14T14:00:00.000Z"
                }
              ]
            

Update a specific property

In response to an HTTP PUT request on a Property URL with an array of values as request body, an Extended Web Thing MUST either reject the request with the appropriate status code (e.g. because the Client is unauthenticated or because the Property is read-only) or store the provided value(s) as new values for the Property. The body of the request SHOULD always be an array of values (at least one), which allows to send several property value updates within a single request.

              --> REQUEST
              PUT {wt}/properties/temperature/

              [
                {
                  "temp":24
                }
              ]


              <-- RESPONSE
              204 NO CONTENT
              Location: {wt}/properties/temperature/
            

A Property URL is always a collection of resources, therefore its representation is an array of individual values with different timestamps. The individual values are not adressable individually, therefore the Location: header in response to a successful property update request SHOULD always be the Property URL itself.

Update multiple properties at once

In response to an HTTP POST request on the destination URL of a properties link, an Extended Web Thing MUST either reject the request with the appropriate status code or store the provided values as new values for each of the provided Properties.

              --> REQUEST
              PUT {wt}/properties/

              [
                {
                  "id":"temperature",
                  "value":{
                    "temp":24,
                    "timestamp":"2015-06-14T14:30:00.000Z"
                  }
                },
                {
                  "id":"acceleration",
                  "value":{
                    "x":-22,
                    "y":2.1,
                    "z":3,
                  }
                }
              ]

              <-- RESPONSE
              204 NO CONTENT
              Location: {wt}/properties/
            

Actions Resource

On top of , the JSON representation used to describe an Action includes the following fields:

Field name Type Description
values Object A description of the parameters that his action accepts.
See .
This field is required.

The Action URL is the result of resolving the id returned in an Action description against the destination URL of the actions link that gave birth to it.

Retrieve a list of actions

In response to an HTTP GET request on the destination URL of an actions link exposed by a resource, an Extended Web Thing MUST return an array of Action descriptions that the initial resource may perform.

              --> REQUEST
              GET {wt}/actions


              <-- RESPONSE
              200 OK
              Link: <http://webofthings.org/actions/upgradefirmware>; rel="type"

              [
                {
                  "id":"upgradeFirmware",
                  "name":"Upgrade Device Firmware"  
                },
                {
                  "id":"reboot",
                  "name":"Reboot"  
                }
              ]
            

Retrieve recent executions of a specific action

In response to an HTTP GET request on an Action URL, an Extended Web Thing MUST return an array that lists the recent executions of a specific Action.

On top of , the JSON representation used to describe the execution of an Action includes the following fields:

Field name Type Description
status String The execution status. One of pending, executing, completed or failed
              --> REQUEST
              GET {wt}/actions/upgradefirmware

              <-- RESPONSE
              200 OK
              Link: <http://webofthings.org/actions/upgradefirmware>; rel="type"
              Link: <model/>; rel="model"

              [
                {
                  "id":"223",
                  "value":{
                    "delay":30,
                    "mode":"SOFT"
                  },
                  "status":"executing"
                  "timestamp":"2015-06-14T18:33:25.938Z"
                },
                {
                  "id":"222",
                  "value":{
                    "delay":60,
                    "mode":"FORCE"
                  },
                  "status":"completed"
                  "timestamp":"2015-06-14T14:22:23.233Z"
                }
              ]
            

Execute an action

In response to an HTTP POST request on an Action URL with valid parameters as request body, an Extended Web Thing MUST either reject the request with the appropriate status code or queue a task to run the action and return the status of that action in a 201 Created response. The action may not run immediately. The Location HTTP header identifies the URL to use to retrieve the most recent update on the action's status.

This is how a Client sends a command to a device.

              --> REQUEST
              POST {wt}/actions/reboot

              {
                "delay":50,
                "mode":"debug"
              }

              <-- RESPONSE
              204 NO RESPONSE
              Location: {wt}/actions/reboot/233
            

Retrieve the status of an action

In response to an HTTP GET request on the URL targeted by the Location HTTP header returned in response to the request to execute an action, an Extended Web Thing MUST return the status of this action or a 404 Not Found status code if the action's status is no longer available.

                      --> REQUEST
                      GET {wt}/actions/reboot/233

                      <-- RESPONSE
                      200 OK

                      {
                        "id":"233",
                        "value":{
                          "delay":50,
                          "mode":"debug"
                        },
                        "status":"executing",
                        "timestamp":"2015-06-14T14:30:00.000Z"
                      }
                    

Things Resource

A Web Thing may proxy other Web Things via the Things resource. For instance, it is expected that gateways and cloud services will proxy a number of third party devices. On top of , the JSON representation used to describe a link to another thing includes the following fields:

Field name Type Description
rootUrl String The URL of the root resource of the Web Thing if it is different from {wt}/thing/{id}

Retrieve a list of Web Things

In response to an HTTP GET request on the destination URL of a things link, an Extended Web Thing MUST return an array of things descriptions.

                    --> REQUEST
                    GET {wt}/things
                                
                    <-- RESPONSE
                    200 OK

                    [
                      {
                        "id":"982tjqogeih",
                        "name":"Shopping Cart"
                      },  
                      {
                        "id":"2398h87wt489foz",
                        "name":"Shopping Cart",
                        "rootUrl":"/pi",
                        "description":"Shopping Cart that updates its location as it moves"
                      },  
                      {
                        "id":"p9qrnc89w48oh",
                        "name":"Shopping Cart",
                        "rootUrl":"https://192.168.0.6/",
                        "description":"LAN-connected gateway to Lamp #4."
                      }
                    ]
                    

The id can be interpreted as a URL, but if a Web Thing can be directly accessed without the proxy, the rootUrl can be used to provide a different Root URL.

Add a Web Thing to a gateway

Clients can add new Things to be proxied by a Web Thing (especially for gateways/cloud) using an HTTP POST request on the Thing URL of a Web Thing and by sending in the request body the root resource representation of the Thing to be proxied.

                    --> REQUEST
                    POST {wt}/things

                    {
                      "id":"p9qrnc89w48oh",
                      "name":"Shopping Cart",
                      "rootUrl":"https://192.168.0.6/",
                      "description":"LAN-connected gateway to Lamp #4."
                    }
                                
                    <-- RESPONSE
                    204 NO CONTENT
                    Location: {wt}/things/p9qrnc89w48oh
                    

Subscriptions Resource

All resources can be subscribed to but in particular, an Extended Web Thing SHOULD enable subscriptions to Actions and Properties. Subscriptions allows for a Client to be notified via a push event whenever the state of an observed resource changes.

The Subscription resource allows to list current subscriptions to resources as well as cancelling a subscription. Such a resource is accessible via the root URL of the Extended Web Thing.

On top of , the JSON representation used to describe a subscription includes the following fields:

Field name Type Description
subscriberId String A unique identifier for the subscriber
This field is required.
type String The type of connection used to exchange updates with the subscriber. One of httpCallback or websockets
resource String The URL of the resource whose changes the subscriber is subscribed to.

Create a subscription

An Extended Web Thing SHOULD support subscriptions via the WebSocket [[!RFC6455]] protocol and MAY support subscriptions via WebHooks (HTTP callbacks). Subscriptions are enabled via the HTTP protocol upgrade mechanism [[!RFC2616]] as shown below.

Clients can subscribe to resources via a protocol upgrade.
Client subscription to a resource via a protocol upgrade, first via Websocket, second via a Webhook (HTTP callback).

To subscribe to a resource the following HTTP headers should be provided via a GET request (e.g., on /properties/temp).

Header name Description
Upgrade The protocol that should be used for the subscription, one of webhook or websocket
This header is required.
Callback The callback URL to which updates should be pushed. webhook or websocket
This header is required in the case of a webhook subscription.

In response to a HTTP GET request on the destination URL of a resource, an Extended Web Thing MUST either reject the request with an appropriate status code or MUST return a 101 Switching Protocol response for a subscription via Websocket or a 200 OK for a subscription via Webhook. It SHOULD then create a record for the subscription that can be retrieved via the /subscriptions URL. For both Websockets and Webhooks subscriptions the following headers must be returned (on top of the protocol specific headers):

Header name Description
Subscription-ID The identifier of the subscription
This header is required.

Retrieve a list of subscriptions

In response to an HTTP GET request on the destination URL of a subscriptions link, an Extended Web Thing MUST return the array of subscriptions to the underlying resource.

            [
              {
                "id":"2349",
                "type":"webhook",
                "resource":"/properties/temperature",
                "callbackUrl":"http://www.compose-project.eu/so/ServiceObject-123213213/callback"
              },
              {
                "id":"2350",
                "subscriberId":"ServiceObject-123213213",
                "type":"websocket",
                "resource":"/properties/location"
              }
            ]
            

The Subscription URL is the result of resolving the id returned in a Subscription resource description against the destination URL of the subscriptions link that gave birth to it.

Retrieve information about a specific subscription

In response to an HTTP GET request on a Subscription URL, an Extended Web Thing MUST return a JSON representation of the subscription. The JSON representation should be the same as the one returned for that subscription in .

              {
                "id":"2349",
                "type":"webhook",
                "resource":"/properties/temperature",
                "callbackUrl":"http://www.compose-project.eu/so/ServiceObject-123213213/callback"
              }
            

Delete a subscription

In response to an HTTP DELETE request on the destination URL of a subscriptions an Extended Web Thing MUST either reject the request with an appropriate status code or remove (unsubscribe) the subscription and return a 200 OK status code.

Semantic Extensions

While it defines a basic semantic for Things in the IoT, the data model defined in this specification benefits from alignment with more detailed vocabularies such as those used in schema.org. The support for semantic extensions SHOULD be implemented using JSON-LD by referencing a JSON-LD context via an HTTP Link Header using the using the http://www.w3.org/ns/json-ld#context link relation as defined in [[!JSONLD]].
                GET /model HTTP/1.1
                Host: mydevice.webofthings.org
                Accept: application/json,application/ld+json,*/*;q=0.1

                ====================================

                HTTP/1.1 200 OK
                ...
                Content-Type: application/json
                Link: <https://schema.org/Product>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"

                {
                    "name": "Beaglebone Black",
                    "description": "A Beaglebone Black embedded device",
                    "productID" : "asin:B00CO3MZCW",
                    "manufacturer" : "Beagleboard", ...
                }
            

Acknowledgments

This work is supported by the European Union's 7th Research Framework Programme (FP7/2013-2015) under grant agreement nº317862 – COMPOSE).

The authors would like to thank the participants of the W3C Web of Things Interest Group, the Web of Things online community and in particular Joel Vogt and Iker Larizgoitia Abad, Francois Daoust, Johannes Hund and Joerg Heuer who have provided very valuable feedback on the drafts of this submission.

Further tools and examples to work with this specification are available on Web of Things online community Website.