Litmus Edge 4.4.x - DeviceHub: Devices
List Devices
POST {{edgeUrl}}/devicehub/v2
List Devices
Returns every configured device in DeviceHub along with the most commonly needed fields. This is the richer projection used by the LE UI's device list and by automation that needs to enumerate devices and their parameters in one call.
For a minimal (ID + Name) projection used by the dashboard tile, see Dashboard > List of Devices.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Request body (GraphQL)
query ListDevices {
ListDevices {
ID
Name
DriverID
AliasTopics
CreationTime
Description
WorkerParams {
Name
Value
Description
}
DHParams {
Name
Value
Description
}
}
}
ListDevices accepts an optional input: { IDs: [ID!] } filter (omit to return every device). Any field on Device can be added to the selection, including Properties, MetaData, Topics, StatusPollingRegister, StoppedState, Debug.
Response
200 OK -- application/json
| Field | GraphQL type | Description |
|---|---|---|
ID |
ID |
Device UUID. Used as {{deviceID}} in REST endpoints and as the foreign key from tags/registers. |
Name |
String |
Display name of the device. Must be unique across the device list. |
DriverID |
ID |
UUID of the driver template bound to this device. Not re-assignable; create a new device to change drivers. |
AliasTopics |
Boolean |
true means published MQTT topics use the human-readable register name; false means the raw register key. |
CreationTime |
Time |
ISO 8601 timestamp the device was created. 1970-01-01T00:00:00Z for devices created before this field was introduced. |
Description |
String |
Free-form description set by the operator. |
WorkerParams |
[Param!]! |
Internal worker tunables (poll interval, batching, etc.). Each entry has Name, Value, Description. |
DHParams |
[Param!]! |
DeviceHub-level parameters, same {Name,Value,Description} shape. Driver-agnostic settings. |
Example response
{
"data": {
"ListDevices": [
{
"ID": "41FBD12E-C6CD-4539-AD50-336D278B207C",
"Name": "Rack 2b M258",
"DriverID": "2AF1FA08-D638-11E9-BB65-2A2AE2DBCCE4",
"AliasTopics": false,
"CreationTime": "1970-01-01T00:00:00Z",
"Description": "",
"WorkerParams": [
{
"Name": "PublishOnPollingInterval",
"Value": "true",
"Description": "true"
}
],
"DHParams": []
}
]
}
}
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown DriverID, etc.). |
NOT_FOUND |
The targeted device, driver, or related entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
query ListDevices {
ListDevices {
ID
Name
DriverID
AliasTopics
CreationTime
Description
WorkerParams {
Name
Value
Description
}
DHParams {
Name
Value
Description
}
}
}
Response
Status: 200 OK
{
"data": {
"ListDevices": [
{
"ID": "41FBD12E-C6CD-4539-AD50-336D278B207C",
"Name": "Rack 2b M258",
"DriverID": "2AF1FA08-D638-11E9-BB65-2A2AE2DBCCE4",
"AliasTopics": false,
"CreationTime": "1970-01-01T00:00:00Z",
"Description": "",
"WorkerParams": [
{
"Name": "PublishOnPollingInterval",
"Value": "true",
"Description": "true"
}
],
"DHParams": [
{
"Name": "WatchDogPeriod",
"Value": "30",
"Description": "30"
},
{
"Name": "WatchDog",
"Value": "true",
"Description": "true"
}
]
}
]
}
}
Create New Device
POST {{edgeUrl}}/devicehub/v2
Create New Device
Creates a single device bound to a driver template. The Properties array supplies the values for every property declared by the driver, and any property the driver marks as Required must be present here. The returned ID is the canonical device UUID used in every subsequent call.
Set StoppedState: true if you want the device to be created but not attempt to connect yet -- useful when you are programmatically populating properties or want to attach registers before the first poll. To start the device later, call Start Device.
Requires: a
DriverIDfromList of Drivers by DriverID and GroupID(ListDriverGroups). ThePropertieskeys come from that driver'sGetDriverDeviceProperties. Send the same input toValidate Create Devicefirst: it returnsErrors[](for exampleDriverID: Unknown DriverID) and creates nothing.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Request body (GraphQL)
mutation CreateDevice($input: CreateDeviceRequest!) {
CreateDevice(input: $input) {
ID
Name
DriverID
Description
}
}
Variables (input: CreateDeviceRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
DriverID |
ID |
Yes | UUID of the driver template. List drivers via DeviceHub > Drivers > List Drivers. |
Name |
String |
Yes | Display name. Must be unique across all devices. |
Properties |
[KeyValueInput!]! |
Yes | Driver-defined property values. Each entry is {Key, Value}. Required properties depend on the driver -- see the driver's template via DeviceHub > Drivers > Get Driver. |
Description |
String |
No | Free-form description shown in the UI. |
AliasTopics |
Boolean |
No | Default false. true makes published MQTT topics use the human register name instead of the raw key. |
Debug |
Boolean |
No | Default false. Enables verbose driver logging for this device. |
MetaData |
[KeyValueInput!] |
No | Operator-controlled metadata (e.g. vendor, model, fw_ver). Surfaced in the UI and downstream pipelines. |
StatusRegister |
RegisterInput |
No | Register definition whose value DeviceHub treats as the device's connection-status signal. null disables. |
StoppedState |
Boolean |
No | Default false. true creates the device in a stopped state -- no connection attempt until Start Device. |
Variables (example)
{
"input": {
"DriverID": "5BC98836-CFD4-11E9-BB65-2A2AE2DBCCE4",
"Name": "apiTestDevice",
"Description": "deviceCreatedfromAPI",
"AliasTopics": true,
"Debug": false,
"MetaData": [],
"Properties": [
{ "Key": "name", "Value": "apiTestDevice" },
{ "Key": "description", "Value": "deviceCreatedfromAPI" }
],
"StatusRegister": null,
"StoppedState": false
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.CreateDevice.ID |
ID |
UUID of the newly created device. Save this as {{deviceID}}. |
data.CreateDevice.Name |
String |
Device name echoed back. |
data.CreateDevice.DriverID |
ID |
Driver UUID echoed back. |
data.CreateDevice.Description |
String |
Description echoed back. |
{
"data": {
"CreateDevice": {
"ID": "36B0FDFA-AFC8-4B84-B0B0-296893DB18ED",
"Name": "apiTestDevice",
"DriverID": "5BC98836-CFD4-11E9-BB65-2A2AE2DBCCE4",
"Description": ""
}
}
}
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown DriverID, etc.). |
NOT_FOUND |
The targeted device, driver, or related entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
Common BAD_USER_INPUT causes
DriverIDdoes not match any installed driver.- A required property for the driver is missing from
Properties. - A property value fails the driver's type/regex constraints (e.g. a port number outside
0..65535, an enum value not inListValues). Namecollides with an existing device.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
mutation CreateDevice($input: CreateDeviceRequest!) {
CreateDevice(input: $input) {
ID
Name
DriverID
Description
}
}
Variables
{
"input": {
"AliasTopics": true,
"Debug": false,
"MetaData": [],
"Name": "apiTestDevice",
"Description": "",
"Properties": [
{
"Key": "name",
"Value": "apiTestDevice"
},
{
"Key": "description",
"Value": "deviceCreatedfromAPI"
}
],
"StatusRegister": null,
"StoppedState": false,
"DriverID": "5BC98836-CFD4-11E9-BB65-2A2AE2DBCCE4"
}
}
Response
Status: 200 OK
{
"data": {
"CreateDevice": {
"ID": "36B0FDFA-AFC8-4B84-B0B0-296893DB18ED",
"Name": "apiTestDevice",
"DriverID": "5BC98836-CFD4-11E9-BB65-2A2AE2DBCCE4",
"Description": ""
}
}
}
Update Device
POST {{edgeUrl}}/devicehub/v2
Update Device
Note:
UpdateDeviceRequesthas noDriverIDand noStoppedState. A device cannot be moved to another driver; create a new device instead. UseStart Device/Stop Deviceto change whether it runs.
Replaces the mutable fields of an existing device. Update Device is a full replacement of the input shape, not a JSON-patch: every value you include is written, every value you omit is left at its server-side default. Provide the full Properties array even when changing a single key, otherwise unspecified keys are reset.
Use this to:
- Re-key the device (
Name). - Re-target a different host (
Properties->networkAddress,networkPort, etc.). - Toggle
DebugorAliasTopics. - Refresh
MetaDatasuch asvendor,model,fw_ver. - Reassign the
StatusRegisterused to compute the device's online/offline state.
You cannot change DriverID. To switch drivers, delete the device and create a new one with the desired driver.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Request body (GraphQL)
mutation UpdateDevice($input: UpdateDeviceRequest!) {
UpdateDevice(input: $input) {
ID
Name
DriverID
Description
Debug
Properties { Name Value Description }
Topics { Direction Encoding Format IntervalMs Topic }
MetaData { Name Value Description }
AliasTopics
CreationTime
StatusPollingRegister {
Name
ValueType
Properties { Name Value Description }
}
}
}
The selection set in the response is yours to choose; the example above mirrors the LE UI's projection.
Variables (input: UpdateDeviceRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the device to update. |
Name |
String |
Yes | New name. Must remain unique across devices. |
Description |
String |
No | Free-form description. |
Properties |
[KeyValueInput!]! |
Yes | Full driver property set. Send the complete list -- omitted keys are not preserved. |
MetaData |
[KeyValueInput!] |
No | Operator metadata. Same semantics as Properties: it is a full replacement. |
AliasTopics |
Boolean |
No | See Create New Device. |
Debug |
Boolean |
No | See Create New Device. |
StatusRegister |
RegisterInput |
No | Reassign the status register. null removes it. |
Variables (example)
{
"input": {
"ID": "41FBD12E-C6CD-4539-AD50-336D278B207C",
"Name": "Rack 2b M258",
"Description": "Modbus TCP Ethernet Driver",
"AliasTopics": false,
"Debug": false,
"MetaData": [
{ "Key": "device_type", "Value": "PLC" },
{ "Key": "fw_ver", "Value": "v2.0.31.40" },
{ "Key": "model", "Value": "modicon m258" },
{ "Key": "vendor", "Value": "schneider electric" },
{ "Key": "device_mac_addr", "Value": "00:80:f4:41:20:68" }
],
"Properties": [
{ "Key": "name", "Value": "Rack 2b M258" },
{ "Key": "description", "Value": "Modbus TCP Ethernet Driver" },
{ "Key": "networkAddress", "Value": "10.17.0.8" },
{ "Key": "networkPort", "Value": "502" },
{ "Key": "stationId", "Value": "1" },
{ "Key": "Zero-Based Addressing", "Value": "1" }
],
"StatusRegister": null
}
}
Response
200 OK -- application/json. Echoes the new state of the device using the selection set from the request. Server-side defaults are filled in for any optional field you left out.
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown DriverID, etc.). |
NOT_FOUND |
The targeted device, driver, or related entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
Operational note
Updating connection-relevant Properties (host, port, credentials) does not automatically restart the device worker. If the device is already started, the worker is signaled to reconnect; for major topology changes (e.g. switching transport) consider an explicit Stop Device -> update -> Start Device sequence to avoid stale connections.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
mutation UpdateDevice($input: UpdateDeviceRequest!) {
UpdateDevice(input: $input) {
ID
Name
DriverID
Description
Debug
Properties {
Name
Value
Description
}
Topics {
Direction
Encoding
Format
IntervalMs
Topic
}
MetaData {
Name
Value
Description
}
AliasTopics
CreationTime
StatusPollingRegister {
Name
ValueType
Properties {
Name
Value
Description
}
}
}
}
Variables
{
"input": {
"AliasTopics": false,
"Debug": false,
"MetaData": [
{
"Key": "device_type",
"Value": "PLC"
},
{
"Key": "fw_ver",
"Value": "v2.0.31.40"
},
{
"Key": "model",
"Value": "modicon m258"
},
{
"Key": "vendor",
"Value": "schneider electric"
},
{
"Key": "version",
"Value": "schneider modocon 1.01"
},
{
"Key": "device_mac_addr",
"Value": "00:80:f4:41:20:68"
}
],
"Name": "Rack 2b M258",
"Description": "Modbus TCP Ethernet Driver",
"Properties": [
{
"Key": "name",
"Value": "Rack 2b M258"
},
{
"Key": "description",
"Value": "Modbus TCP Ethernet Driver"
},
{
"Key": "networkAddress",
"Value": "10.17.0.8"
},
{
"Key": "networkPort",
"Value": "502"
},
{
"Key": "stationId",
"Value": "1"
},
{
"Key": "Zero-Based Addressing",
"Value": "1"
}
],
"StatusRegister": null,
"ID": "41FBD12E-C6CD-4539-AD50-336D278B207C"
}
}
Response
Status: 200 OK
{
"data": {
"UpdateDevice": {
"ID": "41FBD12E-C6CD-4539-AD50-336D278B207C",
"Name": "Rack 2b M258",
"DriverID": "2AF1FA08-D638-11E9-BB65-2A2AE2DBCCE4",
"Description": "",
"Debug": false,
"Properties": [
{
"Name": "description",
"Value": "Modbus TCP Ethernet Driver",
"Description": "Modbus TCP Ethernet Driver"
},
{
"Name": "name",
"Value": "Rack 2b M258",
"Description": "Rack 2b M258"
},
{
"Name": "Zero-Based Addressing",
"Value": "1",
"Description": "1"
},
{
"Name": "stationId",
"Value": "1",
"Description": "1"
},
{
"Name": "networkPort",
"Value": "502",
"Description": "502"
},
{
"Name": "networkAddress",
"Value": "10.17.0.8",
"Description": "10.17.0.8"
}
],
"Topics": [
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": null,
"Topic": "devicehub.plcstatus.41FBD12E-C6CD-4539-AD50-336D278B207C"
},
{
"Direction": "Input",
"Encoding": "JSON",
"Format": "Command",
"IntervalMs": null,
"Topic": "devicehub.manage.41FBD12E-C6CD-4539-AD50-336D278B207C"
},
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": null,
"Topic": "devicehub.raw.41FBD12E-C6CD-4539-AD50-336D278B207C.>"
}
],
"MetaData": [
{
"Name": "device_type",
"Value": "PLC",
"Description": "PLC"
},
{
"Name": "device_mac_addr",
"Value": "00:80:f4:41:20:68",
"Description": "00:80:f4:41:20:68"
},
{
"Name": "version",
"Value": "schneider modocon 1.01",
"Description": "schneider modocon 1.01"
},
{
"Name": "vendor",
"Value": "schneider electric",
"Description": "schneider electric"
},
{
"Name": "model",
"Value": "modicon m258",
"Description": "modicon m258"
},
{
"Name": "fw_ver",
"Value": "v2.0.31.40",
"Description": "v2.0.31.40"
}
],
"AliasTopics": false,
"CreationTime": "1970-01-01T00:00:00Z",
"StatusPollingRegister": null
}
}
}
Enable/Disable Device Data Storage
PUT {{edgeUrl}}/stats/devices/{{deviceID}}
Enable/Disable Device Data Storage
Requires: an existing device. Its storage entry is created together with the device (default
retentionHours: 168,saveAll: false).GET /stats/deviceslists it with the device ID in lowercase, while DeviceHub returns it in uppercase, so compare IDs case-insensitively.
Controls whether DeviceHub persists telemetry from this device to the on-device time-series store. This is the same setting exposed by the Data Storage toggle on the device page in the LE UI.
When saveAll is false, no tag values from this device are persisted (the device still publishes to MQTT/integrations in real time). When true, DeviceHub writes to the local store and retains data for retentionHours, rotating older points out.
This endpoint is REST -- the underlying stats service is not part of the DeviceHub GraphQL surface.
Endpoint
PUT {{edgeUrl}}/stats/devices/{{deviceID}}
Content-Type: application/json
{{deviceID}} is the UUID of the target device. Both the path parameter and the body include the ID; they must match.
Authentication
HTTP Basic Auth. Username is your API token, password is empty. Tokens are managed under System > Access Control > Tokens.
Request body
{
"ID": "{{deviceID}}",
"name": "boiler-01",
"retentionHours": 12,
"saveAll": false
}
| Field | Type | Required | Description |
|---|---|---|---|
ID |
string | Yes | Device UUID. Must match the path parameter. |
name |
string | Yes | Device name. The stats service stores this alongside the ID; pass the current name. |
retentionHours |
integer | Yes | How many hours of data to keep. 0 disables retention even if saveAll: true. |
saveAll |
boolean | Yes | true enables persistence of all of the device's tags; false disables. |
Response
200 OK on success, with an empty body or a small JSON ack depending on build. The change applies immediately to the running worker -- no restart required.
Errors
| HTTP status | When it happens |
|---|---|
400 Bad Request |
Body is missing a required field, or ID in body does not match path. |
401 Unauthorized |
Missing or invalid credentials. |
403 Forbidden |
Token lacks write access to the stats service. |
404 Not Found |
No device exists with the given ID. |
502 / 503 |
Stats service is not running. |
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
{
"ID": "{{deviceID}}",
"name": "boiler-01",
"retentionHours": 12,
"saveAll": false
}
Response
Status: 204 No Content
Delete Devices graphQL
POST {{edgeUrl}}/devicehub/v2
Delete Devices (GraphQL, bulk)
Deletes one or more devices in a single mutation. The operation is bulk by design -- pass a single-element IDs array to delete one device, or a list to delete many atomically.
Deletes cascade to the device's registers/tags, examples in DeviceHub > Tags, and any topic subscriptions tied to the device. They do not delete time-series data already persisted to the stats store; those points age out via the retention policy configured on the stats service.
For a single-device REST equivalent (path-parameter style), see Delete Device Rest.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Request body (GraphQL)
mutation DeleteDevices($input: DeleteDevicesRequest!) {
DeleteDevices(input: $input)
}
Variables (input: DeleteDevicesRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
IDs |
[ID!]! |
Yes | UUIDs of devices to delete. Unknown IDs are ignored (no per-ID error report). |
Variables (example)
{
"input": {
"IDs": [
"4F2715FE-4B84-4223-AFA6-858504803ED7",
"8CDACA9A-FF14-482B-B1A0-F85700525980"
]
}
}
Response
200 OK -- application/json. The mutation returns no data on success.
{
"data": {
"DeleteDevices": null
}
}
A null payload indicates the delete succeeded for the IDs that existed; silently-ignored unknown IDs do not surface as errors here. To confirm a specific device was removed, follow up with List Devices or Get Device.
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown DriverID, etc.). |
NOT_FOUND |
The targeted device, driver, or related entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
mutation DeleteDevices ($input : DeleteDevicesRequest!) {
DeleteDevices(input: $input)
}
Variables
{
"input": {
"IDs": [
"4F2715FE-4B84-4223-AFA6-858504803ED7",
"8CDACA9A-FF14-482B-B1A0-F85700525980"
]
}
}
Response
Status: 200 OK
{
"data": {
"DeleteDevices": null
}
}
Delete Device Rest
DELETE {{edgeUrl}}/devicehub/devices/{{deviceID}}
Delete Device (REST, single)
Deletes a single device identified by path parameter. This is the REST equivalent of Delete Devices graphQL with a one-element IDs array. The GraphQL form is preferred for new automation -- this REST endpoint exists mainly for legacy clients.
Side effects are identical to the GraphQL form: the device's registers, topic subscriptions, and configuration are removed. Persisted time-series data ages out via the stats retention policy.
Endpoint
DELETE {{edgeUrl}}/devicehub/devices/{{deviceID}}
{{deviceID}} is the UUID of the device to delete.
Authentication
HTTP Basic Auth. Username is your API token, password is empty. Tokens are managed under System > Access Control > Tokens.
Parameters
| Location | Name | Required | Description |
|---|---|---|---|
| Path | {{deviceID}} |
Yes | UUID of the device to delete. |
No request body.
Response
204 No Content on success.
Errors
| HTTP status | When it happens |
|---|---|
401 Unauthorized |
Missing or invalid credentials. |
403 Forbidden |
Token lacks delete access to DeviceHub. |
404 Not Found |
No device exists with the given ID. (The GraphQL form silently ignores; this one surfaces a 404.) |
502 / 503 |
DeviceHub service is unreachable. |
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Response
Status: 204 No Content
Device Discovery Tool
POST {{edgeUrl}}/devicehub/v2
Device Discovery Tool
Asks a driver to enumerate discoverable endpoints/servers reachable from its configured network neighborhood, without creating a device first. The returned DiscoveryOptions array is a menu of pre-filled property bundles the operator can pick from to spawn a device.
This feature is only available for protocols that support discovery. As of LE 4.0 those are:
- BACnet (the
BacnetIPdriver) - OPC UA (the
OPC UA Client Advanceddriver)
Other drivers return an empty DiscoveryOptions array.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Request body (GraphQL)
query Discovery($input: DiscoveryRequest!) {
Discovery(input: $input) {
DiscoveryOptions {
Label
Description
Fields {
Name
Type
Value
}
}
}
}
Variables (input: DiscoveryRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
DriverID |
ID |
Yes | UUID of a discovery-capable driver (BACnet or OPC UA Advanced). |
Properties |
[KeyValueInput!]! |
Yes | Driver-specific seed properties controlling the search scope. For OPC UA, this is the discovery/server URL; for BACnet, the local interface and address range. |
Variables (example, OPC UA)
{
"input": {
"DriverID": "2372E68F-BA1B-46E9-BC07-E92CA006B377",
"Properties": [
{
"Key": "Discovery Server URL (Servers and Endpoints Discovery)",
"Value": "opc.tcp://localhost:4840"
},
{
"Key": "Server URL (Endpoints Discovery)",
"Value": "opc.tcp://10.17.2.198:53530/OPCUA/SimulationServer"
}
]
}
}
The exact Keys depend on the driver. List the supported keys via DeviceHub > Drivers > Get Driver and inspect the driver template's discovery-related properties.
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.Discovery.DiscoveryOptions |
[Option!]! |
Menu of discovered endpoints. Empty array means no devices/endpoints found. |
data.Discovery.DiscoveryOptions[].Label |
String |
Human-readable name (e.g. SimulationServer@DESKTOP - opc.tcp://...). |
data.Discovery.DiscoveryOptions[].Description |
String |
Free-form annotation, often security policy/mode for OPC UA. |
data.Discovery.DiscoveryOptions[].Fields |
[Field!]! |
Pre-filled property values for this option. Pass these as Properties to Create New Device to spawn the device. |
data.Discovery.DiscoveryOptions[].Fields[].Name |
String |
Property key. |
data.Discovery.DiscoveryOptions[].Fields[].Type |
String |
Type hint (String, Int, enum index, etc.). Often null for free-text values. |
data.Discovery.DiscoveryOptions[].Fields[].Value |
String |
Property value to copy into the new device. |
Example response
{
"data": {
"Discovery": {
"DiscoveryOptions": [
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: Basic256Sha256, Security Mode: Sign",
"Fields": [
{ "Name": "SecurityPolicy", "Type": null, "Value": "3" },
{ "Name": "ServerURL", "Type": null, "Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer" }
]
}
]
}
}
}
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown DriverID, etc.). |
NOT_FOUND |
The targeted device, driver, or related entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
Discovery-specific errors
BAD_USER_INPUTwithDriverID is not discoverable: the driver does not support discovery (only BACnet and OPC UA Advanced do).INTERNAL_SERVER_ERRORwith a timeout: the discovery scope was too wide or the upstream server did not respond. Narrow the URL or address range.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
query Discovery($input: DiscoveryRequest!) {
Discovery(input: $input) {
DiscoveryOptions {
Label
Description
Fields {
Name
Type
Value
}
}
}
}
Variables
{
"input": {
"DriverID": "2372E68F-BA1B-46E9-BC07-E92CA006B377",
"Properties": [
{
"Key": "Discovery Server URL (Servers and Endpoints Discovery)",
"Value": "opc.tcp://localhost:4840"
},
{
"Key": "Server URL (Endpoints Discovery)",
"Value": "opc.tcp://10.17.2.198:53530/OPCUA/SimulationServer"
}
]
}
}
Response
Status: 200 OK
{
"data": {
"Discovery": {
"DiscoveryOptions": [
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: Basic256Sha256, Security Mode: Sign",
"Fields": [
{
"Name": "SecurityPolicy",
"Type": null,
"Value": "3"
},
{
"Name": "ServerURL",
"Type": null,
"Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer"
},
{
"Name": "SecurityMode",
"Type": null,
"Value": "1"
}
]
},
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: Basic128Rsa15, Security Mode: SignAndEncrypt",
"Fields": [
{
"Name": "SecurityMode",
"Type": null,
"Value": "2"
},
{
"Name": "ServerURL",
"Type": null,
"Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer"
},
{
"Name": "SecurityPolicy",
"Type": null,
"Value": "1"
}
]
},
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: Aes256Sha256RsaPss, Security Mode: SignAndEncrypt",
"Fields": [
{
"Name": "SecurityPolicy",
"Type": null,
"Value": "5"
},
{
"Name": "ServerURL",
"Type": null,
"Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer"
},
{
"Name": "SecurityMode",
"Type": null,
"Value": "2"
}
]
},
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: Basic128Rsa15, Security Mode: Sign",
"Fields": [
{
"Name": "SecurityPolicy",
"Type": null,
"Value": "1"
},
{
"Name": "SecurityMode",
"Type": null,
"Value": "1"
},
{
"Name": "ServerURL",
"Type": null,
"Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer"
}
]
},
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: Aes256Sha256RsaPss, Security Mode: Sign",
"Fields": [
{
"Name": "SecurityPolicy",
"Type": null,
"Value": "5"
},
{
"Name": "SecurityMode",
"Type": null,
"Value": "1"
},
{
"Name": "ServerURL",
"Type": null,
"Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer"
}
]
},
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: Basic256Sha256, Security Mode: SignAndEncrypt",
"Fields": [
{
"Name": "SecurityPolicy",
"Type": null,
"Value": "3"
},
{
"Name": "ServerURL",
"Type": null,
"Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer"
},
{
"Name": "SecurityMode",
"Type": null,
"Value": "2"
}
]
},
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: None, Security Mode: None",
"Fields": [
{
"Name": "ServerURL",
"Type": null,
"Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer"
},
{
"Name": "SecurityPolicy",
"Type": null,
"Value": "0"
},
{
"Name": "SecurityMode",
"Type": null,
"Value": "0"
}
]
},
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: Aes128Sha256RsaOaep, Security Mode: Sign",
"Fields": [
{
"Name": "ServerURL",
"Type": null,
"Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer"
},
{
"Name": "SecurityPolicy",
"Type": null,
"Value": "4"
},
{
"Name": "SecurityMode",
"Type": null,
"Value": "1"
}
]
},
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: Basic256, Security Mode: SignAndEncrypt",
"Fields": [
{
"Name": "SecurityPolicy",
"Type": null,
"Value": "2"
},
{
"Name": "ServerURL",
"Type": null,
"Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer"
},
{
"Name": "SecurityMode",
"Type": null,
"Value": "2"
}
]
},
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: Basic256, Security Mode: Sign",
"Fields": [
{
"Name": "SecurityPolicy",
"Type": null,
"Value": "2"
},
{
"Name": "SecurityMode",
"Type": null,
"Value": "1"
},
{
"Name": "ServerURL",
"Type": null,
"Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer"
}
]
},
{
"Label": "SimulationServer@DESKTOP-IRI8PIH - opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer",
"Description": "Security Policy: Aes128Sha256RsaOaep, Security Mode: SignAndEncrypt",
"Fields": [
{
"Name": "SecurityPolicy",
"Type": null,
"Value": "4"
},
{
"Name": "SecurityMode",
"Type": null,
"Value": "2"
},
{
"Name": "ServerURL",
"Type": null,
"Value": "opc.tcp://DESKTOP-IRI8PIH:53530/OPCUA/SimulationServer"
}
]
}
]
}
}
}
Device Connection Status
POST {{edgeUrl}}/devicehub/v2
Device Connection Status (subscription)
Streams real-time updates whenever any device's connection state changes (connected, disconnected, reconnecting, error, ...). This is a GraphQL subscription, not a query -- it is designed for clients that hold an open connection and receive a push for every event, not for polling.
The LE UI uses this to live-update the green/red status dots on the device list. Use it from your own dashboards or alerting pipelines for sub-second reactions to device state changes.
Transport
Subscriptions require a long-lived transport. A plain POST to {{edgeUrl}}/devicehub/v2 will return only the first event (or none) and then close. The supported transports are:
| Transport | Path | Notes |
|---|---|---|
WebSocket (graphql-ws) |
wss://{{edgeHost}}/devicehub/v2 |
Preferred. Use subscriptions-transport-ws or graphql-ws on the client. |
Server-Sent Events (SSE) |
{{edgeUrl}}/devicehub/v2 with Accept: text/event-stream |
Best for one-way browser clients without a WS library. |
The Postman item is shown as a POST for documentation and one-shot testing; switch to a Postman WebSocket request (Files > New > WebSocket Request) when you need the streaming behavior.
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Subscription body
subscription DeviceChanged {
DeviceChanged {
DevStatus
DeviceID
}
}
DeviceChanged accepts no arguments and fires for every device. To distinguish events, branch on DeviceID client-side.
Available fields
Selectable fields on DeviceChanged include all of:
| Field | Type | Description |
|---|---|---|
DeviceID |
ID |
UUID of the device whose state changed. |
DevStatus |
String |
New connection state. Common values: Connected, Disconnected, Reconnecting, Error, Starting, Stopped. |
Event shape
Each event has the same data-wrapped shape as a query response:
{
"data": {
"DeviceChanged": {
"DevStatus": "Connected",
"DeviceID": "79F3914E-32A1-4227-AC16-023E627EB26E"
}
}
}
A burst of Reconnecting followed by Connected is normal after network flaps; treat the most recent event as the source of truth.
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown DriverID, etc.). |
NOT_FOUND |
The targeted device, driver, or related entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
Subscription-specific notes
- If the transport closes unexpectedly, reconnect with backoff. There is no replay or "missed events" buffer -- events that occur while you are disconnected are lost.
- On reconnect, also issue
List Devicesto reconcile state.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
subscription DeviceChanged {
DeviceChanged {
DevStatus
DeviceID
}
}
Response
Status: 200 OK
{
"data": {
"DeviceChanged": {
"DevStatus": "Connected",
"DeviceID": "79F3914E-32A1-4227-AC16-023E627EB26E"
}
}
}
Start Device
POST {{edgeUrl}}/devicehub/v2
Start Device
Starts the worker for one or more devices. After StartDevices returns, the device begins polling/connecting and DeviceChanged events will flow for it.
Idempotent for already-running devices -- starting a running device is a no-op and does not return an error.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Request body (GraphQL)
mutation StartDevices($input: StartDevicesRequest!) {
StartDevices(input: $input)
}
Variables (input: StartDevicesRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
IDs |
[ID!]! |
Yes | UUIDs of devices to start. Pass a single-element array for one device. |
Variables (example)
{
"input": {
"IDs": ["{{deviceID}}"]
}
}
Response
200 OK -- application/json. The mutation returns no data on success.
{
"data": {
"StartDevices": null
}
}
A null payload means the start was accepted by DeviceHub. It does not mean the device is connected yet -- subscribe to Device Connection Status or poll List Devices to observe the transition from Starting to Connected.
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown DriverID, etc.). |
NOT_FOUND |
The targeted device, driver, or related entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
mutation StartDevices($input: StartDevicesRequest!) {
StartDevices(input: $input)
}
Variables
{
"input": {
"IDs": [
"{{deviceID}}"
]
}
}
Response
Status: 200 OK
{
"data": {
"StartDevices": null
}
}
Stop Device
POST {{edgeUrl}}/devicehub/v2
Stop Device
Stops the worker for one or more devices. The device disconnects from its upstream system, stops polling, and stops publishing to integrations. Its configuration remains intact -- use Start Device to resume, or Delete Devices graphQL to remove permanently.
Idempotent for already-stopped devices.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Request body (GraphQL)
mutation StopDevices($input: StopDevicesRequest!) {
StopDevices(input: $input)
}
The Postman item names the operation StopDevicesRequest for legacy reasons; the GraphQL operation name is StopDevices and what matters at the server is the field name in the selection set.
Variables (input: StopDevicesRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
IDs |
[ID!]! |
Yes | UUIDs of devices to stop. Pass a single-element array for one device. |
Variables (example)
{
"input": {
"IDs": ["{{deviceID}}"]
}
}
Response
200 OK -- application/json. The mutation returns no data on success.
{
"data": {
"StopDevices": null
}
}
The device transitions through Stopping to Stopped. To observe the transition in real time, subscribe to Device Connection Status.
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown DriverID, etc.). |
NOT_FOUND |
The targeted device, driver, or related entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
mutation StopDevicesRequest($input: StopDevicesRequest!) {
StopDevices(input: $input)
}
Variables
{
"input": {
"IDs": [
"{{deviceID}}"
]
}
}
Response
Status: 200 OK
{
"data": {
"StopDevices": null
}
}
Validate Create Device
POST {{edgeUrl}}/devicehub/v2
Validate Create Device
Dry-run validation for a CreateDevice payload. Runs the exact same checks as Create New Device -- driver-specific property rules, name uniqueness, port ranges -- but creates nothing. Use it to pre-flight a device config from a UI form or bulk import before committing.
The request shape is identical to Create New Device (CreateDeviceRequest), so a payload that validates clean here can be sent to CreateDevice unchanged.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Request body (GraphQL)
query ValidateCreateDevice($input: CreateDeviceRequest!) {
ValidateCreateDevice(input: $input) {
ObjectID
Errors { FullName TextToDisplay }
Warnings { FullName TextToDisplay }
}
}
Arguments
| Argument | GraphQL type | Required | Description |
|---|---|---|---|
input |
CreateDeviceRequest! |
Yes | The exact payload you intend to send to CreateDevice. Required fields: DriverID, Name, Description, Properties, AliasTopics. |
Response
200 OK -- application/json
A null result means the payload is valid -- no errors, no warnings:
{
"data": {
"ValidateCreateDevice": null
}
}
If validation fails, an ObjectValidationResult is returned instead. Each entry pinpoints the offending field:
{
"data": {
"ValidateCreateDevice": {
"ObjectID": null,
"Errors": [
{
"FullName": "Properties.name",
"TextToDisplay": "Already exist"
}
],
"Warnings": null
}
}
}
| Field | Type | Description |
|---|---|---|
ObjectID |
ID |
ID of the object the validation ran against (null for create validation). |
Errors |
[ValidationMessage!] |
Blocking problems. The equivalent create/update call would fail. |
Errors[].FullName |
String |
Dotted path of the offending field (e.g. Properties.name). |
Errors[].TextToDisplay |
String |
Human-readable reason (e.g. Already exist). |
Warnings |
[ValidationMessage!] |
Non-blocking findings. The call would succeed. |
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown ID, etc.). |
NOT_FOUND |
The targeted entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
query ValidateCreateDevice($input: CreateDeviceRequest!) {
ValidateCreateDevice(input: $input) {
ObjectID
Errors { FullName TextToDisplay }
Warnings { FullName TextToDisplay }
}
}
Variables
{
"input": {
"DriverID": "2AF1FA08-D638-11E9-BB65-2A2AE2DBCCE4",
"Name": "apiTestDevice",
"Description": "",
"Properties": [
{
"Key": "networkAddress",
"Value": "192.168.1.100"
},
{
"Key": "networkPort",
"Value": "502"
}
],
"MetaData": [],
"AliasTopics": false,
"StoppedState": true,
"Debug": false,
"StatusRegister": null
}
}
Response
Status: 200 OK
{
"data": {
"ValidateCreateDevice": null
}
}
Can Create Device
POST {{edgeUrl}}/devicehub/v2
Can Create Device
Returns true if the license allows creating another DeviceHub device, false once the licensed device limit is reached. Check it before creating devices in bulk so a long import does not fail midway. The register counterpart is Can Create Register.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Request body (GraphQL)
query CanCreateDevice { CanCreateDevice }
No arguments.
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.CanCreateDevice |
Boolean! |
true if another device can be created, false if the limit is reached. |
{
"data": {
"CanCreateDevice": true
}
}
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown ID, etc.). |
NOT_FOUND |
The targeted entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
query CanCreateDevice { CanCreateDevice }
Response
Status: 200 OK
{
"data": {
"CanCreateDevice": true
}
}
Can Create Register
POST {{edgeUrl}}/devicehub/v2
Can Create Register
Returns true if the device's register/tag capacity allows creating more registers -- i.e. whether the current license limit has headroom. Check it before bulk-creating tags so a long import does not fail midway.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Request body (GraphQL)
query CanCreateRegister { CanCreateRegister }
No arguments.
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.CanCreateRegister |
Boolean |
true if more registers can be created on this device, false if the limit is reached. |
Example response
{
"data": {
"CanCreateRegister": true
}
}
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown ID, etc.). |
NOT_FOUND |
The targeted entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
query CanCreateRegister { CanCreateRegister }
Response
Status: 200 OK
{
"data": {
"CanCreateRegister": true
}
}
Validate Update Device
POST {{edgeUrl}}/devicehub/v2
Validate Update Device
Dry-run validation for an UpdateDevice payload. Runs the same checks as Update Device -- including name-collision detection against other devices -- but changes nothing. Use it to pre-flight edits before committing them.
The request shape is identical to Update Device (UpdateDeviceRequest), so a payload that validates clean here can be sent to UpdateDevice unchanged.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
Authentication
HTTP Basic Auth. Username is your API token, password is empty. The same token is valid across /devicehub/v2, /analytics/v2, /cc, /opcua, and the other LE services.
Request body (GraphQL)
query ValidateUpdateDevice($input: UpdateDeviceRequest!) {
ValidateUpdateDevice(input: $input) {
ObjectID
Errors { FullName TextToDisplay }
Warnings { FullName TextToDisplay }
}
}
Arguments
| Argument | GraphQL type | Required | Description |
|---|---|---|---|
input |
UpdateDeviceRequest! |
Yes | The exact payload you intend to send to UpdateDevice. Required fields: Name, Description, Properties, AliasTopics. ID identifies the device being updated. |
Response
200 OK -- application/json
A null result means the payload is valid -- no errors, no warnings:
{
"data": {
"ValidateUpdateDevice": null
}
}
If validation fails, an ObjectValidationResult is returned instead. Each entry pinpoints the offending field:
{
"data": {
"ValidateUpdateDevice": {
"ObjectID": "7D9B6AE2-9FA8-454A-BC50-1E6C5398BB93",
"Errors": [
{
"FullName": "Properties.name",
"TextToDisplay": "Already exist"
}
],
"Warnings": null
}
}
}
| Field | Type | Description |
|---|---|---|
ObjectID |
ID |
ID of the object the validation ran against (null for create validation). |
Errors |
[ValidationMessage!] |
Blocking problems. The equivalent create/update call would fail. |
Errors[].FullName |
String |
Dotted path of the offending field (e.g. Properties.name). |
Errors[].TextToDisplay |
String |
Human-readable reason (e.g. Already exist). |
Warnings |
[ValidationMessage!] |
Non-blocking findings. The call would succeed. |
Errors
GraphQL endpoints return 200 OK even on logical errors. Inspect the errors array in the response body:
{ "errors": [ { "message": "...", "path": ["..."], "extensions": { "code": "..." } } ] }
extensions.code |
Meaning |
|---|---|
UNAUTHENTICATED |
Missing or invalid API token. |
FORBIDDEN |
Token lacks permission for this operation. |
BAD_USER_INPUT |
Invalid argument (wrong type, missing required field, malformed UUID, unknown ID, etc.). |
NOT_FOUND |
The targeted entity does not exist. |
INTERNAL_SERVER_ERROR |
DeviceHub fault. Retry, then escalate via System > Support. |
A non-200 HTTP response means DeviceHub itself is unreachable. See Dashboard > DeviceHub Status.
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Request Body
GraphQL Query
query ValidateUpdateDevice($input: UpdateDeviceRequest!) {
ValidateUpdateDevice(input: $input) {
ObjectID
Errors { FullName TextToDisplay }
Warnings { FullName TextToDisplay }
}
}
Variables
{
"input": {
"ID": "{{deviceID}}",
"Name": "apiTestDeviceRenamed",
"Description": "",
"Properties": [
{
"Key": "networkPort",
"Value": "503"
}
],
"MetaData": [],
"AliasTopics": false,
"Debug": false,
"StatusRegister": null
}
}
Response
Status: 200 OK
{
"data": {
"ValidateUpdateDevice": null
}
}
List Device Data Storage Settings
GET {{edgeUrl}}/stats/devices
List Device Data Storage Settings
Data storage settings for every DeviceHub device: whether its tag values are saved to the time-series database and for how long. Pairs with Enable/Disable Device Data Storage, which changes them for one device.
Endpoint
GET {{edgeUrl}}/stats/devices
Authentication
HTTP Basic Auth. Username is your API token, password is empty. Tokens are managed under System > Access Control > Tokens.
Parameters
None.
Response
200 OK -- application/json. One entry per device.
| Field | Type | Description |
|---|---|---|
ID |
string | DeviceHub device UUID. |
name |
string | Device name. |
saveAll |
boolean | true when all tag values are stored. |
retentionHours |
integer | How long stored values are kept, in hours. |
[
{ "name": "CS1_HMC02", "retentionHours": 24, "saveAll": true, "ID": "b32dd3c7-3ee9-53e0-9881-4793ab61609a" }
]
Errors
| HTTP status | When it happens |
|---|---|
400 Bad Request |
Missing or malformed query/body parameter. |
401 Unauthorized |
Missing or invalid credentials. |
403 Forbidden |
Token lacks permission for this operation. |
404 Not Found |
Target entity does not exist. |
5xx |
Service is unreachable, restarting, or internally errored. Inspect device logs under System > Support. |
TLS note: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.
Response
Status: 200 OK
[
{
"name": "CS1_VMC01",
"retentionHours": 24,
"saveAll": true,
"ID": "a79ebf3c-9360-58f4-a190-3cbf94f57689"
},
{
"name": "CS1_LATHE02",
"retentionHours": 24,
"saveAll": true,
"ID": "c6995533-6bb2-5dbe-85b8-1919569d9f72"
},
{
"name": "CS1_HMC02",
"retentionHours": 24,
"saveAll": true,
"ID": "b32dd3c7-3ee9-53e0-9881-4793ab61609a"
},
{
"name": "CS1_MOULD02",
"retentionHours": 24,
"saveAll": true,
"ID": "bcac471b-319f-5c27-9aab-89760ac4169b"
},
{
"name": "CS1_LATHE01",
"retentionHours": 24,
"saveAll": true,
"ID": "32d87092-bf3c-52c3-9a57-49286dc483d0"
},
{
"name": "CS1_MOULD01",
"retentionHours": 24,
"saveAll": true,
"ID": "5b02049c-7a99-54a7-9c2c-e3a2323e2b52"
},
{
"name": "CS1_HMC01",
"retentionHours": 24,
"saveAll": true,
"ID": "d0913370-6d6d-518a-a4bb-7e529b6a6d47"
},
{
"name": "CS1_MT01",
"retentionHours": 24,
"saveAll": true,
"ID": "ef3cc025-292e-5ae9-8c8f-f51c016c9630"
},
{
"name": "CS1_VMC02",
"retentionHours": 24,
"saveAll": true,
"ID": "f9df967c-5981-5f38-b195-0a1bdf961e6f"
},
{
"name": "CS1_MILL5X01",
"retentionHours": 24,
"saveAll": true,
"ID": "3d004430-1b81-5a7e-b3de-5b0d4ca58548"
}
]