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.
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.
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.
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.
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.
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.
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.
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.
A device or consumer implementation complies with this specification if it follows the normative statements in the present document.
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.
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", ... }
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.
The following sections are applicable for profiles defined by this document.
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.
Unless otherwise specified, all date and time values MUST use the
date-time
format defined in [[RFC3339]].
2022-09-21T23:20:50.52Z
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.
Below is a list of security schemes [[wot-thing-description11]] which conformant Web Things MAY use:
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.
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]].
links
member
that provide hyperlinks to other web resources. This section defines specific combinations of
rel
and type
members of a Link which conformant Consumers
are expected to interpret in a particular way.
rel | type | Meaning |
---|---|---|
icon |
image/* |
An icon representing the Thing |
alternate |
text/html |
A user interface to interact with the Thing |
service-doc |
text/plain or text/html or text/pdf |
A user manual for the Thing |
item |
application/td+json |
The target Thing is a component of this Thing or a member of a collection of Things that this Thing represents |
collection |
application/td+json |
This Thing is a component of the target Thing or a group of Things that the target Thing represents |
If a Consumer encounters a link with "rel": "icon" and "type": "image/*" and it is capable of rendering images in the provided format, then it SHOULD interpret the link as an icon for the Thing and display it to the user.
If a Consumer encounters a link with "rel": "alternate" and "type": "text/html" and it is capable of rendering an HTML page and accepting user input, then it SHOULD interpret the link as a user interface for the Thing and provide a means for the user to follow that link and view and interact with the HTML page.
If a Consumer encounters a link with "rel": "service-doc" and "type": "text/plain", "type": "text/html" or "type": "text/pdf", and is capable of rendering documents in the provided format, then it SHOULD interpret the link as a user manual for the Thing and provide a means for the user to follow that link and read the user manual.
If a Consumer encounters a link with "rel": "item" and "type": "application/td+json" and is capable of rendering a hierarchical tree of Things, then it should interpret the link as an indication that the target is a sub-Thing of the current Thing and render this in a meaningful way to the user.
If a Consumer encounters a link with "rel": "collection" and "type": "application/td+json" and is capable of rendering a hierarchical tree of Things, then it should interpret the link as an indication that the target describes a Thing (e.g. a group, system of Things or Thing Directory) which contains the current Thing and render this in a meaningful way to the user.
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]].
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.
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
.
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" } ] }
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:
op
member
contains the value readproperty
href
member is http
or https
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:
GET
Property
resourceAccept
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:
200
Content-Type
header set to application/json
HTTP/1.1 200 OK Content-Type: application/json false
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:
op
member
contains the value writeproperty
href
member is http
or https
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:
PUT
Property
resourceContent-Type
header set to application/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:
204
HTTP/1.1 204 No Content
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:
op
member contains the value
readallproperties
href
member is http
or https
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:
GET
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:
200
Content-Type
header set to application/json
HTTP/1.1 200 OK Content-Type: application/json { "on": false, "level": 100 }
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:
op
member contains the value
writemultipleproperties
href
member is http
or https
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:
PUT
Properties
resource
Content-Type
header set to application/json
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:
204
HTTP/1.1 204 No Content
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
.
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:
op
member is invokeaction
href
member is http
or https
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:
POST
Action
resourceAccept
header set to application/json
Content-Type
header set to application/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:
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.
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 |
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.
If providing a Synchronous Action Response, a Web Thing MUST send an HTTP response with:
200
Content-Type
header set to
application/json
HTTP/1.1 200 OK Content-Type: application/json
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:
201
Content-Type
header set to
application/json
Location
header set to the URL of the
ActionStatus
resource
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.
queryaction
A queryaction
operation is used to query the current
state of an ongoing action request.
A Web Thing which provides
Asynchronous Action Responses to an invokeaction
operation on an Action
MUST also support
queryaction
operations on
that same Action
.
A Web Thing which only provides
Synchronous Action Responses 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:
GET
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:
200
Content-Type
header set to application/json
ActionStatus
object
representing the current status of the action request, serialized
in JSONHTTP/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" }
cancelaction
A cancelaction
operation is used to cancel an ongoing
Action
request.
A Web Thing which provides
Asynchronous Action Responses to an invokeaction
operation on an Action
MAY also support
cancelaction
operations on
that same Action
.
A Web Thing which only provides
Synchronous Action Responses 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:
DELETE
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:
204
HTTP/1.1 204 No Content
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:
op
member contains the value
queryallactions
href
member is http
or https
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:
GET
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:
200
Content-Type
header set to application/json
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" } ] }
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.
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.
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
.
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" } ] }
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:
op
member contains the value
observeproperty
href
member is http
or https
subprotocol
member has a value of
sse
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:
GET
Property
resourceAccept
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
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:
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.
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).
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]].
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();
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:
op
member contains the value
observeallproperties
href
member is http
or https
subprotocol
member has a value of
sse
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:
GET
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
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:
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.
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).
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]].
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();
The HTTP SSE Profile uses Server-Sent Events [[EVENTSOURCE]] as a mechanism for Consumers to subscribe to events emitted by a Web Thing.
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.
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:
op
member
contains the value subscribeevent
href
member is http
or https
subprotocol
member has a value of
sse
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:
GET
Event
resourceAccept
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
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:
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.
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).
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]].
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();
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:
op
member contains the value
subscribeallevents
href
member is http
or https
subprotocol
member has a value of
sse
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:
GET
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
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:
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.
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).
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]].
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();
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.
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.
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 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.
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]]:
{ "@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" } ] }
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:
op
member contains the value
observeproperty
href
member is http
or https
contentType
member has a
value of application/json
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:
POST
Content-Type
header set to application/json
callbackURL
member set to a callback URL the Thing
should use to send property change notifications to the Consumer.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:
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.
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:
POST
Content-Type
header set to application/json
Link
header with the URL set to the URL of the corresponding Property Affordance,
and rel
set to self
Date
header automatically set to the time of the property change by the
user agent, using the HTTP Date
format from [[rfc9110]]
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:
200 OK
HTTP/1.1 200 OK
unobserveproperty
In order to cancel the observation subscription of a property, a Consumer MUST send an HTTP request to the Web Thing with:
DELETE
Location
header of the HTTP response
during the observeproperty
operationDELETE /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:
204 No Content
HTTP/1.1 204 No Content
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:
op
member contains the value
observeallproperties
href
member is http
or https
contentType
member has a
value of application/json
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:
POST
Content-Type
header set to application/json
callbackURL
member set to a callback URL the Thing
should use to send property change notifications to the Consumer.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:
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.
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:
POST
Content-Type
header set to application/json
Link
header with the URL set to the URL of the corresponding Property Affordance,
and rel
set to self
Date
header automatically set to the time of the property change by the
user agent, using the HTTP Date
format from [[rfc9110]]
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:
200 OK
HTTP/1.1 200 OK
unobserveallproperties
In order to cancel the observation of all properties, a Consumer MUST send an HTTP request to the Web Thing with:
DELETE
Location
header of the HTTP response
during the observeallproperties
operationDELETE /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:
204 No Content
HTTP/1.1 204 No Content
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:
op
member contains the value
subscribeevent
href
member is http
or https
contentType
member has a
value of application/json
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.
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:
201 Created
Location
header set to a unique URL representing the individual event
subscription, for use by the Consumer when later cancelling the subscription.
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:
POST
Content-Type
header set to application/json
Link
header with the URL set to the URL of the corresponding Event Affordance,
and rel
set to self
Date
header automatically set to the time the event occurred by the
user agent, using the HTTP Date
format from [[rfc9110]]
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.
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:
200 OK
HTTP/1.1 200 OK
unsubscribeevent
In order to cancel the subscription to an event, a Consumer MUST send an HTTP request to the Web Thing with:
DELETE
Location
header of the HTTP response
during the subscribeevent
operationDELETE /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:
204 No Content
HTTP/1.1 204 No Content
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:
op
member contains the value
subscribeallevents
href
member is http
or https
contentType
member has a
value of application/json
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:
POST
Content-Type
header set to application/json
callbackURL
member set to a callback URL the Thing
should use to send event notifications to the Consumer.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:
201 Created
Location
header set to a unique URL representing the individual
event subscription, for use by the Consumer when later cancelling the subscription.
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:
POST
Content-Type
header set to application/json
Link
header with the URL set to the URL of the corresponding Event Affordance,
and rel
set to self
Date
header automatically set to the time the event occurred by the
user agent, using the HTTP Date
format from [[rfc9110]]
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.
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:
200 OK
HTTP/1.1 200 OK
unsubscribeallevents
In order to cancel the subscription to all events, a Consumer MUST send an HTTP request to the Web Thing with:
DELETE
Location
header of the HTTP response
during the subscribeallevents
operationDELETE /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:
204 No Content
HTTP/1.1 204 No Content
The privacy considerations of the WoT Architecture [[wot-architecture11]] and WoT Thing Description [[wot-thing-description11]] specifications SHOULD be taken into account.
Please also see WoT Security and Privacy Guidelines [[wot-security]] for implementation advice.
The security considerations of the WoT Architecture [[wot-architecture11]] and WoT Thing Description [[wot-thing-description11]] specifications SHOULD be taken into account.
Please also see WoT Security and Privacy Guidelines [[wot-security]] for implementation advice.
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.