Skip to main content

Communication

Established WS connection - basic package types & structure.

Address​

Open web sockets connection and authenticate with the JWT to address

wss://<HOST>:6113/shelly/wss/hk_sock?t=<JWT>

The integrator learns the hosts it need to connect via User consent/Permissions Grant process from the host parameter provided to Integrator callback url.

The <JWT> token is obtained as explained at Getting Started

Events​

Events that Shelly cloud sends.

Device state reaches the integrator as events on this connection. Apart from the deviceStatus returned by Device Verify for an online device, there is no endpoint to request a device's current state on demand. Events sent while an integrator is disconnected cannot be recovered afterwards, so an integrator is expected to hold the connection open and keep its own copy of the state it needs.

Shelly:StatusOnChange​

Device state change.

{
event: "Shelly:StatusOnChange", // EVENT_NAME
deviceId: string, // DEVICE_ID
status: object // DEVICE_SPECIFIC_STATUS_STRUCTURE
}

Shelly:Settings​

Device settings change. Sent when a setting is changed in the device.

{
event: "Shelly:Settings", // EVENT_NAME
deviceId: string, // DEVICE_ID
settings: object // DEVICE_SPECIFIC_SETTINGS_STRUCTURE
}

Shelly:Online​

Sent when device changes online state.

{
event: "Shelly:Online", // EVENT_NAME
deviceId: string, // DEVICE_ID
online: number // DEVICE_ONLINE_STATUS - 1 for online, 0 for offline
}

Commands​

Request for Relay & Light​

Request
{
event: "Shelly:CommandRequest", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
data: {
cmd: string, // COMMAND_NAME "relay" | "light"
params: {
id: number, // DEVICE_CHANNEL
turn: string // COMMAND_ACTION "on" | "off" | "toggle"
}
}
}

Request for Roller​

Request
{
event: "Shelly:CommandRequest", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
data: {
cmd: string, // COMMAND_NAME "roller"
params: {
id: number, // DEVICE_CHANNEL
go: string // COMMAND_ACTION "stop" | "open" | "close"
}
}
}

Request for Roller to Position​

This command only works if device is calibrated.

Request
{
event: "Shelly:CommandRequest", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
data: {
cmd: string, // COMMAND_NAME "roller_to_pos"
params: {
id: number, // DEVICE_CHANNEL
pos: number, // POSITION_IN_PERCENT
rel: number, // RELATIVE_POSITION_IN_PERCENT
slat_pos:number, // SLAT_POSITION
slat_rel:number // RELATIVE_SLAT_POSITION
}
}
}
  • id identifies the roller/cover channel to change, starts from 0. It must be present even for single channel devices.
  • pos is the position expressed in percent in range 0 to 100.
  • rel is relative move in %, allowed range [-100..100]. pos and rel can't be provided simultaneously.
  • slat_pos same as pos but for slats position (if supported by the device).
  • slat_rel same as rel but for slats position (if supported by the device) slat_pos and slat_rel can't be provided simultaneously.

Check the device documentation for more information.

Request for Thermostats (Beta)​

Since version 0.10.0

Request
{
event: "Shelly:CommandRequest", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
data: {
cmd: string, // COMMAND_NAME "target_t"
params: {
id: number, // DEVICE_CHANNEL
value: number, // TARGET_TEMPERATURE
unit: string // TEMPERATURE_UNIT "C" | "F"
}
}
}
  • id identifies the thermostat channel to change, starts from 0.
  • value is the target temperature, expressed in unit.
  • unit is "C" for Celsius or "F" for Fahrenheit. A value in Fahrenheit is converted to Celsius before it is sent to the device.

The command is supported by the following devices:

  • Wall Display - translated to Thermostat.SetConfig with config.target_C.
  • BLU Gateway Gen3 - translated to BluTrv.Call than to Trv.SetTarget with target_C.
  • Shelly X thermostats - translated to Number.Set on the target temperature. id is not used.

Request for EV Chargers (Beta)​

Since version 0.10.0

Request
{
event: "Shelly:CommandRequest", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
data: {
cmd: string, // COMMAND_NAME "ev_charger"
params: {
id: number, // DEVICE_CHANNEL
charging?: boolean, // START_OR_STOP_CHARGING optional
max_current?: number // CURRENT_LIMIT_IN_AMPS optional
}
}
}
  • id identifies the charger channel, starts from 0. It is 0 on all current models.
  • charging is true to start the charging session or false to stop it.
  • max_current is the charging current limit in amperes. It must be within the device's own range (for example 6 to 16 A).

At least one of charging and max_current must be present. Values must have the exact type: strings such as "true" or "10" are rejected, and no other parameters are allowed.

When both are given, the current limit is applied first and the charging session is started or stopped after that. If the current limit is applied but starting or stopping fails, the new limit stays applied and the response has isok: false.

Stopping a charging session can take several seconds before the response arrives.

Possible res values when isok is false:

  • UNKNOWN_COMMAND - the parameters are invalid, or the device is not an EV charger.
  • ERR_INVALID_DATA - max_current is outside the device range. Nothing is sent to the device.
  • ERR_WRONG_DATA - the channel id does not exist on the device.

The command is supported by the following devices:

  • Shelly X EV chargers, such as the Top AC Portable EV Charger - translated to Number.Set on the current limit and Boolean.Set on the start charging control.

Command Response​

Response
{
event: "Shelly:CommandResponse", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
user: number, // USER_ID device owner
data: {
isok: boolean, // SUCCESS_FLAG
res?: string // MESSAGE optional
}
}
note

A command that does not change the device's state produces no Shelly:StatusOnChange. The response reports success and nothing follows, because status is only sent on change.

JRPC​

Thermostat.SetConfig​

This method falls in the commands section for permissions. All available configurations for Thermostat.SetConfig method can be found in the Wall Display list of useful RPC commands.

Request
{
event: "Shelly:JrpcRequest", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
method: 'Thermostat.SetConfig', // JRPC Method
params: {
id: 0, // DEVICE_CHANNEL, usually 0
config: {
target_C: number // TARGET TEMPERATURE
}
}
}

Cury.Set​

Since version 0.9.0

This method falls in the commands section for permissions. All available parameters for the Cury component can be found in the Cury device documentation.

Sets a slot's heater state, its intensity, or both. At least one of on and intensity must be present.

Request
{
event: "Shelly:JrpcRequest", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
method: 'Cury.Set', // JRPC Method
params: {
id: 0, // DEVICE_CHANNEL, usually 0
slot: string, // "left" | "right"
on: boolean, // optional, heater on or off
intensity: number // optional, 0 to 100, 0 turns the slot off
}
}

intensity sets the level and 0 turns the slot off. on toggles the heater without changing the stored intensity.

Cury.Boost​

Since version 0.9.0

Runs a slot at maximum intensity for the device's configured boost_time.

Request
{
event: "Shelly:JrpcRequest", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
method: 'Cury.Boost', // JRPC Method
params: {
id: 0, // DEVICE_CHANNEL, usually 0
slot: string // "left" | "right"
}
}

Cury.StopBoost​

Since version 0.9.0

Cancels a running boost on a slot.

Request
{
event: "Shelly:JrpcRequest", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
method: 'Cury.StopBoost', // JRPC Method
params: {
id: 0, // DEVICE_CHANNEL, usually 0
slot: string // "left" | "right"
}
}

Cury.SetAwayMode​

Since version 0.9.0

Turns away mode on or off for the whole device.

Request
{
event: "Shelly:JrpcRequest", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
method: 'Cury.SetAwayMode', // JRPC Method
params: {
id: 0, // DEVICE_CHANNEL, usually 0
on: boolean // away mode on or off
}
}

The argument is on. The device reports the same state in its status under away_mode, but sending away_mode as the argument is rejected with JRPC_ERROR and device error -103, "Missing or bad argument 'on'!".

While away mode is on, every other state-modifying Cury method returns an error. Turn it off before sending slot commands.

JRPC Response​

Response
{
event: "Shelly:JrpcResponse", // EVENT_NAME
trid: number, // TRANSACTION_ID
deviceId: string, // DEVICE_ID
response: { // DEVICE_RESPONSE
result?: any,
error?: any
}
}
note

result holds the device's own response to the method, for example null for Cury.Set or {"was_on": true} for Cury.StopBoost. It does not show whether the device's state changed. A call that changes nothing succeeds in the same way and is followed by no Shelly:StatusOnChange.

Actions​

Result constants - data.result

  • OK - All is good.
  • UNAUTHORIZED - Device access is not authorized.
  • WRONG_API_PARAMETERS - Malformed request.
  • WRONG_HOST - Request was made on a wrong host.

Error response WRONG_HOST has an extra parameter host, indicating the actual location of the device. This does not guarantee that the device is currently online there.

Response
{
event: "Integrator:ActionResponse", // event name
trid: number, // transaction id
user: string, // integrator tag
data: {
result: "WRONG_HOST",
deviceId: string,
host: string
}
}

Device Verify​

Verify that the device has a valid integration.

Request
{
event: "Integrator:ActionRequest", // event name
trid: number, // transaction id
data: {
action: "DeviceVerify", // action "DeviceVerify"
deviceId: string, // device id,
}
}
Response
{
event: "Integrator:ActionResponse", // event name
trid: number, // transaction id
user: string, // integrator tag
data: {
result: string, // result constant
deviceId?: string, // optional (if provided in request)
deviceType?: string, // optional (if result is "OK" and device is online)
deviceCode?: string, // optional (if result is "OK" and device is online)
deviceStatus?: {}, // optional (if result is "OK" and device is online)
accessGroups?: string // optional (if result is "OK")
}
}

Keys deviceType, deviceCode and deviceStatus are only available if the device is online in the cloud!

accessGroups

Access given to the integrator for the specific device by the user. Consists of a HEX string value, represented by a single byte, giving us 8 possible groups for access represented by each bit of the byte. Currently there is only one - control that is indicated by the first bit turned ON.

So an accessGroups of 00 means only state changes are sent and no control is present, we refer to this as read-only. Then accessGroups of 01 means group "control" is also activated.

  • 00 (hex) -> 0 0 0 0 0 0 0 0 (binary) read-only
  • 01 (hex) -> 0 0 0 0 0 0 0 1 (binary) active control-group

Device Get Settings​

Retrieve device settings, only if the device is online in the cloud.

Request
{
event: "Integrator:ActionRequest", // event name
trid: number, // transaction id
data: {
action: "DeviceGetSettings", // action "DeviceGetSettings"
deviceId: string, // device id,
}
}
Response
{
event: "Integrator:ActionResponse", // event name
trid: number, // transaction id
user: string, // integrator tag
data: {
result: string, // result constant
deviceId?: string, // optional (if provided in request)
deviceType?: string, // optional (if device is online)
deviceCode?: string, // optional (if device is online)
deviceSettings?: {}, // optional (if device is online)
}
}