Execute a Device Operation
Sends an operation command to a specific relay on a device. Supported actions are ON, OFF, and JOG. The server waits for up to 10 seconds for device confirmation and returns the current command status in data.status.
Rate Limit
| Dimension | Rule | On Limit |
|---|---|---|
| Same application | Maximum 600 relay control requests per 60 seconds | Returns 429 RATE_LIMITED |
| Same device | Maximum 10 relay control requests per 10 seconds | Returns 429 RATE_LIMITED |
| Same relay cooldown | 3-second cooldown after each operation | Returns 429 RATE_LIMITED with Retry-After |
Synchronous Wait
- The first request waits for up to
10seconds - If a terminal result arrives within
10seconds, the response returnsSUCCESS,FAILED, orTIMEOUT - If the caller retries with the same
Idempotency-Keywhile the original request is still waiting for the device, the response may returnSENT TIMEOUTmeans the command was not confirmed within the wait window and must be treated as not confirmed successful
Endpoint
POST /wlte/v1/devices/{deviceId}/relays/{index}/commandsAuthorization Requirements
| Scope | Required | Description |
|---|---|---|
device:control | Yes | Send a relay control command to the target device |
Request
Full URL:
POST {baseUrl}/wlte/v1/devices/{deviceId}/relays/{index}/commandsRequest headers:
Authorization: Bearer {accessToken}
Content-Type: application/json
Accept: application/json
Idempotency-Key: <caller-generated unique string>Path parameters:
| Parameter | Type | Required | Rule |
|---|---|---|---|
deviceId | string | Yes | Must not be empty |
index | integer | Yes | Positive integer, starting from 1 |
Request body:
{
"action": "JOG"
}Body fields:
| Field | Type | Required | Rule |
|---|---|---|---|
action | string | Yes | Must be one of ON, OFF, JOG |
Action descriptions:
| Action | Description |
|---|---|
ON | Relay latches closed |
OFF | Relay latches open |
JOG | Jog: relay closes briefly then opens automatically; duration is determined by the device's persistent configuration |
Idempotency-Key
Idempotency-Key is a required request header. It is a unique string generated by the caller to identify one operation intent. The server uses it to prevent duplicate execution caused by network retries or application-layer retries.
When to generate a new key vs. reuse
| Scenario | Action |
|---|---|
| Sending a new relay operation (regardless of past operations) | Generate a new key |
| Request sent but network timeout — no response received | Reuse the original key on retry |
Received 429 RATE_LIMITED and retrying the relay command | Reuse the original key on retry |
| User triggers a second independent operation (e.g., toggling the relay again) | Generate a new key |
Format requirements
- Length: 1 to 128 characters
- Character set: letters, digits,
-,_ - Recommended: UUID v4, e.g.
550e8400-e29b-41d4-a716-446655440000
Repeated request behavior
- Same client, same path, same key + same body: returns
202 Acceptedwith the original commandid— command is not executed again - Same key but different body: returns
409 IDEMPOTENCY_CONFLICT - The server retains idempotency records for at least
48hours; after expiry the same key is treated as a new request
Network timeout handling flow
- Send the request — the network layer times out with no response
- Resend the same request with the same
Idempotency-Key - The server recognizes the duplicate and returns the command's current status (
SENT,SUCCESS,FAILED, orTIMEOUT) - If the final outcome is still uncertain, poll with the command
idusing Get Command Result
Success Response
HTTP status:
202 AcceptedResponse body (device confirmed success):
{
"code": "COMMAND_ACCEPTED",
"message": "Command accepted.",
"requestId": "req_001",
"data": {
"id": "cmd_001",
"deviceId": "abc123456789",
"relayIndex": 1,
"action": "JOG",
"status": "SUCCESS",
"createdAt": "2026-04-29T00:00:00Z"
}
}Response body (wait window timed out):
{
"code": "COMMAND_ACCEPTED",
"message": "Command accepted.",
"requestId": "req_001",
"data": {
"id": "cmd_001",
"deviceId": "abc123456789",
"relayIndex": 1,
"action": "JOG",
"status": "TIMEOUT",
"createdAt": "2026-04-29T00:00:00Z"
}
}Status Semantics
SENT: the command has been accepted and is still waiting for final device confirmation. This status mainly appears on repeated requests using the sameIdempotency-Keyor on subsequent pollingSUCCESS: the device confirmed successFAILED: the command did not complete successfullyTIMEOUT: the final outcome was not confirmed within the wait window; treat as not confirmed successful
Response data Schema
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique command identifier; persist this for subsequent result polling |
deviceId | string | Yes | Device identifier |
relayIndex | integer | Yes | Relay index, starting from 1 |
action | string | Yes | Command action. Enum: ON, OFF, JOG |
status | string | Yes | Command status. Enum: SENT, SUCCESS, FAILED, TIMEOUT |
createdAt | string | Yes | Command creation time in RFC3339 UTC |
Error Responses
Possible responses:
400 INVALID_REQUEST401 AUTH_REQUIRED401 AUTH_INVALID401 AUTH_EXPIRED403 AUTH_SCOPE_DENIED404 DEVICE_NOT_FOUND409 IDEMPOTENCY_CONFLICT422 COMMAND_REJECTED422 DEVICE_OFFLINE429 RATE_LIMITED503 GATEWAY_UNAVAILABLE500 INTERNAL_ERROR
429 RATE_LIMITED Response Body
When a rate limit is triggered, the response includes a data field describing which limit was hit:
{
"code": "RATE_LIMITED",
"message": "Too many requests",
"requestId": "req_001",
"data": {
"retryAfterSeconds": 3
}
}retryAfterSeconds carries the same value as the Retry-After response header, in seconds.
