Web of Things (WoT) Profiles

W3C Editor's Draft Group Note 29

More details about this document
This version:
https://w3c.github.io/wot-profile/ https://www.w3.org/TR/2025/NOTE-wot-profile-20250730/
Latest published version:
https://www.w3.org/TR/wot-profile/
Latest editor's draft:
https://w3c.github.io/wot-profile/
History:
https://www.w3.org/standards/history/wot-profile/
Editors:
Michael Lagally ( Oracle Corp. )
Ben Francis ( Invited Expert )
Michael McCool ( Intel Corp. )
Ryuichi Matsukura ( Fujitsu Ltd. )
Sebastian Kaebisch ( Siemens AG )
Tomoaki Mizushima ( Internet Research Institute, Inc. )
Feedback:
public-wot-wg@w3.org with subject line [wot-profile] … message topic … ( archives )
Contributors
In the GitHub repository
Repository
We are on GitHub
File a bug
Contribute

Abstract

This specification defines a Profiling Mechanism and a set of Profiles which enable out-of-the-box interoperability between Web Things and their Consumers on the Web of Things .

Being out-of-the-box interoperable means that any Consumer which conforms with a given Profile can interact with any Thing which conforms with the same profile, without additional customization.

A Profile is a technical specification which provides a set of assertions to which conformant Consumers and Things must conform.

The Profiling Mechanism provides a means to denote that a given Thing conforms to one or more Profiles, by referring to the identifiers of those Profiles in the profile member of its Thing Description .

The specification defines three profiles:

The Profiles defined in this specification share a set of Common Constraints to which implementations of those Profiles must also conform. This includes constraints on units, date formats, security mechanisms, discovery mechanisms, link relations and errors.

Future versions of this specification, or extension specifications, may define additional Profiles.

Status of This Document

This is a preview

Do not attempt to implement this version of the specification. Do not reference this version as authoritative in any way. Instead, see https://w3c.github.io/wot-profile/ for the Editor's draft.

This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C standards and drafts index .

This document was published by initially on the Web of Things Working Group W3C Recommendation Track and published as an Editor's Draft. Publication as an Editor's a Working Draft does on 18 January 2023. The WoT Working Group later decided not imply endorsement by to continue to pursue the document to W3C Recommendation status and its Members. This is instead to publish it as a Group Note , as a useful point of reference for use with the WoT 1.x family of specifications. A Group Note provides a stable reference for a draft document and may be updated, replaced, or obsoleted by other documents at any time. It that is inappropriate not intended to cite be a formal standard. Software MAY implement this document as other than specification at their own risk.

Following the publication of this Note, the Working Group intends to switch their attention to a work in progress. new recommendation track WoT Profiles 2.0 specification for use with the WoT 2.x family of specifications.

This document was produced published by a group operating under the W3C Patent Policy . W3C maintains a public list Web of any patent disclosures Things Working Group made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of as a patent that Group Note using the individual believes contains Essential Claim(s) must disclose Note track .

This Group Note is endorsed by the information in accordance with section 6 Web of the Things Working Group , but is not endorsed by W3C itself nor its Members.

The W3C Patent Policy . does not carry any licensing requirements or commitments on this document.

This document is governed by the 03 November 2023 W3C Process Document .

1. Introduction

1.1 Motivation

The Web of Things (WoT) seeks to counter the fragmentation of the Internet of Things (IoT) by using and extending existing, standardized web technologies.

The W3C WoT Thing Description [ wot-thing-description11 ] specification defines an information model and JSON-based representation format for describing the capabilities of connected devices and the interfaces with which to communicate with them. Thing Descriptions are designed to be protocol-agnostic and flexible enough to describe a wide range of existing ("brownfield") IoT devices.

In order to provide this level of flexibility the Thing Description specification includes a number of extension points including protocol bindings, payload bindings, security mechanisms, link relations and semantic contexts. As long as all of the capabilities of a device can be described using a Thing Description and a Consumer implements all of the extensions used, the Consumer should be able to interoperate with that device. However, the result of this extensible architecture is that any given Consumer can only interoperate with a subset of possible Web Things .

This specification is designed to complement the Thing Description [ wot-thing-description11 ] specification, by enabling ad-hoc interoperability through the use of "profiles". A profile prescribes a finite set of extensions and defaults that a Thing can be constrained to in order to guarantee out-of-the-box interoperability with any Consumer which implements that profile.

Profiles are designed specifically for new ("greenfield") implementations where developers have the freedom to conform to a prescriptive protocol binding and set of common constraints, in order to benefit from this additional level of interoperability.

Future versions of this specification, or extension specifications, may define additional Profiles.

1.2 Use Cases and Requirements

The Web of Things Interest Group collected use cases for the Web of Things from stakeholders representing various different industries. This includes both vertical domain-specific use cases and horizontal use cases which apply to multiple application domains [ wot-usecases ].

Several of the domain-specific use cases refer to the need for easy integration of devices from multiple vendors. This is especially important for cross-domain use cases which require "multi-vendor system integration" and "out-of-the-box interoperability".

A set of requirements for Profiles were derived from these use cases.

1.3 Out-of-the-Box Interoperability

At a high level, out-of-the-box interoperability means that a Consumer is guaranteed to be able to use every capability of a Thing , without Thing-specific customization.

The full definition of out-of-the-box interoperability used in this specification includes multiple layers. The following classification adopts terminology from the "H2020 – CREATE-IoT Project - Recommendations for commonalities and interoperability profiles of IoT platforms" [ H2020-CREATE-IoT ] report. The definitions below have been adapted to reflect the scope of the WoT profile.

1.3.1 Technical Interoperability

Technical Interoperability is usually associated with communication protocols and the infrastructure needed for those protocols to operate. This implies agreeing on a common protocol (e.g. HTTP / TCP/IP) and providing additional clarifications, where required.

1.3.2 Syntactic Interoperability

Syntactic Interoperability is usually associated with data formats and encodings along with techniques for compressing them. Examples for these formats and encodings in the WoT are JSON, XML, JSON-LD, UTF-8 payloads.

1.3.3 Semantic Interoperability

Semantic Interoperability is associated with a common understanding of the behavior of communication partners. In the profile context, it includes a common interpretation of (synchronous and asynchronous) action semantics, a common event model, how to set/get multiple properties, writable properties, a common error model and error messages.

Domain specific ontologies, e.g. semantic interop of automotive and medical devices exceed the scope of the this specification.

1.3.4 Organisational Interoperability

Organisational Interoperability in the profile context implies that any Consumer which conforms with a given profile can interact with any Thing which conforms with the same profile, without additional customization.

Organisational Interoperability also requires commonly agreed approaches to security, trust and privacy, i.e. a consumer is provided access to Things only when these common terms and conditions are applied.

Devices created by various engineers, vendors and SDOs that satisfy the requirements of the profile specification can be integrated with compliant consumers without additional customization. This works across infrastructures, regions and cultures.

2. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY , MUST , MUST NOT , OPTIONAL , RECOMMENDED , SHOULD , and SHOULD NOT in this document are to be interpreted as described in BCP 14 [ RFC2119 ] [ RFC8174 ] when, and only when, they appear in all capitals, as shown here.

A device or consumer implementation complies with this specification if it follows the normative statements in the present document.

3. Terminology

The fundamental WoT terminology such as Thing , Web Thing , Consumer , Thing Description ( TD ), WoT Thing Description , Partial TD , Thing Model ( TM ), Interaction Model , Interaction Affordance , Property , Action , Event , Protocol Binding , Servient , Vocabulary , Term , Vocabulary Term , WoT Interface , and WoT Runtime are defined in Section 3 of the WoT Architecture specification [ WOT-ARCHITECTURE ].

For convenience of the reader, we use the terms keyword and field for the linguistic notion vocabulary term as defined in the Thing Description Specification.

We use the terms device and thing in an interchangeable manner.

3.1 Additional Definitions

Profile
A technical specification which provides a set of assertions such that any Consumer which conforms with the those assertions is out-of-the-box interoperable with any Thing which also conforms with those assertions.

4. Profiling Mechanism

In order to conform with a profile, a Web Thing MUST conform with all the normative statements in the profile's specification.

In order to denote that a given Web Thing conforms to one or more profiles, its Thing Description MUST include a profile member [ wot-thing-description11 ]. The value of the profile member MUST be set to either a valid URI [ RFC3986 ] identifying a single profile, or an array of valid URIs identifying multiple profiles.

In order to use a profile member in a Thing Description, the @context member MUST contain the anyURI https://www.w3.org/2022/wot/td/v1.1 in order to denote that the document is using version 1.1 of the Thing Description specification. [ wot-thing-description11 ]. All Things and Consumers conforming to a profile MUST satisfy the assertions specified in the [ wot-thing-description11 ], except for the assertion td-context-ns-td10-namespacev10 with text TD 1.1 consumers MUST accept TDs satisfying the W3C WoT Thing Description 1.0 [wot-thing-description] specification.

{
  "@context": "https://www.w3.org/2022/wot/td/v1.1",
  "id": "urn:dev:ops:32473-WoTLamp-1234",
  "profile": "https://www.w3.org/2022/wot/profile/http-basic/v1",
  "title": "My Lamp",
  "description": "A web connected lamp",
  ...
}

{
  "@context": "https://www.w3.org/2022/wot/td/v1.1",
  "id": "urn:dev:ops:32473-WoTLamp-1234",
  "profile": [
    "https://www.w3.org/2022/wot/profile/http-basic/v1",
    "https://www.w3.org/2022/wot/profile/http-sse/v1"
  ],
  "title": "My Lamp",
  "description": "A web connected lamp",
  ...
}

Note

Conforming to a Profile does not prevent a Web Thing from describing additional capabilities and protocol bindings in their Thing Description beyond those described in the Profile, as long as they conform with all of the normative assertions of the Profile.

5. Common Constraints

The following sections are applicable for profiles defined by this document.

5.1 Units

Authors of Thing Descriptions should be aware that units that are common in their geographic region are not globally applicable and may lead to misinterpretation with drastic consequences.

It is highly RECOMMENDED to provide a unit , if a value has a physical quantity.

It is highly RECOMMENDED to use the metric system (SI units) for devices that are used in global deployments.

5.2 Date Format

Unless otherwise specified, all date and time values MUST use the date-time format defined in [ RFC3339 ].



2022-09-21T23:20:50.52Z


Note

In order to reduce ambiguity, RFC 3339 only permits an hour with a value between 00 and 23 (not 24), and time zones expressed as a numerical offset relative to UTC. The suffix "Z" when applied to a time denotes a UTC offset of 00:00.

5.3 Security

Conformant Consumers MUST support at least all of these security schemes.

A Thing MAY implement multiple security schemes.

A Thing MUST support at least one of the above security schemes.

For the BasicSecurityScheme the "in" field MUST be either omitted or be given its default value of "header" as defined in [[wot-thing-description11]. For the BasicSecurityScheme the "name" field MUST be provided using the value "Authorization" if a "proxy" endpoint is not given. For the BasicSecurityScheme the "name" field MUST be provided using the value "Proxy-Authorization" if a"proxy" endpoint is given.

Conformant Consumers MUST support security bootstrapping for all implemented security schemes, as defined in Security Bootstrapping in the WoT Discovery [ wot-discovery ] specification.

Conformant Things which require authentication in order to retrieve their Thing Description MUST implement security bootstrapping, as defined in Security Bootstrapping in the WoT Discovery [ wot-discovery ] specification.

5.4 Discovery

A Web Thing's Thing Description [ wot-thing-description11 ] MUST be retrievable from a Thing Description Server [ wot-architecture11 ] using an HTTP [ HTTP11 ] URL provided by a Direct Introduction Mechanism [ wot-discovery ].

5.6 Errors

If any of the operations defined in the protocol bindings of HTTP profiles are unsuccessful then the Web Thing MUST send an HTTP response with an HTTP error code which describes the reason for the failure.

It is RECOMMENDED that error responses use one of the following HTTP error codes:

  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 500 Internal Server Error
  • 503 Service Unavailable

A Web Thing MAY respond with 3xx status codes for the purposes of redirection, caching or authentication. A Web Thing MUST NOT respond with a 300 Multiple Choices status code.

Web Things MAY respond with other valid HTTP error codes (e.g. 418 I'm a teapot ). Consumers MAY interpret other valid HTTP error codes as a generic 4xx or 5xx error with no special defined behaviour.

If an HTTP error response contains a body, the content of that body MUST conform with the Problem Details format [ RFC7807 ].

6. HTTP Basic Profile

This section defines the HTTP Basic Profile, which includes a Protocol Binding for reading and writing properties and invoking, querying and cancelling actions.

This profile may be used in conjunction with the HTTP SSE Profile or the HTTP Webhook Profile in order to provide operations for observing properties and listening for events.

In order to conform with the HTTP Basic Profile, Web Things and Consumers MUST also conform with all of the assertions in the Common Constraints section.

6.1 Identifier

In order to denote that a given Web Thing conforms to the HTTP Basic Profile, its Thing Description MUST have a profile member [ wot-thing-description11 ] with a value of https://www.w3.org/2022/wot/profile/http-basic/v1 .

6.2 Protocol Binding

This section defines a protocol binding which describes how a Consumer communicates with a Web Thing [ wot-architecture11 ] using JSON [ JSON ] payloads over the HTTP [ HTTP11 ] protocol.

A Consumer or Web Thing conforming to the HTTP Basic Profile MUST implement this protocol binding.

The examples provided throughout this section describe how a Consumer would communicate with a Web Thing which produces the following Thing Description:

{
  "@context": "https://www.w3.org/2022/wot/td/v1.1",
  "id": "https://mywebthingserver.com/things/lamp",
  "profile": "https://www.w3.org/2022/wot/profile/http-basic/v1",
  "base": "https://mywebthingserver.com/things/lamp/",
  "title": "My Lamp",
  "description": "A web connected lamp",
  "securityDefinitions": {
    "oauth2": {
      "scheme": "oauth2",
      "flow": "code",
      "authorization": "https://mywebthingserver.com/oauth/authorize",
      "token": "https://mywebthingserver.com/oauth/token"
    }
  },
  "security": "oauth2",
  "properties": {
    "on": {
      "type": "boolean",
      "title": "On/Off",
      "description": "Whether the lamp is turned on",
      "forms": [{"href": "properties/on"}]
    },
    "level" : {
      "type": "integer",
      "title": "Brightness",
      "description": "The level of light from 0-100",
      "unit": "percent",
      "minimum" : 0,
      "maximum" : 100,
      "forms": [{"href": "properties/level"}]
    }
  },
  "actions": {
    "fade": {
      "title": "Fade",
      "description": "Fade the lamp to a given level",
      "synchronous": false,
      "input": {
        "type": "object",
        "properties": {
          "level": {
            "title": "Brightness",
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "unit": "percent"
          },
          "duration": {
            "title": "Duration",
            "type": "integer",
            "minimum": 0,
            "unit": "milliseconds"
          }
        }
      },
      "forms": [{"href": "actions/fade"}]
    }
  },
  "forms": [
    {
      "op": ["readallproperties", "writemultipleproperties"],
      "href": "properties"
    },
    {
      "op": "queryallactions",
      "href": "actions"
    }
  ]

}


6.2.1 Properties

6.2.1.1 readproperty

The URL of a Property resource to be used when reading the value of a property MUST be obtained from a Thing Description by locating a Form inside the corresponding PropertyAffordance for which:

  • After defaults have been applied, its op member contains the value readproperty
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • After defaults have been applied, the value of its contentType member is application/json

The resolved value of the href member MUST then be used as the URL of the Property resource.

In order to read the value of a property, a Consumer MUST send an HTTP request to a Web Thing with:

  • Method set to GET
  • URL set to the URL of the Property resource
  • Accept header set to application/json
GET /things/lamp/properties/on HTTP/1.1
Host: mythingserver.com

Accept

:

application/json

If a Web Thing receives an HTTP request following the format above and the Consumer has permission to read the corresponding property, then upon successfully reading the value of the property it MUST send an HTTP response with:

  • Status code set to 200
  • Content-Type header set to application/json
  • A body with the value of the property serialized in JSON
HTTP/1.1 200 OK
Content-Type: application/json

false


6.2.1.2 writeproperty

The URL of a Property resource to be used when writing the value of a property MUST be obtained from a Thing Description by locating a Form inside the corresponding PropertyAffordance for which:

  • After defaults have been applied, its op member contains the value writeproperty
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • After defaults have been applied, the value of its contentType member is application/json

The resolved value of the href member MUST then be used as the URL of the Property resource.

In order to write the value of a property, a Consumer MUST send an HTTP request to a Web Thing with:

  • Method set to PUT
  • URL set to the URL of the Property resource
  • Content-Type header set to application/json
  • A body with a requested new value for the property serialized in JSON
PUT /things/lamp/properties/on HTTP/1.1
Host: mythingserver.com
Content-Type: application/json

true


If a Web Thing receives an HTTP request following the format above and the Consumer has permission to write the corresponding property, then upon successfully writing the value of the property it MUST send an HTTP response with:

  • Status code set to 204


HTTP/1.1


204

No
Content

6.2.1.3 readallproperties

The URL of a Properties resource to be used when reading the value of all properties at once MUST be obtained from a Thing Description by locating a Form inside the top level forms member for which:

  • Its op member contains the value readallproperties
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • After defaults have been applied, the value of its contentType member is application/json

The resolved value of the href member MUST then be used as the URL of the Properties resource.

In order to read the value of all properties, a Consumer MUST send an HTTP request to a Web Thing with:

  • Method set to GET
  • URL set to the URL of the Properties resource
  • Accept header set to application/json
GET /things/lamp/properties HTTP/1.1
Host: mythingserver.com

Accept

:

application/json

If a Web Thing receives an HTTP request following the format above, then upon successfully reading the values of all the readable properties to which the Consumer has permission to access, it MUST send an HTTP response with:

  • Status code set to 200
  • Content-Type header set to application/json
  • A body with the values of all readable properties serialized in JSON, as an object keyed by property name
HTTP/1.1 200 OK
Content-Type: application/json
{
  "on": false,
  "level": 100
}

6.2.1.4 writemultipleproperties

The URL of a Properties resource to be used when writing the value of multiple properties at once MUST be obtained from a Thing Description by locating a Form inside the top level forms member for which:

  • Its op member contains the value writemultipleproperties
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • After defaults have been applied, the value of its contentType member is application/json

The resolved value of the href member MUST then be used as the URL of the Properties resource.

In order to write the value of multiple properties at once, a Consumer MUST send an HTTP request to a Web Thing with:

  • Method set to PUT
  • URL set to the URL of the Properties resource
  • Content-Type header set to application/json
  • A body with requested new values for the writable properties serialized in JSON, as an object keyed by property name
PUT /things/lamp/properties HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
{
  "on": true,
  "level": 50
}

If a Web Thing receives an HTTP request following the format above, then upon successfully writing the values of the requested writable properties it MUST send an HTTP response with:

  • Status code set to 204


HTTP/1.1


204

No
Content

Note

The readmultipleproperties operation is excluded due to the complexities of the request payload format and because it doesn't add much functionality over readproperty and readallproperties . writeallproperties is excluded because it is just a special case of writemultipleproperties .

6.2.2 Actions

6.2.2.1 invokeaction

The URL of an Action resource to be used when invoking an action MUST be obtained from a Thing Description by locating a Form inside the corresponding ActionAffordance for which:

  • After defaults have been applied, the value of its op member is invokeaction
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • After defaults have been applied, the value of its contentType member is application/json

The resolved value of the href member MUST then be used as the URL of the Action resource.

In order to invoke an action on a Web Thing, a Consumer MUST send an HTTP request to the Web Thing with:

  • Method set to POST
  • URL set to the URL of the Action resource
  • Accept header set to application/json
  • Content-Type header set to application/json
  • A body with an input to the action, if any, serialized in JSON
POST /things/lamp/actions/fade HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
Accept: application/json
{
  "level": 100,
  "duration": 5
}

If a Web Thing receives an HTTP request following the format above then it MUST respond with one of three response formats:

  1. Synchronous Action Response
  2. Asynchronous Action Response
  3. Error Response

The synchronous member of an ActionAffordance MUST be set to true or false .

If the synchronous member of the ActionAffordance [ wot-thing-description11 ] is set to true then the Web Thing MUST respond with a Synchronous Action Response .

If the synchronous member of the ActionAffordance [ wot-thing-description11 ] is set to false then the Web Thing MUST respond with an Asynchronous Action Response .

For long-running actions which are not expected to finish executing within the timeout period of an HTTP request (e.g. 30 to 120 seconds), it is RECOMMENDED that a Web Thing respond with an Asynchronous Action Response so that a Consumer may continue to monitor the status of an action request with a queryaction operation on a dynamically created ActionStatus resource, after the initial invokeaction response.

For short-lived actions which are expected to finish executing within the timeout period of an HTTP request, a Web Thing MAY wait until the action has completed to send a Synchronous Action Response.

If a Web Thing encounters an error in attempting to execute an action before responding to the invokeaction request, then it MUST send an Error Response.

Conforming Consumers MUST support all three types of response to the initial invokeaction request. After the initial request, support for subsequent operations on an ActionStatus resource is OPTIONAL .

6.2.2.1.1 ActionStatus object

The status of an asynchronous action invocation request is represented by an ActionStatus object which includes the following members:

Member Description Assignment Type
status The status of the action request. mandatory string (one of pending , running , completed or failed )
output The output data, if any, of a completed action which MUST conform with the output data schema of the corresponding ActionAffordance . optional any type
error An error message, if any, associated with a failed action which MUST use the JSON serialization of the Problem Details format [ RFC7807 ] (only needed in response to a queryaction operation). optional object
href The [ URL ] of an ActionStatus resource which can be used by queryaction and cancelaction operations, the URI scheme [ RFC3986 ] of which MUST resolve to http or https (only needed for an Asynchronous Action Response ). optional string
timeRequested A timestamp indicating the time at which the Thing received the request to execute the action. (See Date Format for date format constraints). optional string
timeEnded A timestamp indicating the time at which the Thing successfully completed executing the action, or failed to execute the action. (See Date Format for date format constraints). optional string
Note

It is possible that a Thing's clock may not be set to the correct time. If timings are important then a Consumer may therefore choose to treat the timeEnded member of an ActionStatus object as being relative to the timeRequested member, but not necessarily as relative to its own internal clock, or the clocks of other Things.

6.2.2.1.2 Synchronous Action Response

If providing a Synchronous Action Response, a Web Thing MUST send an HTTP response with:

  • Status code set to 200
  • Content-Type header set to application/json
  • A body containing the output of the action, if any, serialized in JSON
HTTP/1.1 200 OK

Content-Type

:

application/json

6.2.2.1.3 Asynchronous Action Response

If providing an Asynchronous Action Response, a Web Thing MUST send an HTTP response containing the URL of an ActionStatus resource, the URI scheme [ RFC3986 ] of which MUST resolve to http or https . The response MUST have:

  • Status code set to 201
  • Content-Type header set to application/json
  • Location header set to the URL of the ActionStatus resource
  • A body containing an ActionStatus object serialized in JSON, with its href member set to the URL of the ActionStatus resource
HTTP/1.1 201 CREATED
Content-Type: application/json
Location: /things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655
{
  "status": "pending",
  "href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655",
  "timeRequested": "2021-11-10T11:43:19.135Z"
}

In resource constrained environments, the ActionStatus objects of older completed/failed actions MAY be deleted to make room for newly invoked actions.

A Web Thing SHOULD return a 503 error response if the invocation cannot be accepted because the action is unavailable, e.g. because the Thing is overloaded.

6.2.2.2 queryaction

A queryaction operation is used to query the current state of an ongoing action request.

A Web Thing which provides Asynchronous Action Response s to an invokeaction operation on an Action MUST also support queryaction operations on that same Action . A Web Thing which only provides Synchronous Action Response s to an invokeaction operation on an Action SHOULD NOT support queryaction operations on that same Action .

The URL of an ActionStatus resource to be used in a queryaction operation MUST be obtained from the Location header of an Asynchronous Action Response , or the href member of the ActionStatus object in its body.

In order to query the status of an action request, a Consumer MUST send an HTTP request to a Web Thing with:

  • Method set to GET
  • URL set to the URL of the ActionStatus resource
  • Accept header set to application/json
GET /things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655
Host: mythingserver.com

Accept:


application/json


If a Web Thing receives an HTTP request following the format above and the Consumer has permission to query the corresponding ActionStatus resource, then upon successfully reading the status of the action request it MUST send an HTTP response with:

  • Status code set to 200
  • Content-Type header set to application/json
  • A body containing an ActionStatus object representing the current status of the action request, serialized in JSON
HTTP/1.1 200 OK
Content-Type: application/json
{
  "status": "running",
  "timeRequested": "2021-11-10T11:43:19.135Z"
}

If the queried action failed to execute, then the status member of the ActionStatus object MUST be set to "failed" . If the queried action failed to execute, then the error member MAY provide additional error information conforming to the Problem Details format [ RFC7807 ].

HTTP/1.1 200 OK
Content-Type: application/json
{
  "status": "failed",
  "error": {
    "type": "https://mythingserver.com/docs/errors/invalid-level",
    "title": "Invalid value for level provided",
    "invalid-params": [
      {
        "name": "level",
        "reason": "Must be a valid number between 0 and 100"
      }
    ]
  },
  "timeRequested": "2021-11-10T11:43:19.135Z",
  "timeEnded": "2021-11-10T11:43:20.513Z"
}

6.2.2.3 cancelaction

A cancelaction operation is used to cancel an ongoing Action request.

A Web Thing which provides Asynchronous Action Response s to an invokeaction operation on an Action MAY also support cancelaction operations on that same Action . A Web Thing which only provides Synchronous Action Response s to an invokeaction operation on an Action SHOULD NOT support cancelaction operations on that same Action .

The URL of an ActionStatus resource to be used in a cancelaction operation MUST be obtained from the Location header of an Asynchronous Action Response , or the href member of the ActionStatus object in its body.

In order to cancel an action request, a Consumer MUST send an HTTP request to a Web Thing with:

  • Method set to DELETE
  • URL set to the URL of the ActionStatus resource
DELETE /things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655 HTTP/1.1

Host

:

mythingserver.com

If a Web Thing receives an HTTP request following the format above and the Consumer has permission to cancel the corresponding Action request, then upon successfully cancelling Action it MUST send an HTTP response with:

  • Status code set to 204


HTTP/1.1


204

No
Content

6.2.2.4 queryallactions

The URL of an Actions resource to be used when querying the status of all ongoing action requests MUST be obtained from a Thing Description by locating a Form inside the top level forms member for which:

  • Its op member contains the value queryallactions
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • After defaults have been applied, the value of its contentType member is application/json

The resolved value of the href member MUST then be used as the URL of the Actions resource.

In order to query the status of all ongoing action requests, a Consumer MUST send an HTTP request to a Web Thing with:

  • Method set to GET
  • URL set to the URL of the Actions resource
  • Accept header set to application/json
GET /things/lamp/actions HTTP/1.1
Host: mythingserver.com

Accept

:

application/json

If a Web Thing receives an HTTP request following the format above, then upon successfully retreiving the status of all ongoing action requests to which the Consumer has permission to access, it MUST send an HTTP response with:

  • Status code set to 200
  • Content-Type header set to application/json
  • A body containing an object, keyed by Action name, with the value of each object member being an array of ActionStatus objects representing the action requests, serialized in JSON.

Each array in the result object MUST be sorted in reverse chronological order such that the most recent action request appears first.

HTTP/1.1 200 OK
Content-Type: application/json
{
  "fade": [
    {
      "status": "completed",
      "href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655",
      "timeRequested": "2021-11-10T11:43:19.135Z",
      "timeEnded": "2021-11-10T11:43:20.513Z"
    },
    {
      "status": "failed",
      "href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a456-558329",
      "timeRequested": "2021-11-10T11:42:15.133Z",
      "timeEnded": "2021-11-10T11:42:22.524Z"
    },
    {
      "status": "running",
      "href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a457-434656",
      "timeRequested": "2021-11-10T11:41:53.351Z"
    },
    {
      "status": "pending",
      "href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a457-ea9519",
      "timeRequested": "2021-11-10T11:39:53.651Z"
    }
  ]
}

Note : Retention of ActionStatus objects
When an Action request is cancelled with a cancelaction operation, its ActionStatus object is deleted and need not be retained. For all other Action requests it is assumed that a Web Thing will store the ActionStatus object so that its status may later be queried with a queryaction or queryallactions operation. It is not expected that ActionStatus objects should be retained indefinitely, they may be stored in volatile memory and/or periodically pruned. The length of time for which to retain ActionStatus objects is expected to be implementation-specific and may depend on application-specific requirements or resource constraints.

7. HTTP SSE Profile

This section defines the HTTP SSE Profile, including a Protocol Binding for observing properties and listening for events using Server-Sent Events [ EVENTSOURCE ].

This profile may be used in conjunction with the HTTP Basic Profile in order to provide operations to read and write properties and invoke, query and cancel actions.

In order to conform with the HTTP SSE Profile, Web Things and Consumers MUST also conform with all of the assertions in the Common Constraints section.

7.1 Identifier

In order to denote that a given Web Thing conforms to the HTTP SSE Profile, its Thing Description MUST have a profile member [ wot-thing-description11 ] with a value of https://www.w3.org/2022/wot/profile/http-sse/v1 .

7.2 Protocol Binding

This section defines a protocol binding which describes how a Consumer communicates with a Web Thing [ wot-architecture11 ] using Server-Sent Events [ EVENTSOURCE ].

A Consumer or Web Thing conforming to the HTTP SSE Profile MUST implement this protocol binding.

The examples provided throughout this section describe how a Consumer would communicate with a Web Thing which produces the following Thing Description:

{
  "@context": "https://www.w3.org/2022/wot/td/v1.1",
  "id": "https://mywebthingserver.com/things/lamp",
  "profile": [
    "https://www.w3.org/2022/wot/profile/http-basic/v1",
    "https://www.w3.org/2022/wot/profile/http-sse/v1",
  ],
  "base": "https://mywebthingserver.com/things/lamp/",
  "title": "My Lamp",
  "description": "A web connected lamp",
  "securityDefinitions": {
    "oauth2": {
      "scheme": "oauth2",
      "flow": "code",
      "authorization": "https://mywebthingserver.com/oauth/authorize",
      "token": "https://mywebthingserver.com/oauth/token"
    }
  },
  "security": "oauth2",
  "properties": {
    "on": {
      "type": "boolean",
      "title": "On/Off",
      "description": "Whether the lamp is turned on",
      "forms": [
        {
          "href": "properties/on",
          "op": ["readproperty", "writeproperty"],
        },
        {
          "href": "properties/on",
          "op": ["observeproperty", "unobserveproperty"],
          "subprotocol": "sse"
        }
      ]
    },
    "level" : {
      "type": "integer",
      "title": "Brightness",
      "description": "The level of light from 0-100",
      "unit": "percent",
      "minimum" : 0,
      "maximum" : 100,
      "forms": [
      {
        "href": "properties/level",
        "op": ["readproperty", "writeproperty"],
      },
      {
        "href": "properties/level",
        "op": ["observeproperty", "unobserveproperty"],
        "subprotocol": "sse"
      }
    ]
  },
    }
  },
  "actions": {
    "fade": {
      "title": "Fade",
      "description": "Fade the lamp to a given level",
      "synchronous": false,
      "input": {
        "type": "object",
        "properties": {
          "level": {
            "title": "Brightness",
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "unit": "percent"
          },
          "duration": {
            "title": "Duration",
            "type": "integer",
            "minimum": 0,
            "unit": "milliseconds"
          }
        }
      },
      "forms": [{"href": "actions/fade"}]
    }
  },
  "events": {
    "overheated": {
      "title": "Overheated",
      "data": {
        "type": "number",
        "unit": "degree celsius"
      },
      "description": "The lamp has exceeded its safe operating temperature",
      "forms": [{
        "href": "events/overheated",
        "subprotocol": "sse"
      }]
    }
  },
  "forms": [
    {
      "op": ["readallproperties", "writemultipleproperties"],
      "href": "properties"
    },
    {
      "op": ["observeallproperties", "unobserveallproperties"],
      "href": "properties",
      "subprotocol": "sse"
    },
    {
      "op": "queryallactions",
      "href": "actions"
    },
    {
      "op": ["subscribeallevents", "unsubscribeallevents"],
      "href": "events",
      "subprotocol": "sse"
    }
  ]

}


7.2.1 Properties

7.2.1.1 observeproperty

The URL of a Property resource to be used when observing the value of a property MUST be obtained from a Thing Description by locating a Form inside the corresponding PropertyAffordance for which:

  • Its op member contains the value observeproperty
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • Its subprotocol member has a value of sse
  • After defaults have been applied, the value of its contentType member is application/json

The resolved value of the href member MUST then be used as the URL of the Property resource.

In order to observe a property, a Consumer MUST follow the Server-Sent Events [ EVENTSOURCE ] specification to open a connection with the Web Thing at the URL of the Property resource.

This involves the Consumer sending an HTTP request to the Web Thing with:

  • Method set to GET
  • URL set to the URL of the Property resource
  • Accept header set to text/event-stream
  • Connection header set to keep-alive
GET /things/lamp/properties/level HTTP/1.1
Host: mythingserver.com
Accept: text/event-stream

Connection

:

keep-alive

Note : Opening a connection using JavaScript

For Consumers implemented in JavaScript [ ECMASCRIPT ] and executed in a runtime which exposes the EventSource interface, a Server-Sent Events connection can be initiated using the EventSource constructor.



const

levelSource
=

new


EventSource

(

'/things/lamp/properties/level'

);

If a Web Thing receives an HTTP request following the format above and the Consumer has permission to observe the corresponding property, then it MUST follow the Server-Sent Events [ EVENTSOURCE ] specification to maintain an open connection with the Consumer and push a property value to the Consumer each time the value of the specified property changes.

This involves the Web Thing initially sending an HTTP response to the Consumer with:

  • Status code set to 200
  • Content-Type header set to text/event-stream
HTTP/1.1 200 OK

Content-Type

:

text/event-stream

Whenever the value of the specified property changes while the Web Thing has an open connection with a Consumer, the Web Thing MUST send a property value to the Consumer using the event stream format in the Server-Sent Events [ EVENTSOURCE ] specification. For each message sent, the Web Thing MUST set the event field to the name of the PropertyAffordance and populate the data field with the property value, serialized in JSON and following the data schema specified in the PropertyAffordance . The id field SHOULD be set to a unique identifier for the property change, for use when re-establishing a dropped connection (see below). It is RECOMMENDED that the identifier is a timestamp representing the time at which the property changed (see Date Format for date format constraints).

event: level\n
data: 42\n

id:


2021-11-17T15:33:20.827Z


\n\n


If the connection between the Consumer and Web Thing drops (except as a result of the unobserve operation defined below), the Consumer MUST re-establish the connection following the steps outlined in the Server-Sent Events specification [ EVENTSOURCE ]. Once the connection is re-established the Web Thing SHOULD , if possible, send any missed property changes which occurred since the last change specified by the Consumer in a Last-Event-ID header.

Note : application/json wrapped in text/event-stream

Property values are serialised in JSON and provided in the data field of a Server-Sent Event serialised in text/event-stream format. The text/event-stream content type used in HTTP headers is assumed to be implied by the sse subprotocol, and the embedded application/json content type is indicated in contentType member of the Form (with defaults applied).

7.2.1.2 unobserveproperty

In order to stop observing a property, a Consumer MUST terminate the corresponding Server-Sent Events connection with the Web Thing as specified in the Server-Sent Events specification [ EVENTSOURCE ].

Note : Terminating a connection using JavaScript

For Consumers implemented in JavaScript [ ECMASCRIPT ] and executed in a runtime which exposes the EventSource interface, a Server-Sent Events connection can be terminated using the close() method on an EventSource [ EVENTSOURCE ] object.


levelSource.close()

;


7.2.1.3 observeallproperties

The URL of a properties resource to be used when observing changes to all properties of a Web Thing MUST be obtained from a Thing Description by locating a Form inside the top level forms member of a Thing Description for which:

  • Its op member contains the value observeallproperties
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • Its subprotocol member has a value of sse
  • After defaults have been applied, the value of its contentType member is application/json

The resolved value of the href member MUST then be used as the URL of the properties resource.

In order to observe changes to all properties of a Web Thing, a Consumer MUST follow the Server-Sent Events [ EVENTSOURCE ] specification to open a connection with the Web Thing at the URL of the properties resource.

This involves the Consumer sending an HTTP request to the Web Thing with:

  • Method set to GET
  • URL set to the URL of the properties resource
  • Accept header set to text/event-stream
  • Connection header set to keep-alive
GET /things/lamp/properties HTTP/1.1
Host: mythingserver.com
Accept: text/event-stream

Connection

:

keep-alive

Note : Opening a connection using JavaScript

For Consumers implemented in JavaScript [ ECMASCRIPT ] and executed in a runtime which exposes the EventSource interface, a Server-Sent Events connection can be initiated using the EventSource constructor.



const

lampPropertiesSource
=

new


EventSource

(

'/things/lamp/properties'

);

If a Web Thing receives an HTTP request following the format above then it MUST follow the Server-Sent Events [ EVENTSOURCE ] specification to maintain an open connection with the Consumer and push new property values to the Consumer for all properties for which it has permission to observe.

This involves the Web Thing initially sending an HTTP response to the Consumer with:

  • Status code set to 200
  • Content-Type header set to text/event-stream
HTTP/1.1 200 OK

Content-Type

:

text/event-stream

Whenever a property changes while the Web Thing has an open connection with a Consumer, the Web Thing MUST send the new property value to the Consumer using the event stream format in the Server-Sent Events [ EVENTSOURCE ] specification. For each message sent, the Web Thing MUST set the event field to the name of the PropertyAffordance and populate the data field with the new property value. The property data MUST follow the data schema specified in the PropertyAffordance and MUST be serialized in JSON. The id field SHOULD be set to a unique identifier for the event, for use when re-establishing a dropped connection (see below). It is RECOMMENDED that the identifier is a timestamp representing the time at which the property changed (see Date Format for date format constraints).

event: level\n
data: 42\n

id:


2021-11-17T15:33:20.827Z


\n\n


If the connection between the Consumer and Web Thing drops (except as a result of the unobserveallproperties operation defined below), the Consumer MUST re-establish the connection following the steps outlined in the Server-Sent Events specification [ EVENTSOURCE ]. Once the connection is re-established the Web Thing SHOULD , if possible, send any missed property changes which occurred since the last change specified by the Consumer in a Last-Event-ID header.

Note : application/json wrapped in text/event-stream

Property values are serialised in JSON and provided in the data field of a Server-Sent Event serialised in text/event-stream format. The text/event-stream content type used in HTTP headers is assumed to be implied by the sse subprotocol, and the embedded application/json content type is indicated in contentType member of the Form (with defaults applied).

7.2.1.4 unobserveallproperties

In order to unobserve all properties, a Consumer MUST terminate the corresponding Server-Sent Events connection with the properties endpoint of the Web Thing, following the steps specified in the Server-Sent Events specification [ EVENTSOURCE ].

Note : Terminating a connection using JavaScript

For Consumers implemented in JavaScript [ ECMASCRIPT ] and executed in a runtime which exposes the EventSource interface, a Server-Sent Events connection can be terminated using the close() method on an EventSource [ EVENTSOURCE ] object.


lampPropertiesSource.close()

;


7.2.2 Events

The HTTP SSE Profile uses Server-Sent Events [ EVENTSOURCE ] as a mechanism for Consumers to subscribe to events emitted by a Web Thing.

Note

Consumers are not required to implement the EventSource JavaScript API from the Server-Sent Events specification in order to conform with this profile. Any programming language may be used to consume an event stream.

7.2.2.1 subscribeevent

The URL of an Event resource to be used when subscribing to an event MUST be obtained from a Thing Description by locating a Form inside the corresponding EventAffordance for which:

  • After defaults have been applied, its op member contains the value subscribeevent
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • Its subprotocol member has a value of sse
  • After defaults have been applied, the value of its contentType member is application/json

The resolved value of the href member MUST then be used as the URL of the Event resource.

In order to subscribe to an event, a Consumer MUST follow the Server-Sent Events [ EVENTSOURCE ] specification to open a connection with the Web Thing at the URL of the Event resource.

This involves the Consumer sending an HTTP request to the Web Thing with:

  • Method set to GET
  • URL set to the URL of the Event resource
  • Accept header set to text/event-stream
  • Connection header set to keep-alive
GET /things/lamp/events/overheated HTTP/1.1
Host: mythingserver.com
Accept: text/event-stream

Connection

:

keep-alive

Note : Opening a connection using JavaScript

For Consumers implemented in JavaScript [ ECMASCRIPT ] and executed in a runtime which exposes the EventSource interface, a Server-Sent Events connection can be initiated using the EventSource constructor.



const

overheatedEventSource
=

new


EventSource

(

'/things/lamp/events/overheated'

);

If a Web Thing receives an HTTP request following the format above and the Consumer has permission to subscribe to the corresponding event, then it MUST follow the Server-Sent Events [ EVENTSOURCE ] specification to maintain an open connection with the Consumer and push event data to the Consumer as events of the specified type are emitted.

This involves the Web Thing initially sending an HTTP response to the Consumer with:

  • Status code set to 200
  • Content-Type header set to text/event-stream
HTTP/1.1 200 OK

Content-Type

:

text/event-stream

Whenever an event of the specified type occurs while the Web Thing has an open connection with a Consumer, the Web Thing MUST send event data to the Consumer using the event stream format in the Server-Sent Events [ EVENTSOURCE ] specification. For each message sent, the Web Thing MUST set the event field to the name of the EventAffordance and populate the data field with event data, if any. The event data MUST follow the data schema specified in the EventAffordance and be serialized in JSON. The id field SHOULD be set to a unique identifier for the event, for use when re-establishing a dropped connection (see below). It is RECOMMENDED that the identifier is a timestamp representing the time at which the event ocurred (see Date Format for date format constraints).

event: overheated\n
data: 90\n

id:


2021-11-16T16:53:50.817Z


\n\n


If the connection between the Consumer and Web Thing drops (except as a result of the unsubscribeevent operation defined below), the Consumer MUST re-establish the connection following the steps outlined in the Server-Sent Events specification [ EVENTSOURCE ]. Once the connection is re-established the Web Thing SHOULD , if possible, send any missed events which occurred since the last event specified by the Consumer in a Last-Event-ID header.

Note : application/json wrapped in text/event-stream

Event payloads are serialised in JSON and provided in the data field of a Server-Sent Event serialised in text/event-stream format. The text/event-stream content type used in HTTP headers is assumed to be implied by the sse subprotocol, and the embedded application/json content type is indicated in contentType member of the Form (with defaults applied).

7.2.2.2 unsubscribeevent

In order to unsubscribe from an event, a Consumer MUST terminate the corresponding Server-Sent Events connection with the Web Thing as specified in the Server-Sent Events specification [ EVENTSOURCE ].

Note : Terminating a connection using JavaScript

For Consumers implemented in JavaScript [ ECMASCRIPT ] and executed in a runtime which exposes the EventSource interface, a Server-Sent Events connection can be terminated using the close() method on an EventSource [ EVENTSOURCE ] object.


overheatedEventSource.close()

;


7.2.2.3 subscribeallevents

The URL of an events resource to be used when subscribing to all events emitted by a Web Thing MUST be obtained from a Thing Description by locating a Form inside the top level forms member of a Thing Description for which:

  • Its op member contains the value subscribeallevents
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • Its subprotocol member has a value of sse
  • After defaults have been applied, the value of its contentType member is application/json

The resolved value of the href member MUST then be used as the URL of the events resource.

In order to subscribe to all events emitted by a Web Thing, a Consumer MUST follow the Server-Sent Events [ EVENTSOURCE ] specification to open a connection with the Web Thing at the URL of the events resource.

This involves the Consumer sending an HTTP request to the Web Thing with:

  • Method set to GET
  • URL set to the URL of the events resource
  • Accept header set to text/event-stream
  • Connection header set to keep-alive
GET /things/lamp/events HTTP/1.1
Host: mythingserver.com
Accept: text/event-stream

Connection

:

keep-alive

Note : Opening a connection using JavaScript

For Consumers implemented in JavaScript [ ECMASCRIPT ] and executed in a runtime which exposes the EventSource interface, a Server-Sent Events connection can be initiated using the EventSource constructor.



const

lampEventsSource
=

new


EventSource

(

'/things/lamp/events'

);

If a Web Thing receives an HTTP request following the format above then it MUST follow the Server-Sent Events [ EVENTSOURCE ] specification to maintain an open connection with the Consumer and push event data to the Consumer for all event types for which it has permission to subscribe.

This involves the Web Thing initially sending an HTTP response to the Consumer with:

  • Status code set to 200
  • Content-Type header set to text/event-stream
HTTP/1.1 200 OK

Content-Type

:

text/event-stream

Whenever an event occurs while the Web Thing has an open connection with a Consumer, the Web Thing MUST send event data to the Consumer using the event stream format in the Server-Sent Events [ EVENTSOURCE ] specification. For each message sent, the Web Thing MUST set the event field to the name of the EventAffordance and populate the data field with event data, if any. The event data MUST follow the data schema specified in the EventAffordance and be serialized in JSON. The id field SHOULD be set to a unique identifier for the event, for use when re-establishing a dropped connection (see below). It is RECOMMENDED that the identifier is a timestamp representing the time at which the event ocurred (see Date Format for date format constraints).

event: overheated\n
data: 90\n

id:


2021-11-16T16:53:50.817Z


\n\n


If the connection between the Consumer and Web Thing drops (except as a result of the unsubscribeallevents operation defined below), the Consumer MUST re-establish the connection following the steps outlined in the Server-Sent Events specification [ EVENTSOURCE ]. Once the connection is re-established the Web Thing SHOULD , if possible, send any missed events which occurred since the last event specified by the Consumer in a Last-Event-ID header.

Note : application/json wrapped in text/event-stream

Event payloads are serialised in JSON and provided in the data field of a Server-Sent Event serialised in text/event-stream format. The text/event-stream content type used in HTTP headers is assumed to be implied by the sse subprotocol, and the embedded application/json content type is indicated in contentType member of the Form (with defaults applied).

7.2.2.4 unsubscribeallevents

In order to unsubscribe from all events, a Consumer MUST terminate the corresponding Server-Sent Events connection with the events endpoint of the Web Thing, following the steps specified in the Server-Sent Events specification [ EVENTSOURCE ].

Note : Terminating a connection using JavaScript

For Consumers implemented in JavaScript [ ECMASCRIPT ] and executed in a runtime which exposes the EventSource interface, a Server-Sent Events connection can be terminated using the close() method on an EventSource [ EVENTSOURCE ] object.


lampEventsSource.close()

;


8. HTTP Webhook Profile

This section defines the HTTP Webhook Profile, including a Protocol Binding for observing properties and listening for events using Webhooks .

The HTTP Webhook profile MAY be used in conjunction with the HTTP Basic Profile in order to provide operations to read and write properties and invoke, query and cancel actions.

The HTTP Webhook profile MAY be used as an alternative event mechanism to the HTTP SSE Profile .

In order to conform with the HTTP Webhook Profile, Web Things and Consumers MUST also conform with all of the assertions in the Common Constraints section.

Note : HTTP client and server roles

In order to implement the HTTP Webhook profile it must be possible for both the Thing and Consumer to act as both an HTTP client and HTTP server, accessible by each other over a network. This may not be possible in all deployment scenarios.

8.1 Identifier

In order to denote that a given Web Thing conforms to the HTTP Webhook Profile, its Thing Description MUST have a profile member [ wot-thing-description11 ] with a value of https://www.w3.org/2022/wot/profile/http-webhook/v1 .

Note

Note that the profile member is an array that may contain multiple profile entries, which indicates that a Web Thing conforms to all of the profiles in that array.

8.2 Protocol Binding

This section defines a protocol binding which describes how a Consumer and a Web Thing communicate using Webhooks.

A Consumer or Web Thing conforming to the HTTP Webhook Profile MUST implement this protocol binding.

The examples provided throughout this section describe how a Consumer would communicate with a Web Thing which produces the following Thing Description [ wot-thing-description11 ]:

Example 44 : HTTP Webhook Profile Example Thing Description
{
  "@context": "https://www.w3.org/2022/wot/td/v1.1",
  "id": "https://mywebthingserver.com/things/lamp",
  "profile": [
    "https://www.w3.org/2022/wot/profile/http-webhook/v1",
  ],
  "base": "https://mywebthingserver.com/things/lamp/",
  "title": "My Lamp",
  "description": "A web connected lamp",
  "securityDefinitions": {
    "oauth2": {
      "scheme": "oauth2",
      "flow": "code",
      "authorization": "https://mywebthingserver.com/oauth/authorize",
      "token": "https://mywebthingserver.com/oauth/token"
    }
  },
  "security": "oauth2",
  "properties": {
    "on": {
      "type": "boolean",
      "title": "On/Off",
      "description": "Whether the lamp is turned on",
      "forms": [
        {
          "op": "observeproperty",
          "href": "properties/on",
          "subprotocol": "webhook",
          "contentType": "application/json",
          "htv:methodName": "POST"
        },
        {
          "op": "unobserveproperty",
          "href": "properties/on/{subscriptionID}",
          "subprotocol": "webhook",
          "htv:methodName": "DELETE"
        }
      ]
    },
    "level" : {
      "type": "integer",
      "title": "Brightness",
      "description": "The level of light from 0-100",
      "unit": "percent",
      "minimum" : 0,
      "maximum" : 100,
      "forms": [
        {
          "op": "observeproperty",
          "href": "properties/level",
          "subprotocol": "webhook",
          "contentType": "application/json",
          "htv:methodName": "POST"
        },
        {
          "op": "unobserveproperty",
          "href": "properties/level/{subscriptionID}",
          "subprotocol": "webhook",
          "htv:methodName": "DELETE"
        }
      ]
    },
  },
  "events": {
    "overheated": {
      "title": "Overheated",
      "data": {
        "type": "number",
        "unit": "degree celsius"
      },
      "description": "The lamp has exceeded its safe operating temperature",
      "subscription": {
        "type": "object",
        "properties": {
          "callbackURL": {
            "type": "string",
            "format": "uri",
            "description": "Callback URL provided by subscriber for Webhook notifications."
          }
        }
      }
      "forms": [
        {
          "op": "subscribeevent",
          "href": "events/overheated",
          "subprotocol": "webhook",
          "contentType": "application/json",
          "htv:methodName": "POST"
        },
        {
          "op": "unsubscribeevent",
          "href": "events/overheated/{subscriptionID}",
          "subprotocol": "webhook",
          "htv:methodName": "DELETE"
        }
      ]
    }
  },
  "forms": [
    {
      "op": "observeallproperties",
      "href": "properties",
      "subprotocol": "webhook",
      "htv:methodName": "POST"
    },
    {
      "op": "unobserveallproperties",
      "href": "properties/{subscriptionID}",
      "suprotocol": "webhook",
      "htv:methodName": "DELETE"
    },
    {
      "op": "subscribeallevents",
      "href": "events",
      "subprotocol": "webhook",
      "htv:methodName": "POST"
    },
    {
      "op": "unsubscribeallevents",
      "href": "events/{subscriptionID}",
      "suprotocol": "webhook",
      "htv:methodName": "DELETE"
    }
  ]

}


8.2.1 Properties

8.2.1.1 observeproperty

The URL of a Property resource to be used when observing the value of a property MUST be obtained from a Thing Description [ wot-thing-description11 ] by locating a Form inside the corresponding PropertyAffordance for which:

  • Its op member contains the value observeproperty
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • Once defaults have been applied, its contentType member has a value of application/json
  • Its subprotocol member has a value of webhook

The resolved value of the href member MUST then be used as the URL of the Property resource.

In order to observe a property, a Consumer MUST send an HTTP request to the Web Thing with:

  • Method set to POST
  • URL set to the URL of the Property resource
  • Content-Type header set to application/json
  • A body containing a JSON object with the following members:
    • A callbackURL member set to a callback URL the Thing should use to send property change notifications to the Consumer.
Example 45 : Observe property request
POST /things/lamp/properties/level HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
{
  callbackURL: "https://myconsumer.com/listeners/d629c54e-a919-463b-8680-602a21f91fe9"
}

If a Web Thing receives an HTTP request following the format above and the Consumer has permission to observe the corresponding property, then upon successfully registering a callback URL it MUST send an HTTP response to the Consumer with:

  • Status code set to 201 Created
  • Location header set to a unique URL representing the individual property observation subscription, for use by the Consumer when later cancelling the observation of the Property.
Example 46 : Observe property response
HTTP/1.1 201 Created

Location

:

/things/properties/level/74353483-3997-437a-a4f5-84d03784e517

Whilst the Property observation subscription is registered, whenever a change in the value of the observed property occurs, the Web Thing MUST send an HTTP request to the observing Consumer with:

  • Method set to POST
  • URL set to the callback URL provided by the Consumer when registering the observation
  • Content-Type header set to application/json
  • A Link header with the URL set to the URL of the corresponding Property Affordance, and rel set to self
  • A Date header automatically set to the time of the property change by the user agent, using the HTTP Date format from [ rfc9110 ]
  • A body containing the new value of the property, serialised in JSON and conforming to the data schema of the Property Affordance
Example 47 : Property change notification request
POST /listeners/d629c54e-a919-463b-8680-602a21f91fe9 HTTP/1.1
Host: myconsumer.com
Date: Fri, 4 Jul 2025 12:48:00 GMT
Content-type: application/json
Link: <https://mythingserver.com/things/mylamp1/properties/level>; rel="self"

90


When a Consumer receives an HTTP request following the format above to a valid callback URL, it MUST send an HTTP response to the Web Thing with:

  • Status code set to 200 OK
Example 48 : Property change notification response


HTTP/1.1


200

OK

8.2.1.2 unobserveproperty

In order to cancel the observation subscription of a property, a Consumer MUST send an HTTP request to the Web Thing with:

  • Method set to DELETE
  • URL set to the subscription URL provided in the Location header of the HTTP response during the observeproperty operation
Example 49 : Unobserve property request
DELETE /things/properties/level/74353483-3997-437a-a4f5-84d03784e517 HTTP/1.1 

Host:


mythingserver.com


If a Web Thing receives an HTTP request following the format above, and a property observation subscription exists with the provided URL, then upon successfully cancelling the subscription the Web Thing MUST send an HTTP response to the Consumer with:

  • Status code set to 204 No Content
Example 50 : Unobserve property response


HTTP/1.1


204

No
Content

8.2.1.3 observeallproperties

The URL of a Properties resource to be used when observing the values of all properties of a Web Thing MUST be obtained from a Thing Description [ wot-thing-description11 ] by locating a Form inside the top level forms member of a Thing Description for which:

  • Its op member contains the value observeallproperties
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • Once defaults have been applied, its contentType member has a value of application/json
  • Its subprotocol member has a value of webhook

The resolved value of the href member MUST then be used as the URL of the Properties resource.

In order to observe changes to all Properties of a Web Thing , a Consumer MUST send an HTTP request to the Web Thing with:

  • Method set to POST
  • URL set to the URL of the properties resource
  • Content-Type header set to application/json
  • A body containing a JSON object with the following members:
    • A callbackURL member set to a callback URL the Thing should use to send property change notifications to the Consumer.
Example 51 : Observe all properties request
POST /things/lamp/properties HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
{
  callbackURL: "https://myconsumer.com/listeners/aa2d8e1f-dc6a-4fe0-a5c0-a42d9f532699"
}

If a Web Thing receives an HTTP request following the format above and the Consumer has permission to observe properties of the Thing, then upon successfully registering a callback URL it MUST send an HTTP response to the Consumer with:

  • Status code set to 201 Created
  • Location header set to a unique URL representing the individual observation subscription, for use by the Consumer when later cancelling the observation of all properties.
Example 52 : Observe all properties response
HTTP/1.1 201 Created

Location

:

/things/properties/a84fc5df-2667-4db2-a767-feb4640f2cf7

Whilst the Properties observation subscription is registered, whenever a change in the value of any observeable property occurs, the Web Thing MUST send an HTTP request to the observing Consumer with:

  • Method set to POST
  • URL set to the callback URL provided by the Consumer when registering the observation subscription
  • Content-Type header set to application/json
  • A Link header with the URL set to the URL of the corresponding Property Affordance, and rel set to self
  • A Date header automatically set to the time of the property change by the user agent, using the HTTP Date format from [ rfc9110 ]
  • A body containing the new value of the property, serialised in JSON and conforming to the data schema of the Property Affordance
Example 53 : Property change notification request
POST /listeners/aa2d8e1f-dc6a-4fe0-a5c0-a42d9f532699 HTTP/1.1
Host: myconsumer.com
Date: Fri, 4 Jul 2025 12:56:00 GMT
Content-type: application/json
Link: <https://mythingserver.com/things/mylamp1/properties/level>; rel="self"

86


When a Consumer receives an HTTP request following the format above to a valid callback URL, it MUST send an HTTP response to the Web Thing with:

  • Status code set to 200 OK
Example 54 : Property change notification response


HTTP/1.1


200

OK

8.2.1.4 unobserveallproperties

In order to cancel the observation of all properties, a Consumer MUST send an HTTP request to the Web Thing with:

  • Method set to DELETE
  • URL set to the subscription URL provided in the Location header of the HTTP response during the observeallproperties operation
Example 55 : Unobserve all properties request
DELETE /things/properties/a84fc5df-2667-4db2-a767-feb4640f2cf7 HTTP/1.1 

Host:


mythingserver.com


If a Web Thing receives an HTTP request following the format above, and a properties observation subscription exists with the provided URL, then upon successfully cancelling the observation subscription the Web Thing MUST send an HTTP response to the Consumer with:

  • Status code set to 204 No Content
Example 56 : Unobserve all properties response


HTTP/1.1


204

No
Content

8.2.2 Events

8.2.2.1 subscribeevent

The URL of an Event resource to be used when subscribing to an event MUST be obtained from a Thing Description [ wot-thing-description11 ] by locating a Form inside the corresponding EventAffordance for which:

  • Its op member contains the value subscribeevent
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • Once defaults have been applied, its contentType member has a value of application/json
  • Its subprotocol member has a value of webhook

The resolved value of the href member MUST then be used as the URL of the Event resource.

In order to subscribe to an event, a Consumer MUST send an HTTP request to the Web Thing with:

  • Method set to POST
  • URL set to the URL of the Event resource
  • Content-Type header set to application/json
  • A body containing a JSON object with the following members:
    • A callbackURL member set to a callback URL the Thing should use to send event notifications to the Consumer .
Example 57 : Subscribe event request
POST /things/lamp/events/overheated HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
{
  callbackURL: "https://myconsumer.com/listeners/e79dd0a5-4537-4ded-a10f-bb4eb2aca28d"
}

If a Web Thing receives an HTTP request following the format above and the Consumer has permission to subscribe to the corresponding event, then upon successfully registering a callback URL it MUST send an HTTP response to the Consumer with:

  • Status code set to 201 Created
  • Location header set to a unique URL representing the individual event subscription, for use by the Consumer when later cancelling the subscription.
Example 58 : Subscribe event response
HTTP/1.1 201 Created

Location

:

/things/events/overheated/ce527faa-a5ab-4f03-8f85-e4411d13edb5

Whilst the Event subscription is registered, whenever an instance of the monitored event occurs, the Web Thing MUST send an HTTP request to the subscribed Consumer with:

  • Method set to POST
  • URL set to the callback URL provided by the Consumer when subscribing to the event
  • Content-Type header set to application/json
  • A Link header with the URL set to the URL of the corresponding Event Affordance, and rel set to self
  • A Date header automatically set to the time the event occurred by the user agent, using the HTTP Date format from [ rfc9110 ]
  • A body containing the data payload of the event, if any, serialised in JSON and conforming to the data schema of the Event Affordance

If the event does not include a data payload then the Content-type header of the request SHOULD NOT be set, and the body should be empty.

Example 59 : Event notification request
POST /listeners/e79dd0a5-4537-4ded-a10f-bb4eb2aca28d HTTP/1.1
Host: myconsumer.com
Date: Fri, 4 Jul 2025 16:46:00 GMT
Content-type: application/json
Link: <https://mythingserver.com/things/mylamp1/events/overheated>; rel="self"

90


When a Consumer receives an HTTP request following the format above to a valid callback URL, it MUST send an HTTP response to the Web Thing with:

  • Status code set to 200 OK
Example 60 : Event notification response


HTTP/1.1


200

OK

8.2.2.2 unsubscribeevent

In order to cancel the subscription to an event, a Consumer MUST send an HTTP request to the Web Thing with:

  • Method set to DELETE
  • URL set to the subscription URL provided in the Location header of the HTTP response during the subscribeevent operation
Example 61 : Unsubscribe event request
DELETE /things/events/overheated/ce527faa-a5ab-4f03-8f85-e4411d13edb5 HTTP/1.1 

Host:


mythingserver.com


If a Web Thing receives an HTTP request following the format above, and an event subscription exists with the provided URL, then upon successfully cancelling the subscription the Web Thing MUST send an HTTP response to the Consumer with:

  • Status code set to 204 No Content
Example 62 : Unsubscribe event response


HTTP/1.1


204

No
Content

8.2.2.3 subscribeallevents

The URL of an Events resource to be used when subscribing to all events of a Web Thing MUST be obtained from a Thing Description [ wot-thing-description11 ] by locating a Form inside the top level forms member of the Thing Description for which:

  • Its op member contains the value subscribeallevents
  • After being resolved against a base URL where applicable, the URI scheme [ RFC3986 ] of the value of its href member is http or https
  • Once defaults have been applied, its contentType member has a value of application/json
  • Its subprotocol member has a value of webhook

The resolved value of the href member MUST then be used as the URL of the Events resource.

In order to subscribe to all Events of a Web Thing , a Consumer MUST send an HTTP request to the Web Thing with:

  • Method set to POST
  • URL set to the URL of the events resource
  • Content-Type header set to application/json
  • A body containing a JSON object with the following members:
    • A callbackURL member set to a callback URL the Thing should use to send event notifications to the Consumer .
Example 63 : Subscribe all events request
POST /things/lamp/events HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
{
  callbackURL: "https://myconsumer.com/listeners/bdd2aa13-387b-4c97-9725-52294a9fa5a9"
}

If a Web Thing receives an HTTP request following the format above and the Consumer has permission to subscribe to events of the Thing, then upon successfully registering a callback URL it MUST send an HTTP response to the Consumer with:

  • Status code set to 201 Created
  • Location header set to a unique URL representing the individual event subscription, for use by the Consumer when later cancelling the subscription.
Example 64 : Subscribe all events response
HTTP/1.1 201 Created

Location

:

/things/events/929dbb69-eb66-46df-a0fe-93701d82e7ea

Whilst the Events subscription is registered, whenever an event occurs, the Web Thing MUST send an HTTP request to the subscribed Consumer with:

  • Method set to POST
  • URL set to the callback URL provided by the Consumer when registering the subscription
  • Content-Type header set to application/json
  • A Link header with the URL set to the URL of the corresponding Event Affordance, and rel set to self
  • A Date header automatically set to the time the event occurred by the user agent, using the HTTP Date format from [ rfc9110 ]
  • A body containing the event data payload, if any, serialised in JSON and conforming to the data schema of the Event Affordance

If the event does not include a data payload then the Content-type header of the request SHOULD NOT be set, and the body should be empty.

Example 65 : Event notification request
POST /listeners/bdd2aa13-387b-4c97-9725-52294a9fa5a9 HTTP/1.1
Host: myconsumer.com
Date: Fri, 4 Jul 2025 17:04:00 GMT
Content-type: application/json
Link: <https://mythingserver.com/things/mylamp1/events/overheated>; rel="self"

86


When a Consumer receives an HTTP request following the format above to a valid callback URL, it MUST send an HTTP response to the Web Thing with:

  • Status code set to 200 OK
Example 66 : Event notification response


HTTP/1.1


200

OK

8.2.2.4 unsubscribeallevents

In order to cancel the subscription to all events, a Consumer MUST send an HTTP request to the Web Thing with:

  • Method set to DELETE
  • URL set to the subscription URL provided in the Location header of the HTTP response during the subscribeallevents operation
Example 67 : Unsubscribe all events request
DELETE /things/events/929dbb69-eb66-46df-a0fe-93701d82e7ea HTTP/1.1 

Host:


mythingserver.com


If a Web Thing receives an HTTP request following the format above, and an events subscription exists with the provided URL, then upon successfully cancelling the events subscription the Web Thing MUST send an HTTP response to the Consumer with:

  • Status code set to 204 No Content
Example 68 : Unsubscribe all events response


HTTP/1.1


204

No
Content

9. Privacy Considerations

The privacy considerations of the WoT Architecture [ wot-architecture11 ] and WoT Thing Description [ wot-thing-description11 ] specifications SHOULD be taken into account.

Note

Please also see WoT Security and Privacy Guidelines [ wot-security ] for implementation advice.

10. Security Considerations

The security considerations of the WoT Architecture [ wot-architecture11 ] and WoT Thing Description [ wot-thing-description11 ] specifications SHOULD be taken into account.

Note

Please also see WoT Security and Privacy Guidelines [ wot-security ] for implementation advice.

11. Accessibility Considerations

The values of title and description members at all levels of a Thing Description may be used to generate a user interface and SHOULD therefore be human readable strings which can also be rendered by assistive technologies when necessary.

A. Recent Specification Changes

A.1 Changes from the FPWD published 24 November 2020

B. References

B.1 Normative references

[EVENTSOURCE]
Server-Sent Events . Ian Hickson. W3C. 28 January 2021. W3C Recommendation. URL: https://www.w3.org/TR/eventsource/
[HTTP11]
Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing . R. Fielding, Ed.; J. Reschke, Ed. IETF. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7230.html
[JSON]
The JavaScript Object Notation (JSON) Data Interchange Format . T. Bray, Ed. IETF. December 2017. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc8259
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels . S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC3339]
Date and Time on the Internet: Timestamps . G. Klyne; C. Newman. IETF. July 2002. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc3339
[RFC3986]
Uniform Resource Identifier (URI): Generic Syntax . T. Berners-Lee; R. Fielding; L. Masinter. IETF. January 2005. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc3986
[RFC7807]
Problem Details for HTTP APIs . M. Nottingham; E. Wilde. IETF. March 2016. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc7807
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words . B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[rfc9110]
HTTP Semantics . R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed. IETF. June 2022. Internet Standard. URL: https://httpwg.org/specs/rfc9110.html
[URL]
URL Standard . Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
[wot-architecture11]
Web of Things (WoT) Architecture 1.1 . Michael Lagally; Ryuichi Matsukura; Kunihiko Toumura; Michael McCool. W3C. 5 December 2023. W3C Recommendation. URL: https://www.w3.org/TR/wot-architecture11/
[wot-discovery]
Web of Things (WoT) Discovery . Kunihiko Toumura; Michael McCool; Andrea Cimmino; Farshid Tavakolizadeh. W3C. 5 December 2023. W3C Recommendation. URL: https://www.w3.org/TR/wot-discovery/
[wot-thing-description11]
Web of Things (WoT) Thing Description 1.1 . Sebastian Käbisch; Michael McCool; Ege Korkan. W3C. 5 December 2023. W3C Recommendation. URL: https://www.w3.org/TR/wot-thing-description11/
[wot-usecases]
Web of Things (WoT): Use Cases and Requirements . Michael Lagally; Michael McCool; Ryuichi Matsukura; Tomoaki Mizushima. W3C. 7 March 2022. W3C Working Group Note. URL: https://www.w3.org/TR/wot-usecases/

B.2 Informative references

[ECMASCRIPT]
ECMAScript Language Specification . Ecma International. URL: https://tc39.es/ecma262/multipage/
[H2020-CREATE-IoT]
H2020 – CREATE-IoT Project - Recommendations for commonalities and interoperability profiles of IoT platforms . IoT European Large-Scale Pilots Programme. 2018-11. Published. URL: https://european-iot-pilots.eu/wp-content/uploads/2018/11/D06_02_WP06_H2020_CREATE-IoT_Final.pdf
[WOT-ARCHITECTURE]
Web of Things (WoT) Architecture . Matthias Kovatsch; Ryuichi Matsukura; Michael Lagally; Toru Kawaguchi; Kunihiko Toumura; Kazuo Kajimoto. W3C. 9 April 2020. W3C Recommendation. URL: https://www.w3.org/TR/wot-architecture/
[wot-security]
Web of Things (WoT) Security and Privacy Guidelines . Elena Reshetova; Michael McCool. W3C. 6 November 2019. W3C Working Group Note. URL: https://www.w3.org/TR/wot-security/