Web Thing Protocol

WebSocket Sub-protocol

This document defines a WebSocket sub-protocol called the Web Thing Protocol, for monitoring and controlling connected devices over the World Wide Web. The Web Thing Protocol is intended as a dedicated real-time protocol for the Web of Things, to enable a WoT Consumer to communicate with one or more WoT Things over a WebSocket connection.

Introduction

This document defines a WebSocket [[WEBSOCKETS-PROTOCOL]] sub-protocol for monitoring and controlling connected devices over the Web.

The Web of Things (WoT) is a collection of standardised technology building blocks that help provide interoperability on the Internet of Things (IoT). The WoT Thing Description specification [[wot-thing-description11]] defines a metadata format for describing the capabilities of "Things" (connected devices) on the Web. The WoT Discovery specification [[wot-discovery]] defines mechanisms for discovering Things on the Web. This specification complements those building blocks by defining a dedicated real-time protocol for communicating with Things over the Web.

WebSockets [[WEBSOCKETS-PROTOCOL]] provide a way to upgrade a standard HTTP [[HTTP11]] request to a full-duplex, persistent, real-time communication channel over a single TCP connection. This can be used to create a versatile and efficient two-way channel with which a WoT Consumer can communicate with one or more Things [[wot-architecture11]] to carry out the full set of WoT operations. However, since a WebSocket is essentially just a raw TCP socket with no semantics of its own, a sub-protocol needs to be defined in order for a Consumer and Thing to communicate.

Whilst many other WebSocket sub-protocols exist, what makes the Web Thing Protocol unique is that it is specifically designed around the Web of Things information model and set of operations [[wot-thing-description11]], as well as being targeted specifically at Web of Things use cases [[wot-usecases]]. It can therefore be thought of as being native to the Web of Things.

The sub-protocol defines message payload formats for each of the well-known operation types defined in the WoT interaction model [[wot-architecture11]], and other messages needed for WebSocket communication.

This specification is intended to complement deliverables of the WoT Working Group, including WoT Architecture [[wot-architecture11]], WoT Thing Description [[wot-thing-description11]], WoT Discovery [[wot-discovery]], WoT Binding Templates [[wot-binding-templates]] and WoT Profile [[wot-profile]]. It is intended to implement use cases and requirements defined in the Web Thing Protocol Use Cases & Requirements community report.

Whilst this document is not on a standards track, the Web Thing Protocol is intended to eventually join a standards track at the W3C or another standards body such as the IETF.

Terminology

Fundamental WoT terminology such as Thing or Web Thing, Consumer or WoT Consumer, WoT Thing Description or Thing Description, Interaction Model, Interaction Affordance, Property, Action and Event are defined in the Terminology section of the WoT Architecture specification [[wot-architecture11]].

WebSocket Connection

Protocol Handshake

In order to communicate with a Web Thing, a WoT Consumer [[wot-architecture11]] MUST locate one or more WebSocket [[WEBSOCKETS-PROTOCOL]] endpoints provided by the Thing for a given set of Interaction Affordances [[wot-thing-description11]].

The URL of a WebSocket endpoint to be used for a given interaction MUST be obtained from a Thing Description [[wot-architecture11]] by locating a Form inside the corresponding Interaction Affordance for which:

To open a WebSocket on a Thing, an HTTP GET request [[RFC9110]] MUST be upgraded to a WebSocket connection using a standard WebSocket protocol handshake [[WEBSOCKETS-PROTOCOL]], specifying the "webthingprotocol" sub-protocol.

        GET wss://mythingserver.com/things/robot
        Host: mythingserver.com
        Origin: https://mythingserver.com
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
        Sec-WebSocket-Protocol: webthingprotocol
        Sec-WebSocket-Version: 13
      
        HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
        Sec-WebSocket-Protocol: webthingprotocol        
      

Sub-protocol name to be confirmed, see IANA Considerations.

A WebSocket can be opened from a web page using the JavaScript WebSocket API [[WEBSOCKETS-API]] which will take care of the handshake detailed above and allow messages to be sent and received.

        const socket = new WebSocket('wss://mywebthingserver/things/robot', 'webthingprotocol');
      

WebSocket Re-use

A single WebSocket [[WEBSOCKETS-PROTOCOL]] connection from a WoT Consumer MAY be shared between multiple Interaction Affordances of a Thing. A single WebSocket connection from a WoT Consumer MAY also be shared between multiple Things.

Before opening a new WebSocket connection, a WoT Consumer SHOULD check whether it already has an open connection to the same WebSocket endpoint URL.

If an existing connection to the same WebSocket endpoint URL exists, then that connection SHOULD be re-used rather than opening an additional socket.

If an existing connection to the same WebSocket endpoint URL exists but is using a different set of credentials for its given SecurityScheme [[wot-thing-description11]] (e.g. a different Bearer Token), then the WoT Consumer MUST NOT re-use the connection.

WebSocket Messages

All messages MUST be a JSON object [[JSON]].

Common members of all messages
Member Type Assignment Description
thingID string Mandatory The ID (URI) of the Thing to which the message relates.
messageID string Mandatory A unique identifier (UUID) for the current message.
messageType string Mandatory A string which denotes the type of message (one of request, response or notification).
operation string Mandatory A string which denotes the type of WoT operation [[wot-thing-description11]] to which the message relates (one of readproperty, writeproperty, observeproperty, unobserveproperty, invokeaction, queryaction, cancelaction, subscribeevent, unsubscribeevent, readallproperties, writeallproperties, readmultipleproperties, writemultipleproperties, observeallproperties, unobserveallproperties, subscribeallevents, unsubscribeallevents, or queryallactions).
correlationID string Optional A unique identifer (UUID) which is shared between messages corresponding to the same operation, e.g. a request and a response.

The top level JSON object MUST contain a thingID member with the value set to a unique identifier of the Web Thing to which the message relates. If the Thing Description of the Web Thing contains an id member then the value of that id member MUST be used as the unique identifier assigned to thingID. If the Thing Description of the Web Thing does not contain an id member then the URL [[URL]] from which the Thing Description was retrieved MAY be used as the thingID value instead. The value of the thingID member MUST be a valid URI [[URI]] serialised as a string.

The top level JSON object MUST contain a messageID member with the value set to a unique identifier for the current message in UUIDv4 format [[rfc9562]].

The top level JSON object MUST contain a messageType member, with its value set to one of request, response or notification.

Message types
Message type Direction Description
request Consumer ➡ Thing A message sent from a Consumer to a Thing (e.g. to request a reading of a property, invoke an action or subscribe to an event)
response Thing ➡ Consumer A message sent from a Thing to a Consumer in response to a request (e.g. to respond with a property reading, provide the final response to an action or confirm a subscription to an event)
notification Thing ➡ Consumer A message pushed from a Thing to a Consumer (e.g. an event, change in property value, or change in action state)

The top level JSON object MUST contain an operation member, with its value set to one of the well-known WoT operation names from the Thing Description specification [[wot-thing-description11]].

The lifecycle of an operation consists of a series of messages in a sequence (e.g. a request followed by a response, or a request followed by a response then one or more notifications). Each type of operation follows a particular sequence of message types, outlined in the table below:

Operation lifecycles
Operation Lifecycle
readproperty request, response
writeproperty request, response
readallproperties request, response
readmultipleproperties request, response
writeallproperties request, response
writemultipleproperties request, response
observeproperty request, response, notification, notification...
unobserveproperty request, response
observeallproperties request, response, notification, notification...
unobserveallproperties request, response

The top level JSON object MAY contain a correlationID member which provides a unique identifier in UUIDv4 format [[rfc9562]] which is shared between messages corresponding to the same WoT operation (e.g. a property read request and response, or an event subscription request and event notification). If a request message contains a correlatonID member then any response and notification messages which correspond to the same operation MUST also include a correlationID member with the same value.

All date and time values MUST use the date-time format defined in [[RFC3339]].

      2025-01-15T12:08:00.42Z
    

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.

readproperty

Request

To request a property reading from a Thing, a Consumer MUST send a message to the Thing which contains the following members:

Members of a readproperty request message
Member Type Assignment Description
messageType string "request" A string which denotes that this message is a request sent from a Consumer to a Thing.
operation string "readproperty" A string which denotes that this message relates to a readproperty operation.
name string Mandatory The name of the Property to read, as per its key in the properties member of the Thing Description.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "c370da58-69ae-4e83-bb5a-ac6cfb2fed54",
            "messageType": "request",
            "operation": "readproperty",
            "name": "on",
            "correlationID": "5afb752f-8be0-4a3c-8108-1327a6009cbd"
          }
        

When a Thing receives a message from a Consumer with messageType set to request and operation set to readproperty it MUST attempt to read the value of the Property with the given name.

Response

Upon successfully reading the value of the requested Property, the Thing MUST send a message to the requesting Consumer containing the following members:

Members of a readproperty response message
Member Type Assignment Description
messageType string "response" A string which denotes that this message is a response sent from a Thing to a Consumer.
operation string "readproperty" A string which denotes that this message relates to a readproperty operation.
name string Mandatory The name of the Property being read, as per its key in the properties member of the Thing Description.
value any Mandatory The current value of the Property being read, with a type and structure conforming to the data schema of the corresponding PropertyAffordance in the Thing Description.
timestamp string Optional A timestamp in date-time format [[RFC3339]] set to the time the property reading took place.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "79057736-3e0e-4dc3-b139-a33051901ee2",
            "messageType": "response",
            "operation": "readproperty",
            "name": "on",
            "value": true,
            "timestamp": "2024-01-13T23:20:50.52Z",
            "correlationID": "5afb752f-8be0-4a3c-8108-1327a6009cbd"
          }
        

writeproperty

Request

To set the value of a Property of a Thing, a Consumer MUST send a message to the Thing which contains the following members:

Members of a writeproperty request message
Member Type Assignment Description
messageType string "request" A string which denotes that this message is a request sent from a Consumer to a Thing.
operation string "writeproperty" A string which denotes that this message relates to a writeproperty operation.
name string Mandatory The name of the Property whose value should be set, as per its key in the properties member of the Thing Description.
value any Mandatory The desired new value of the Property, with a type and structure conforming to the data schema of the corresponding PropertyAffordance in the Thing Description.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "97d22676-6d45-4435-aef5-dd87467a0c44",
            "messageType": "response",
            "operation": "writeproperty",
            "name": "on",
            "value": true,
            "correlationID": "f6cf46a8-9c96-437e-8b53-925b7679a990"
          }
        

Response

When a Thing receives a message from a Consumer with messageType set to request and operation set to writeproperty it MUST attempt to set the Property with the name provided in the name member to the value provided in the value member.

Upon successfully submitting the value of the requested Property, the Thing MUST send a message to the requesting Consumer containing the following members:

Members of a writeproperty response message
Member Type Assignment Description
messageType string "response" A string which denotes that this message is a response sent from a Thing to a Consumer.
operation string "writeproperty" A string which denotes that this message relates to a writeproperty operation.
name string Mandatory The name of the Property being written, as per its key in the properties member of the Thing Description.
value any Optional The value which has been successfully assigned to the Property being written, with a type and structure conforming to the data schema of the corresponding PropertyAffordance in the Thing Description.
timestamp string Optional A timestamp in date-time format [[RFC3339]] set to the time the property write took place.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "db25fe4f-bee8-43a7-8ff0-3a1ff6e620b0",
            "messageType": "response",
            "operation": "writeproperty",
            "name": "on",
            "value": true,
            "timestamp": "2024-01-13T23:20:50.52Z",
            "correlationID": "f6cf46a8-9c96-437e-8b53-925b7679a990"
          }
        

If the Thing can confirm that the requested value has been set successfully then the response message to a writeproperty request SHOULD contain a value member with its value set to the value which has been successfully set.

If the Thing can not confirm that the requested value has been set successfully (e.g. in the case of a write-only property or a device that is temporarily asleep so the write has been queued) then the response message to a writeproperty request MUST NOT contain a value member.

If a Consumer attempts to set the value of a numerical Property to a value which conforms to the Property's data schema but to a level of precision the Thing does not support, (e.g. 3.14159), then the Thing MAY respond with the actual value set (e.g. 3.14).

readallproperties

Request

To request a reading of all of a Thing's readable Properties at once, a Consumer MUST send a message to the Thing which contains the following members:

Members of a readallproperties request message
Member Type Assignment Description
messageType string "request" A string which denotes that this message is a request sent from a Consumer to a Thing.
operation string "readallproperties" A string which denotes that this message relates to a readallproperties operation.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "e144349c-5cd7-4002-938f-aac5adf99789",
            "messageType": "request",
            "operation": "readallproperties",
            "correlationID": "c08075a4-d53c-4f51-b251-a6b6922c2b1f"
          }
        

When a Thing receives a message from a Consumer with messageType set to request and operation set to readallproperties it MUST attempt to read the value of all of its readable Properties (i.e. all Property Affordances where writeOnly [[wot-thing-description11]] is not set to true).

Response

Upon successfully reading the value of all of its readable Properties, the Thing MUST send a message to the requesting Consumer containing the following members:

Members of a readallproperties response message
Member Type Assignment Description
messageType string "response" A string which denotes that this message is a response sent from a Thing to a Consumer.
operation string "readallproperties" A string which denotes that this message relates to a readallproperties operation.
values object Mandatory The values of all Properties contained in an object keyed by Property name, with the value of each Property conforming to the data schema of the corresponding PropertyAffordance in the Thing Description.
timestamp string Optional A timestamp in date-time format [[RFC3339]] set to the time the property readings took place.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "79057736-3e0e-4dc3-b139-a33051901ee2",
            "messageType": "response",
            "operation": "readallproperties",
            "values": {
              "on": true,
              "level": 50
            },
            "timestamp": "2025-05-22T17:15:35.636Z",
            "correlationID": "c08075a4-d53c-4f51-b251-a6b6922c2b1f"
          }
        

Error Response

If a Thing receives a readallproperties request message from a Consumer but the reading of at least one of the properties unexpectedly fails, then it MUST send an error response to the Consumer with status set to 500.

          
            {
              "thingID": "https://mythingserver.com/things/mylamp1",
              "messageID": "1876e481-5fc2-4b39-93b4-1f434f7b6a47",
              "messageType": "response",
              "operation": "readallproperties",
              "error": {
                "status": "500",
                "type": "https://w3c.github.io/web-thing-protocol/errors#500",
                "title": "Internal Server Error"
                "detail": "Reading the 'level' property unexpectedly failed"
              }
              "timestamp": "2025-05-22T17:15:36.636Z",
              "correlationID": "c08075a4-d53c-4f51-b251-a6b6922c2b1f"
            }
          
        

If a readallproperties operation only partially fails (i.e. some Properties can be read but others can not), a Thing MAY include the successfully read values in the error response, in a values member keyed by Property name.

readmultipleproperties

Request

To request a reading of multiple readable Properties of a Thing at once, a Consumer MUST send a message to the Thing which contains the following members:

Members of a readmultipleproperties request message
Member Type Assignment Description
messageType string "request" A string which denotes that this message is a request sent from a Consumer to a Thing.
operation string "readmultipleproperties" A string which denotes that this message relates to a readmultipleproperties operation.
names array Mandatory An array of strings specifying the names of the Properties to read, as per their keys in the properties member of the Thing Description.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "dacaea0e-43c2-4fc0-bd66-5a807ca52324",
            "messageType": "request",
            "operation": "readmultipleproperties",
            "names": ["on", "level"],
            "correlationID": "c0503f71-288f-4460-b308-c4cc0009cd89"
          }
        

When a Thing receives a message from a Consumer with messageType set to request and operation set to readmultipleproperties it MUST attempt to read the value of all the Properties specified in the names member of the message.

Response

Upon successfully reading the values of the specified Properties, the Thing MUST send a message to the requesting Consumer containing the following members:

Members of a readmultipleproperties response message
Member Type Assignment Description
messageType string "response" A string which denotes that this message is a response sent from a Thing to a Consumer.
operation string "readmultipleproperties" A string which denotes that this message relates to a readmultipleproperties operation.
values object Mandatory The values of the read Properties contained in an object keyed by Property name, with the value of each Property conforming to the data schema of the corresponding PropertyAffordance in the Thing Description.
timestamp string Optional A timestamp in date-time format [[RFC3339]] set to the time the property readings took place.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "695a2626-be5f-4f91-8719-105abc52aa0f",
            "messageType": "response",
            "operation": "readmultipleproperties",
            "values": {
              "on": true,
              "level": 50
            },
            "timestamp": "2025-05-22T18:04:33.531Z",
            "correlationID": "c0503f71-288f-4460-b308-c4cc0009cd89"
          }
        

Error Response

If a Thing receives a readmultipleproperties request message from a Consumer with a names member which is empty, contains an invalid Property name, or the name of a writeOnly [[wot-thing-description11]] Property, then it MUST send an error response to the Consumer with status set to 400.

          
            {
              "thingID": "https://mythingserver.com/things/mylamp1",
              "messageID": "72e6f397-8ae9-4882-ac7d-303a953527a5",
              "messageType": "response",
              "operation": "readmultipleproperties",
              "error": {
                "status": "400",
                "type": "https://w3c.github.io/web-thing-protocol/errors#400",
                "title": "Bad Request"
                "detail": "No property found with the name 'volume'"
              }
              "timestamp": "2025-05-22T18:04:33.531Z",
              "correlationID": "c0503f71-288f-4460-b308-c4cc0009cd89"
            }
          
        

If a Thing receives a readmultipleproperties request message from a Consumer with a names member containing valid Property names but the reading of at least one of the properties unexpectedly fails, then it MUST send an error response to the Consumer with status set to 500.

          
            {
              "thingID": "https://mythingserver.com/things/mylamp1",
              "messageID": "cf0240ca-e21c-49b8-bca4-e27002525ea1",
              "messageType": "response",
              "operation": "readmultipleproperties",
              "error": {
                "status": "500",
                "type": "https://w3c.github.io/web-thing-protocol/errors#500",
                "title": "Internal Server Error"
                "detail": "Reading the 'level' property unexpectedly failed"
              }
              "timestamp": "2025-05-22T18:04:33.531Z",
              "correlationID": "c0503f71-288f-4460-b308-c4cc0009cd89"
            }
          
        

If a readmultipleproperties operation only partially fails (i.e. some Properties can be read but others can not), a Thing MAY include the successfully read values in the error response, in a values member keyed by Property name.

writeallproperties

Request

To set the value of all Properties of a Thing at once, a Consumer MUST send a message to the Thing which contains the following members:

Members of a writeallproperties request message
Member Type Assignment Description
messageType string "request" A string which denotes that this message is a request sent from a Consumer to a Thing.
operation string "writeallproperties" A string which denotes that this message relates to a writeallproperties operation.
values object Mandatory An object keyed by Property name, containing the desired value of each Property, with a type and structure conforming to the data schema of each corresponding PropertyAffordance in the Thing Description.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "60c33fc4-ed99-446e-a2e3-f3b5be82c34b",
            "messageType": "request",
            "operation": "writeallproperties",
            "values": {
              "on": true,
              "level": 75
            },
            "correlationID": "551aaa52-ff95-4fb5-a657-2b5f430d47ff"
          }
        

When a Thing receives a message from a Consumer with messageType set to request and operation set to writeallproperties it MUST attempt to write the values of all writeable Properties using the values specified in the values member of the message.

Response

Upon successfully writing the values of all writeable Properties, the Thing MUST send a message to the requesting Consumer containing the following members:

Members of a writeallproperties response message
Member Type Assignment Description
messageType string "response" A string which denotes that this message is a response sent from a Thing to a Consumer.
operation string "writeallproperties" A string which denotes that this message relates to a writeallproperties operation.
values object Mandatory An object keyed by Property name, containing the values which have been successfully assigned to writeable Properties, with the type and structure of each value conforming to the data schema in its corresponding PropertyAffordance in the Thing Description.
timestamp string Optional A timestamp in date-time format [[RFC3339]] set to the time the property readings took place.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "74022347-72c2-4fa1-9e34-1a662bdff85e",
            "messageType": "response",
            "operation": "writeallproperties",
            "values": {
              "on": true,
              "level": 75
            },
            "timestamp": "2025-08-13T17:11:00.531Z",
            "correlationID": "551aaa52-ff95-4fb5-a657-2b5f430d47ff"
          }
        

Error Response

If a Thing receives a writeallproperties request message from a Consumer which does not contain values for all writeable properties, contains an invalid Property name, contains the name of a readOnly [[wot-thing-description11]] Property, or contains a value which does not conform to the data schema of the corresponding PropertyAffordance then it MUST send an error response to the Consumer with status set to 400.

          
            {
              "thingID": "https://mythingserver.com/things/mylamp1",
              "messageID": "6dcfce6a-b0cd-48e7-992a-b96d5cb2b872",
              "messageType": "response",
              "operation": "writeallproperties",
              "error": {
                "status": "400",
                "type": "https://w3c.github.io/web-thing-protocol/errors#400",
                "title": "Bad Request"
                "detail": "No property found with the name 'volume'"
              }
              "timestamp": "2025-08-13T18:31:43.531Z",
              "correlationID": "551aaa52-ff95-4fb5-a657-2b5f430d47ff"
            }
          
        

If a Thing receives a writeallproperties request message from a Consumer with a values member containing valid names and values for all writeable Properties, but the writing of at least one of the properties unexpectedly fails, then it MUST send an error response to the Consumer with status set to 500.

          
            {
              "thingID": "https://mythingserver.com/things/mylamp1",
              "messageID": "35caf0d3-05f6-4a15-8ddf-a765b5280b06",
              "messageType": "response",
              "operation": "writeallproperties",
              "error": {
                "status": "500",
                "type": "https://w3c.github.io/web-thing-protocol/errors#500",
                "title": "Internal Server Error"
                "detail": "Writing the 'level' property unexpectedly failed"
              }
              "timestamp": "2025-08-13T19:04:36.426Z",
              "correlationID": "551aaa52-ff95-4fb5-a657-2b5f430d47ff"
            }
          
        

If a writeallproperties operation only partially fails (i.e. some Properties are written successfully but others are not), a Thing MUST include the successfully written values in the error response, in a values member keyed by Property name.

writemultipleproperties

Request

To set the value of multiple Properties of a Thing at once, a Consumer MUST send a message to the Thing which contains the following members:

Members of a writemultipleproperties request message
Member Type Assignment Description
messageType string "request" A string which denotes that this message is a request sent from a Consumer to a Thing.
operation string "writemultipleproperties" A string which denotes that this message relates to a writemultipleproperties operation.
values object Mandatory An object keyed by Property name, containing the desired value of each Property, with a type and structure conforming to the data schema of each corresponding PropertyAffordance in the Thing Description.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "02c576a2-5adf-4924-b2c8-2222396a3d5c",
            "messageType": "request",
            "operation": "writemultipleproperties",
            "values": {
              "on": false,
              "level": 25
            },
            "correlationID": "e851583f-e152-4cad-9bb3-7bd3b24f8525"
          }
        

When a Thing receives a message from a Consumer with messageType set to request and operation set to writemultipleproperties it MUST attempt to write the values of the Properties specified in the values member of the message.

Response

Upon successfully writing the values of the specified Properties, the Thing MUST send a message to the requesting Consumer containing the following members:

Members of a writemultipleproperties response message
Member Type Assignment Description
messageType string "response" A string which denotes that this message is a response sent from a Thing to a Consumer.
operation string "writemultipleproperties" A string which denotes that this message relates to a writemultipleproperties operation.
values object Mandatory An object keyed by Property name, containing the values which have been successfully assigned to Properties, with the type and structure of each value conforming to the data schema in its corresponding PropertyAffordance in the Thing Description.
timestamp string Optional A timestamp in date-time format [[RFC3339]] set to the time the property readings took place.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "9c5d6eaf-4624-4464-8cc0-09472443ae82",
            "messageType": "response",
            "operation": "writemultipleproperties",
            "values": {
              "on": false,
              "level": 25
            },
            "timestamp": "2025-08-17T18:35:00.246Z",
            "correlationID": "e851583f-e152-4cad-9bb3-7bd3b24f8525"
          }
        

Error Response

If a Thing receives a writemultipleproperties request message from a Consumer with a values member which is empty, contains an invalid Property name, contains the name of a readOnly [[wot-thing-description11]] Property, or contains a value which does not conform to the data schema of the corresponding PropertyAffordance then it MUST send an error response to the Consumer with status set to 400.

          
            {
              "thingID": "https://mythingserver.com/things/mylamp1",
              "messageID": "b0f9f6a3-3558-4680-8b3d-4c017c669433",
              "messageType": "response",
              "operation": "writemultipleproperties",
              "error": {
                "status": "400",
                "type": "https://w3c.github.io/web-thing-protocol/errors#400",
                "title": "Bad Request"
                "detail": "No property found with the name 'volume'"
              }
              "timestamp": "2025-08-19T18:38:35.613Z",
              "correlationID": "e851583f-e152-4cad-9bb3-7bd3b24f8525"
            }
          
        

If a Thing receives a writemultipleproperties request message from a Consumer with a values member containing valid names and values of writeable Properties, but the writing of at least one of the properties unexpectedly fails, then it MUST send an error response to the Consumer with status set to 500.

If a writemultipleproperties operation only partially fails (i.e. some Properties are written successfully but others are not), a Thing MUST include the successfully written values in the error response, in a values member keyed by Property name.

          
            {
              "thingID": "https://mythingserver.com/things/mylamp1",
              "messageID": "8620b30a-03db-4332-a139-53bef96e4e47",
              "messageType": "response",
              "operation": "writemultipleproperties",
              "error": {
                "status": "500",
                "type": "https://w3c.github.io/web-thing-protocol/errors#500",
                "title": "Internal Server Error"
                "detail": "Writing the 'level' property unexpectedly failed"
              },
              "values": {
                "on": "true"
              },
              "timestamp": "2025-08-19T18:40:35.360Z",
              "correlationID": "e851583f-e152-4cad-9bb3-7bd3b24f8525"
            }
          
        

observeproperty

Request

To observe a Property, a Consumer MUST send a message to the Thing which contains the following members:

Members of an observeproperty request message
Member Type Assignment Description
messageType string "request" A string which denotes that this message is a request sent from a Consumer to a Thing.
operation string "observeproperty" A string which denotes that this message relates to an observeproperty operation.
name string Mandatory The name of the Property to be observed, as per its key in the properties member of the Thing Description.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "f160098e-8c71-4025-9cb8-49fa038f5076",
            "messageType": "request",
            "operation": "observeproperty",
            "name": "level",
            "correlationID": "3b380f3c-4fb8-4dc0-8ef2-ef2c2b528931"
          }
        

When a Thing receives a message from a Consumer with messageType set to request and operation set to observeproperty it MUST attempt to register an observation subscription to the Property with the given name.

If a Thing receives an observeproperty request for a Property which already has an active observation subscription over the same WebSocket connection, the Thing MUST replace the existing observation subscription with a new one, using the correllationID of the last observeproperty request received (i.e. last subscription wins).

If an observeproperty request replaces an observation subscription that was previously registered by an observeallproperties operation then that does not impact active observation subscriptions for other Properties, which should continue to be registered using their current correllationID. Conversely, an observeallproperties request may replace an observation subscription previously registered by an observeproperty operation over the same WebSocket connection, which would impact any active observation subscriptions for other Properties on the same connection.

Response

Upon successfully registering an observation subscription to the requested Property, the Thing MUST send a message to the requesting Consumer containing the following members:

Members of an observeproperty response message
Member Type Assignment Description
messageType string "response" A string which denotes that this message is a response sent from a Thing to a Consumer.
operation string "observeproperty" A string which denotes that this message relates to an observeproperty operation.
name string Mandatory The name of the Property being observed, as per its key in the properties member of the Thing Description.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "4df7faaf-6099-4766-a615-cb49883edfd4",
            "messageType": "response",
            "operation": "observeproperty",
            "name": "level",
            "correlationID": "3b380f3c-4fb8-4dc0-8ef2-ef2c2b528931"
          }
        

Notification

Whilst a property observation subscription is registered, whenever a change in the value of the observed Property occurs, the Thing MUST send a message to the observing Consumer containing the following members:

Members of an observeproperty notification message
Member Type Assignment Description
messageType string "notification" A string which denotes that this message is a notification sent from a Thing to a Consumer.
operation string "observeproperty" A string which denotes that this message relates to an observeproperty operation.
name string Mandatory The name of the Property being observed, as per its key in the properties member of the Thing Description.
value any Mandatory The current value of the Property being observed, with a type and structure conforming to the data schema of the corresponding PropertyAffordance in the Thing Description.
timestamp string Optional A timestamp in date-time format [[RFC3339]] set to the time the change in value took place.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "c9cce575-1923-441b-88cb-e58d4f7e615f",
            "messageType": "notification",
            "operation": "observeproperty",
            "name": "level",
            "value": 42,
            "timestamp": "2025-08-20T11:54:25.535Z",
            "correlationID": "3b380f3c-4fb8-4dc0-8ef2-ef2c2b528931"
          }
        

Because a duplicate observation subscription replaces a previous subscription to the same Property, a Thing should only ever send one notification message per WebSocket connection for each change in property value. Notification messages always use the correllationID of the currently active observation subscription (which may have replaced a previous subscription).

unobserveproperty

Request

To stop observing a Property, a Consumer MUST send a message to the Thing which contains the following members:

Members of an unobserveproperty request message
Member Type Assignment Description
messageType string "request" A string which denotes that this message is a request sent from a Consumer to a Thing.
operation string "unobserveproperty" A string which denotes that this message relates to an unobserveproperty operation.
name string Mandatory The name of the Property to stop observing, as per its key in the properties member of the Thing Description.
        {
          "thingID": "https://mythingserver.com/things/mylamp1",
          "messageID": "85afa9c1-b5d1-479a-9a80-ce272b156dff",
          "messageType": "request",
          "operation": "unobserveproperty",
          "name": "level",
          "correlationID": "6180212a-8b28-49fa-9bfc-89c8c43ce887"
        }
      

When a Thing receives a message from a Consumer with messageType set to request and operation set to unobserveproperty it MUST attempt to remove any observation subscription to the Property with the given name.

If an unobserveproperty request removes an observation subscription that was previously registered by an observeallproperties operation then that does not impact active observation subscriptions for other Properties that may have been registered by the same operation.

Response

Upon successfully removing an observation subscription to the requested Property, the Thing MUST send a message to the requesting Consumer containing the following members:

Members of an unobserveproperty response message
Member Type Assignment Description
messageType string "response" A string which denotes that this message is a response sent from a Thing to a Consumer.
operation string "unobserveproperty" A string which denotes that this message relates to an unobserveproperty operation.
name string Mandatory The name of the Property no longer being observed, as per its key in the properties member of the Thing Description.
        {
          "thingID": "https://mythingserver.com/things/mylamp1",
          "messageID": "2e6a9454-ac50-4c8a-9c1e-4380c5a05963",
          "messageType": "response",
          "operation": "unobserveproperty",
          "name": "level",
          "correlationID": "6180212a-8b28-49fa-9bfc-89c8c43ce887"
        }
        

If a Thing receives an unobserveproperty request for a Property, but that Property does not have any active observation subscriptions over the current WebSocket connection, then it SHOULD still send a success response since the intended outcome has been achieved.

observeallproperties

Request

To observe all Properties of a Thing, a Consumer MUST send a message to the Thing which contains the following members:

Members of an observeallproperties request message
Member Type Assignment Description
messageType string "request" A string which denotes that this message is a request sent from a Consumer to a Thing.
operation string "observeallproperties" A string which denotes that this message relates to an observeallproperties operation.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "b8988514-5a26-474f-9895-df20db848dd1",
            "messageType": "request",
            "operation": "observeallproperties",
            "correlationID": "e8948c71-b460-46f8-b4e5-f93b04c6e67b"
          }
        

When a Thing receives a message from a Consumer with messageType set to request and operation set to observeallproperties it MUST attempt to register an observation subscription for each Property of the Thing.

If a Thing receives an observeallproperties request and there are already active Property observation subscriptions on the same WebSocket connection, the Thing MUST replace the existing observation subscriptions with new ones, using the correllationID of the observeallproperties request received (i.e. last subscription wins).

The observeallproperties operation can be thought of as a batch operation which adds individual observation subscriptions to each Property. Those observation subscriptions may later be individually replaced by new observation subscriptions using observeproperty operations, or individually cancelled using unobserveproperty operations.

Response

Upon successfully registering an observation subscription to all Properties, the Thing MUST send a message to the requesting Consumer containing the following members:

Members of an observeallproperties response message
Member Type Assignment Description
messageType string "response" A string which denotes that this message is a response sent from a Thing to a Consumer.
operation string "observeallproperties" A string which denotes that this message relates to an observeallproperties operation.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "0855374a-328d-4a7a-8d46-560d915985f0",
            "messageType": "response",
            "operation": "observeallproperties",
            "correlationID": "e8948c71-b460-46f8-b4e5-f93b04c6e67b"
          }
        

Notification

Whilst an observation subscription to all properties is registered, whenever a change in the value of any Property of the Thing occurs, the Thing MUST send a message to the observing Consumer containing the following members:

Members of an observeallproperties notification message
Member Type Assignment Description
messageType string "notification" A string which denotes that this message is a notification sent from a Thing to a Consumer.
operation string "observeallproperties" A string which denotes that this message relates to an observeallproperties operation.
name string Mandatory The name of the Property whose value changed, as per its key in the properties member of the Thing Description.
value any Mandatory The current value of the Property that changed, with a type and structure conforming to the data schema of the corresponding PropertyAffordance in the Thing Description.
timestamp string Optional A timestamp in date-time format [[RFC3339]] set to the time the change in value took place.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "c351f404-f058-48fe-9c6c-9555fffb4619",
            "messageType": "notification",
            "operation": "observeallproperties",
            "name": "level",
            "value": 42,
            "timestamp": "2025-09-03T12:24:64.532Z",
            "correlationID": "e8948c71-b460-46f8-b4e5-f93b04c6e67b"
          }
        

Because a duplicate observation subscription replaces a previous subscription to the same Property, a Thing should only ever send one notification message per WebSocket connection for each change in property value. Notification messages always use the correllationID of the currently active observation subscription (which may have replaced a previous subscription).

unobserveallproperties

Request

To stop observing all Properties of a Thing, a Consumer MUST send a message to the Thing which contains the following members:

Members of an unobserveallproperties request message
Member Type Assignment Description
messageType string "request" A string which denotes that this message is a request sent from a Consumer to a Thing.
operation string "unobserveallproperties" A string which denotes that this message relates to an unobserveallproperties operation.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "38794cc1-ff97-494c-b662-7fcf951802a7",
            "messageType": "request",
            "operation": "unobserveallproperties",
            "correlationID": "51f2692b-b707-4097-9077-e313761406aa"
          }
        

When a Thing receives a message from a Consumer with messageType set to request and operation set to unobserveallproperties it MUST attempt to remove observation subscriptions from all Properties of the Thing.

The unobserveallproperties operation can be thought of as a batch operation which removes all individual observation subscriptions that have been registered with a Thing over a given WebSocket connection, regardless of whether those observation subscriptions were registered using an observeproperty operation or an observeallproperties operation.

Response

Upon successfully removing observation subscriptions from all Properties, the Thing MUST send a message to the requesting Consumer containing the following members:

Members of an unobserveallproperties response message
Member Type Assignment Description
messageType string "response" A string which denotes that this message is a response sent from a Thing to a Consumer.
operation string "unobserveallproperties" A string which denotes that this message relates to an unobserveallproperties operation.
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "ec6ad624-74fe-402e-a009-114b779d1bb0",
            "messageType": "response",
            "operation": "unobserveallproperties",
            "correlationID": "51f2692b-b707-4097-9077-e313761406aa"
          }
        

If a Thing receives an unobserveallproperties request but the Thing does not have any active observation subscriptions over the current WebSocket connection, then it SHOULD still send a success response since the intended outcome has been achieved.

Error Response

If a Thing experiences an error when attempting to carry out an operation requested by a Consumer, it MUST send a response message to the Consumer containing the following members:

Members of an error response message
Member Type Assignment Description
messageType string "response" A string which denotes that this message is a response sent from a Thing to a Consumer.
error object Mandatory An object conforming to the Problem Details Format [[RFC9457]].
        
          {
            "thingID": "https://mythingserver.com/things/mylamp1",
            "messageID": "79057736-3e0e-4dc3-b139-a33051901ee2",
            "messageType": "response",
            "operation": "readproperty",
            "name": "on",
            "error": {
              "status": "404",
              "type": "https://w3c.github.io/web-thing-protocol/errors#404",
              "title": "Not Found"
              "detail": "No property found with the name 'on'"
            }
            "timestamp": "2024-01-13T23:20:50.52Z",
            "correlationID": "5afb752f-8be0-4a3c-8108-1327a6009cbd"
          }
        
      

If the error experienced could be described by one of the common error types described in the following table then that error type SHOULD be used:

Common error types
status type title Description
400 https://w3c.github.io/web-thing-protocol/errors#400 Bad Request The request message was invalid (e.g. is missing mandatory members or contains an unknown operation type).
403 https://w3c.github.io/web-thing-protocol/errors#403 Forbidden The requesting Consumer is not have permission to carry out the requested operation.
404 https://w3c.github.io/web-thing-protocol/errors#404 Not Found The interaction affordance referenced in the request message can not be found (e.g. no Property with the given name exists).
500 https://w3c.github.io/web-thing-protocol/errors#500 Internal Server Error The Thing experienced an unexpected condition which prevented it from fulfilling the requested operation.
503 https://w3c.github.io/web-thing-protocol/errors#503 Service Unavailable The Thing or interaction affordance is currently not able to fulfil the requested operation (e.g. because it is overloaded or undergoing a firmware update).

The URLs given for error types in the table above are placeholders and will be replaced in the final version of this specification.

The error member of an error response message MAY contain a detail member with its value set to a string containing additional human-readable information about the specific instance of the error.

A Thing MAY use its own error types where one of the common error types above does not sufficiently explain the error, as long as the error member of the response message conforms to the Problem Details Format [[RFC9457]].

        
          {
            "thingID": "https://mythingserver.com/things/teapot",
            "messageID": "07de640d-1b10-4857-b1ae-0c29d62acedc",
            "messageType": "response",
            "operation": "invokeaction",
            "name": "brewCoffee",
            "error": {
              "status": "418",
              "type": "https://mythingserver.com/errors#418",
              "title": "I'm a teapot"
              "detail": "This device can not brew coffee because it is a teapot"
            }
            "timestamp": "2025-05-22T07:21:50.53Z",
            "correlationID": "61aa2164-b1ef-4585-aa3f-626a7f4a185f"
          }
        
      

Example Thing Descriptions

Privacy Considerations

Security Considerations

Accessibility Considerations

IANA Considerations

This specification proposes the registration of a sub-protocol in the IANA "WebSocket Subprotocol Name Registry". The name of the sub-protocol and the published URL of its definition are to be confirmed, but currently the name "webthingprotocol" and this document are used as a placeholder and draft proposal.

Subprotocol Identifier
webthingprotocol
Subprotocol Common Name
Web Thing Protocol
Subprotocol Definition
This document.