Execute Relay Command
Control one or multiple relays. Single-relay and multi-relay control use the same endpoint. For one relay, send one item in relays.
Relay changes in one request are sent as one device command and consume one device-operation allowance. Do not split one batch into consecutive requests.
Endpoint
POST /wlte/v1/devices/{deviceId}/relays/commandsPermission
| Scope | Required | Description |
|---|---|---|
device:control | Yes | Control relays on the specified device |
Request
POST {baseUrl}/wlte/v1/devices/{deviceId}/relays/commands
Authorization: Bearer {accessToken}
Content-Type: application/json
Accept: application/json
Idempotency-Key: <caller-generated unique value>{
"relays": [
{ "index": 1, "action": "ON" },
{ "index": 2, "action": "OFF" }
]
}| Field | Type | Required | Description |
|---|---|---|---|
relays | array | Yes | Non-empty relay operation list |
relays[].index | integer | Yes | Relay index starting at 1; indexes must be unique |
relays[].action | string | Yes | ON, OFF, or JOG |
| Action | Description |
|---|---|
ON | Keep the relay on |
OFF | Keep the relay off |
JOG | Turn on briefly, then turn off using the jog duration stored on the device |
Relay indexes must be within the device capability range. Use List Device Type Definitions to discover relay count and supported actions.
Idempotency-Key
Idempotency-Key is required and identifies one operation intent.
| Scenario | Key usage |
|---|---|
| New user operation | Generate a new key |
| Network timeout with no response | Retry the same request with the original key |
Retry after 429 RATE_LIMITED | Wait, then reuse the original key |
| Device, relay list, or action changes | Generate a new key |
The same key and request return the original command without sending it again. Reusing a key with a different request returns 409 IDEMPOTENCY_CONFLICT. Idempotency records are retained for approximately 48 hours.
Success Response
HTTP status:
202 Accepted{
"code": "COMMAND_ACCEPTED",
"message": "Command accepted.",
"requestId": "req_001",
"data": {
"command": {
"id": "cmd_001",
"deviceId": "abc123456789",
"operation": "device.relay.set",
"status": "SUCCESS",
"params": {
"relays": [
{ "index": 1, "action": "ON" },
{ "index": 2, "action": "OFF" }
]
},
"createdAt": "2026-07-15T08:30:00Z"
},
"state": {
"deviceId": "abc123456789",
"status": "ONLINE",
"peripherals": {
"relays": [
{ "index": 1, "on": true },
{ "index": 2, "on": false }
],
"digitalInputs": [
{ "index": 1, "active": false }
],
"analogInputs": [],
"sensors": []
},
"stateUpdatedAt": "2026-07-15T08:30:00Z"
}
}
}| Field | Type | Required | Description |
|---|---|---|---|
data.command | object | Yes | Command object |
data.command.id | string | Yes | Command ID used to query the result |
data.command.operation | string | Yes | Fixed as device.relay.set |
data.command.params.relays | array | Yes | Normalized operation list |
data.command.status | string | Yes | SENT, SUCCESS, FAILED, or TIMEOUT |
data.command.createdAt | string | Yes | Command creation time in RFC3339 UTC |
data.state | object | No | Latest runtime state included in the device acknowledgement |
data.state.peripherals | object | No | May contain relays, digital inputs, analog inputs, and sensors |
state is returned only when the device response includes usable state. The service does not perform a second device refresh only to fill this field.
Status
SENT: the original command is still waiting for confirmation, usually on an idempotent retry.SUCCESS: the device confirmed execution.FAILED: the platform confirmed that the command did not complete.TIMEOUT: no final confirmation arrived in the wait window; do not treat it as successful.
Use data.command.id with Get Command Result when later confirmation is required.
Possible errors include 400 INVALID_REQUEST, 401 AUTH_REQUIRED, 401 AUTH_INVALID, 401 AUTH_EXPIRED, 403 AUTH_SCOPE_DENIED, 404 DEVICE_NOT_FOUND, 409 DEVICE_BUSY, 409 IDEMPOTENCY_CONFLICT, 422 COMMAND_REJECTED, 422 DEVICE_OFFLINE, 429 RATE_LIMITED, 503 GATEWAY_UNAVAILABLE, and 500 INTERNAL_ERROR.
