Shadows#

Shadows service maintains a device shadow for each thing — a persisted record holding the thing's last reported state and its desired state. It lets users read and set a thing's state even while the thing is offline, and aligns the two whenever the thing reconnects.

A shadow is a single record per thing.

Field Description
thing_id ID of the thing the shadow belongs to
state Nested object holding the desired, reported, and delta states (see below)
reported_at Unix timestamp (seconds) of the last reported-state update
updated_at Unix timestamp (seconds) of the last desired-state update

State#

desired, reported, and delta are each a free-form JSON object (a set of key/value pairs).

Field Description
desired State the application wants the thing to reach.
reported State the thing last reported. Merged from the thing's telemetry messages.
delta Computed subset of desired whose values differ from (or are absent in) reported. Omitted when empty.

The delta is derived on read and on every state change; it is never stored directly. Keys present only in reported are not part of the delta.

How it works#

  • Desired state is set by a user through the HTTP API. On update, the service recomputes the delta and publishes it to the thing on its command subject (things.<id>.commands.shadow).
  • Reported state is updated automatically as the thing publishes messages. The service consumes messages from the broker, flattens each into a state patch, and merges the patch into reported (no-op writes are skipped).
  • On each reported-state change, any still-pending delta is re-published, so a reconnecting thing receives commands it missed while offline.

Authorization is delegated to the Things service: reading a shadow requires viewer access on the thing's group, while updating or removing a shadow requires editor access.

Managing a shadow#

# Set the desired state for a thing
curl -s -S -i -X PUT \
  -H "Authorization: Bearer <user_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "desired": {"fanSpeed": 3, "targetTemp": 21}
  }' \
  https://localhost/svcshadows/things/<thing_id>/shadows
{
  "thing_id": "111e4567-e89b-12d3-a456-426614174000",
  "state": {
    "desired": { "fanSpeed": 3, "targetTemp": 21 },
    "reported": { "fanSpeed": 1, "targetTemp": 19 },
    "delta": { "fanSpeed": 3, "targetTemp": 21 }
  },
  "reported_at": 1774342400,
  "updated_at": 1774342578
}
# View a thing's shadow
curl -s -S -i \
  -H "Authorization: Bearer <user_token>" \
  https://localhost/svcshadows/things/<thing_id>/shadows

# Remove a thing's shadow
curl -s -S -i -X DELETE \
  -H "Authorization: Bearer <user_token>" \
  https://localhost/svcshadows/things/<thing_id>/shadows

For the full API reference, see the API documentation.