Device Commands
A device command is a temporary power-control instruction that is effective between an absolute start and end timestamp. It is intended for one-time dispatch rather than persistent configuration or recurring schedules.
Commands are asynchronous. The response to a submission confirms that Pylontech OpenAPI accepted the request, not that the device has completed it.
Command Model
A command contains:
json
{
"powerControl": {
"targetBatteryPowerW": -3000
},
"startTime": "2025-10-11T00:00:00Z",
"endTime": "2025-10-11T01:00:00Z"
}startTime and endTime are ISO 8601 UTC timestamps. The command is effective only within that time window.
powerControl must contain at least one control property. Properties not included in the request keep the device's existing settings.
Power Control
The current command model supports:
| Property | Meaning |
|---|---|
targetBatteryPowerW | Target battery power. Positive values discharge the battery; negative values charge it. |
chargeCutoffSocPercent | SOC at which charging stops. |
dischargeCutoffSocPercent | SOC below which discharging stops. |
siteImportLimitW | Temporary site import power limit. |
siteExportLimitW | Temporary site export power limit. |
The accepted range depends on both the API schema and the capability of the target device. A syntactically valid value can still be rejected when it exceeds the device capability range.
Lifecycle
text
received ──► executing ──► completed
│ │
└─────────────┴──────► cancelled| Status | Meaning |
|---|---|
received | The platform has accepted the command. Execution has not yet started. |
executing | The command is currently effective on the device. |
completed | The command reached the end of its execution lifecycle. |
cancelled | The command was cancelled manually or by the platform. |
The status response may also include the time the command was received, started, completed, or cancelled.
Send a Command
Submit a command for one device:
http
POST /device/{deviceId}/commands
Authorization: Bearer {access_token}
Content-Type: application/jsonA successful request returns HTTP 202 Accepted and a command ID:
json
{
"id": "command-001",
"message": "Command received",
"timestamp": "2025-10-10T23:59:00Z"
}Store the returned ID and use it to query the execution state.
Query Command Status
Query a command by device ID and command ID:
http
GET /devices/{deviceId}/commands/{commandId}
Authorization: Bearer {access_token}The response contains the submitted control values, effective time window, current status, and the status timestamps available at that point in the lifecycle.
Open Query command execution status
Query Command History
Command history can be filtered by status and queried within a required UTC time range. The current maximum query range is 30 days.
Open Get device command history
Cancel a Command
A command can be cancelled while it is pending or executing:
http
PUT /devices/{deviceId}/commands/{commandId}/cancel
Authorization: Bearer {access_token}An already completed command cannot be cancelled and returns a conflict response.
Cancellation Reasons
A command can enter cancelled for the following reasons:
| Reason | Meaning |
|---|---|
manuallyCancel | The command was explicitly cancelled. |
timeWindowOverlap | Its effective window conflicts with another command. |
startTimeExpire | The start time expired before execution could begin. |
deviceFault | A device fault prevented or stopped execution. |
notSupported | The target device does not support the requested control. |
Batch Commands
Batch dispatch sends the same command to up to 50 devices:
json
{
"devices": [
"device-001",
"device-002"
],
"command": {
"powerControl": {
"targetBatteryPowerW": -3000
},
"startTime": "2025-10-11T00:00:00Z",
"endTime": "2025-10-11T01:00:00Z"
}
}The submission response returns a batchCommandId. Batch cancellation returns the result for each affected device and can contain both successful and failed cancellations.
Command Conflicts
Commands for the same device must not have overlapping effective time windows. If a new command overlaps an existing command, the platform rejects the new command. It does not replace or automatically cancel the existing command.
To execute the new command, first manually cancel the existing command through the cancel endpoint. Submit the new command only after the cancellation succeeds.