LitmusEdge 4.0.x API Documentation/DeviceHub/Tags - LE, LEM, LUNS API Docs
List All Tags
POST {{edgeUrl}}/devicehub/v2
List All Tags
Returns a paginated roster of every tag (Register) on every device. Use this to render the global "Tags" page in the UI, or to bulk-export tag metadata to an external system.
This is the cross-device counterpart of List Registers from Single Device. If you already know which device you want, the single-device endpoint is much cheaper.
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 ListRegisters {
ListRegistersFromAllDevices(input: { Limit: 100 }) {
TotalCount
Registers {
ID
DeviceID
TagName
Description
ValueType
PublishCoV
TagFormula
}
}
}
Arguments (input: ListRegistersFromAllDevicesRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
Limit |
Int |
Yes | Page size, 1..1000. Larger values are clamped to 1000. |
ContinueFrom |
ID |
No | Cursor from the previous page. Omit (or null) on the first page. |
The selection on Registers is yours to expand -- the example uses the small projection. Available fields include Name, Properties, Topics, MetaData, Description.
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.ListRegistersFromAllDevices.TotalCount |
Int |
Server-wide total. Use to render a progress bar across pages. |
data.ListRegistersFromAllDevices.Registers |
[Register!]! |
One page of registers. |
Registers[].ID |
ID |
Register UUID. |
Registers[].DeviceID |
ID |
UUID of the parent device. |
Registers[].TagName |
String |
Operator-chosen alias used in topics and downstream pipelines. |
Registers[].Description |
String |
Free-form description. |
Registers[].ValueType |
String |
One of int, uint, int64, uint64, float32, float64, bool, string, bytes. Driver-dependent. |
Registers[].PublishCoV |
Boolean |
If true, publish only on Change-of-Value (CoV) rather than every poll. |
Registers[].TagFormula |
String |
Optional expression evaluated on every read (e.g. value * 0.1 + 32). null for raw values. |
Pagination
When the response contains Limit items, request the next page using the last ID you received as ContinueFrom. Stop when fewer than Limit items come back (or when Last == true if you selected that field on related endpoints).
Example response
{
"data": {
"ListRegistersFromAllDevices": {
"TotalCount": 11,
"Registers": [
{
"ID": "1A5572B2-8242-40C8-BC63-FFEBC7DAF1E4",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"TagName": "apiTag1",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
}
]
}
}
}
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 ListRegisters {
ListRegistersFromAllDevices(input: {Limit: 100}) {
TotalCount
Registers {
ID
DeviceID
TagName
Description
ValueType
PublishCoV
TagFormula
}
}
}
Response
Status: 200 OK
{
"data": {
"ListRegistersFromAllDevices": {
"TotalCount": 11,
"Registers": [
{
"ID": "1A5572B2-8242-40C8-BC63-FFEBC7DAF1E4",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"TagName": "apiTag1",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
},
{
"ID": "0BB9BE0A-EBC8-4932-9CCC-D9E3A994D986",
"DeviceID": "89C52E9A-0901-4D8D-B842-7B533F64E1B7",
"TagName": "motionTopic8",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
},
{
"ID": "2ADE6AFF-A950-413B-82EA-2D142A76C741",
"DeviceID": "89C52E9A-0901-4D8D-B842-7B533F64E1B7",
"TagName": "motionTopic1",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
},
{
"ID": "5DA5BD59-D25E-488C-A37B-B0E90649F22D",
"DeviceID": "89C52E9A-0901-4D8D-B842-7B533F64E1B7",
"TagName": "motionTopic6",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
},
{
"ID": "665E3EA1-7FFA-469F-ADCB-F9FB5472D16B",
"DeviceID": "89C52E9A-0901-4D8D-B842-7B533F64E1B7",
"TagName": "motionTopic5",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
},
{
"ID": "A8091B99-DBCD-4C9B-BEE1-EE571D84797A",
"DeviceID": "89C52E9A-0901-4D8D-B842-7B533F64E1B7",
"TagName": "motionTopic0",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
},
{
"ID": "A9D97FFC-72B6-4775-AA5E-895378650B74",
"DeviceID": "89C52E9A-0901-4D8D-B842-7B533F64E1B7",
"TagName": "motionTopic2",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
},
{
"ID": "E3DEC8C0-EE07-4D7F-8525-26C585E2B603",
"DeviceID": "89C52E9A-0901-4D8D-B842-7B533F64E1B7",
"TagName": "motionTopic3",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
},
{
"ID": "E4E22269-5B67-4EF2-BFD8-578072AE1A29",
"DeviceID": "89C52E9A-0901-4D8D-B842-7B533F64E1B7",
"TagName": "motionTopic4",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
},
{
"ID": "5EAEBA93-B17D-45FC-8291-CA5CFCEFB994",
"DeviceID": "CDC283FB-72E2-42DF-A587-4D6299D70C9A",
"TagName": "sine1",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
},
{
"ID": "A21EB566-296F-41A8-8436-C5C73E2C5448",
"DeviceID": "CDC283FB-72E2-42DF-A587-4D6299D70C9A",
"TagName": "sine2",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
}
]
}
}
}
List Registers from Single Device
POST {{edgeUrl}}/devicehub/v2
List Registers from Single Device
Returns the paginated list of tags belonging to one device, with a richer projection than List All Tags. Use this on a device-detail page or any workflow scoped to a single device.
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 ListRegisters($input: ListRegistersRequest!) {
ListRegisters(input: $input) {
Registers {
ID
DeviceID
Name
TagName
Description
ValueType
Properties { Name Value Description }
Topics { Direction Encoding Format IntervalMs Topic }
PublishCoV
MetaData { Name Value Description }
TagFormula
}
TotalCount
Last
}
}
Variables (input: ListRegistersRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
DeviceID |
ID |
Yes | UUID of the device whose tags to list. |
Limit |
Int |
Yes | Page size, 1..1000. |
ContinueFrom |
ID |
No | Cursor from the previous page (last ID you received). Omit on the first page. |
{
"input": {
"DeviceID": "{{deviceID}}",
"Limit": 10
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.ListRegisters.Registers |
[Register!]! |
One page of registers. |
data.ListRegisters.TotalCount |
Int |
Total tags on this device, regardless of page size. |
data.ListRegisters.Last |
Boolean |
true if this is the final page. Loop until Last == true. |
Register field reference (richer projection)
| Field | Type | Description |
|---|---|---|
ID |
ID |
Register UUID. |
DeviceID |
ID |
Parent device UUID. |
Name |
String |
Register name at the source (driver-defined identifier). |
TagName |
String |
Operator alias used in topics and downstream pipelines. |
Description |
String |
Free-form description. |
ValueType |
String |
Wire type. See List All Tags for the value enumeration. |
Properties |
[Param!]! |
Register properties (e.g. address, pollingInterval, valueType). Schema is determined by the parent driver's SupportedRegisters[].RegisterProperties. |
Topics |
[TopicConfig!]! |
Each topic the register publishes to. Direction = Input / Output; Encoding = JSON / Binary; Format = payload shape; IntervalMs = publish cadence (0 = on every poll). |
PublishCoV |
Boolean |
Change-of-Value publishing mode. |
MetaData |
[Param!]! |
Operator metadata. |
TagFormula |
String |
Optional value transform expression. |
{
"data": {
"ListRegisters": {
"Registers": [
{
"ID": "007398CD-51DC-47B8-A3FD-F51929EA61DF",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "WindSpeed16ProcessVariable",
"Description": "",
"ValueType": "float64",
"Properties": [
{ "Name": "pollingInterval", "Value": "1000", "Description": "" }
],
"Topics": [],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
}
],
"TotalCount": 11,
"Last": false
}
}
}
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 ListRegisters($input: ListRegistersRequest!) {
ListRegisters(input: $input) {
Registers {
ID
DeviceID
Name
TagName
Description
ValueType
Properties {
Name
Value
Description
}
Topics {
Direction
Encoding
Format
IntervalMs
Topic
}
PublishCoV
MetaData {
Name
Value
Description
}
TagFormula
}
TotalCount
Last
}
}
Variables
{
"input": {
"DeviceID": "{{device_id}}",
"Limit": 10
}
}
Response
Status: 200 OK
{
"data": {
"ListRegisters": {
"Registers": [
{
"ID": "007398CD-51DC-47B8-A3FD-F51929EA61DF",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "WindSpeed16ProcessVariable",
"Description": "",
"ValueType": "float64",
"Properties": [
{
"Name": "pollingInterval",
"Value": "1000",
"Description": null
},
{
"Name": "count",
"Value": "1",
"Description": null
},
{
"Name": "formula",
"Value": "sin(t/1000) * 2",
"Description": null
},
{
"Name": "max_value",
"Value": "50",
"Description": null
},
{
"Name": "min_value",
"Value": "0",
"Description": null
},
{
"Name": "address",
"Value": "60",
"Description": null
}
],
"Topics": [
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": 1000,
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.007398CD-51DC-47B8-A3FD-F51929EA61DF"
},
{
"Direction": "Input",
"Encoding": "JSON",
"Format": "Command",
"IntervalMs": null,
"Topic": "devicehub.pollonce.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.007398CD-51DC-47B8-A3FD-F51929EA61DF"
}
],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
},
{
"ID": "01133640-EFBC-44F1-8188-A1447C00A5CC",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "WaterPressure7SetPoint",
"Description": "",
"ValueType": "float64",
"Properties": [
{
"Name": "formula",
"Value": "sin(t/1000) * 2",
"Description": null
},
{
"Name": "max_value",
"Value": "50",
"Description": null
},
{
"Name": "min_value",
"Value": "0",
"Description": null
},
{
"Name": "address",
"Value": "280",
"Description": null
},
{
"Name": "pollingInterval",
"Value": "1000",
"Description": null
},
{
"Name": "count",
"Value": "1",
"Description": null
}
],
"Topics": [
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": 1000,
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.01133640-EFBC-44F1-8188-A1447C00A5CC"
},
{
"Direction": "Input",
"Encoding": "JSON",
"Format": "Command",
"IntervalMs": null,
"Topic": "devicehub.pollonce.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.01133640-EFBC-44F1-8188-A1447C00A5CC"
}
],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
},
{
"ID": "035CD2C9-35CF-405D-A984-1E5DFC816583",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "WaterPressure13ProcessVariable",
"Description": "",
"ValueType": "float64",
"Properties": [
{
"Name": "min_value",
"Value": "0",
"Description": null
},
{
"Name": "address",
"Value": "144",
"Description": null
},
{
"Name": "pollingInterval",
"Value": "1000",
"Description": null
},
{
"Name": "count",
"Value": "1",
"Description": null
},
{
"Name": "formula",
"Value": "sin(t/1000) * 2",
"Description": null
},
{
"Name": "max_value",
"Value": "50",
"Description": null
}
],
"Topics": [
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": 1000,
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.035CD2C9-35CF-405D-A984-1E5DFC816583"
},
{
"Direction": "Input",
"Encoding": "JSON",
"Format": "Command",
"IntervalMs": null,
"Topic": "devicehub.pollonce.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.035CD2C9-35CF-405D-A984-1E5DFC816583"
}
],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
},
{
"ID": "049ED31A-F0A3-491B-92BC-D47E85237174",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "Pressure18ProcessVariable",
"Description": "",
"ValueType": "string",
"Properties": [
{
"Name": "address",
"Value": "34",
"Description": null
},
{
"Name": "pollingInterval",
"Value": "1000",
"Description": null
},
{
"Name": "DB",
"Value": "75",
"Description": null
},
{
"Name": "count",
"Value": "1",
"Description": null
}
],
"Topics": [
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": 1000,
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.049ED31A-F0A3-491B-92BC-D47E85237174"
},
{
"Direction": "Input",
"Encoding": "JSON",
"Format": "Command",
"IntervalMs": null,
"Topic": "devicehub.pollonce.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.049ED31A-F0A3-491B-92BC-D47E85237174"
}
],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
},
{
"ID": "04C0FEB1-227D-400B-87F7-6C8478DA7944",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "WindDuration14SetPoint",
"Description": "",
"ValueType": "string",
"Properties": [
{
"Name": "address",
"Value": "74",
"Description": null
},
{
"Name": "pollingInterval",
"Value": "1000",
"Description": null
},
{
"Name": "DB",
"Value": "155",
"Description": null
},
{
"Name": "count",
"Value": "1",
"Description": null
}
],
"Topics": [
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": 1000,
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.04C0FEB1-227D-400B-87F7-6C8478DA7944"
},
{
"Direction": "Input",
"Encoding": "JSON",
"Format": "Command",
"IntervalMs": null,
"Topic": "devicehub.pollonce.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.04C0FEB1-227D-400B-87F7-6C8478DA7944"
}
],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
},
{
"ID": "05E3241F-43BB-4045-BF69-4A26EE4F5705",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "WindDuration11SetPoint",
"Description": "",
"ValueType": "string",
"Properties": [
{
"Name": "address",
"Value": "68",
"Description": null
},
{
"Name": "pollingInterval",
"Value": "1000",
"Description": null
},
{
"Name": "DB",
"Value": "155",
"Description": null
},
{
"Name": "count",
"Value": "1",
"Description": null
}
],
"Topics": [
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": 1000,
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.05E3241F-43BB-4045-BF69-4A26EE4F5705"
},
{
"Direction": "Input",
"Encoding": "JSON",
"Format": "Command",
"IntervalMs": null,
"Topic": "devicehub.pollonce.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.05E3241F-43BB-4045-BF69-4A26EE4F5705"
}
],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
},
{
"ID": "05FE7CD0-8751-4C0B-AE1F-185B86E974F8",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "WaterDelay16SetPoint",
"Description": "",
"ValueType": "string",
"Properties": [
{
"Name": "count",
"Value": "1",
"Description": null
},
{
"Name": "address",
"Value": "222",
"Description": null
},
{
"Name": "pollingInterval",
"Value": "1000",
"Description": null
},
{
"Name": "DB",
"Value": "155",
"Description": null
}
],
"Topics": [
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": 1000,
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.05FE7CD0-8751-4C0B-AE1F-185B86E974F8"
},
{
"Direction": "Input",
"Encoding": "JSON",
"Format": "Command",
"IntervalMs": null,
"Topic": "devicehub.pollonce.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.05FE7CD0-8751-4C0B-AE1F-185B86E974F8"
}
],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
},
{
"ID": "0671BF01-6365-482B-A08D-404ABB2BB075",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "WindDuration19SetPoint",
"Description": "",
"ValueType": "string",
"Properties": [
{
"Name": "count",
"Value": "1",
"Description": null
},
{
"Name": "address",
"Value": "84",
"Description": null
},
{
"Name": "pollingInterval",
"Value": "1000",
"Description": null
},
{
"Name": "DB",
"Value": "155",
"Description": null
}
],
"Topics": [
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": 1000,
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.0671BF01-6365-482B-A08D-404ABB2BB075"
},
{
"Direction": "Input",
"Encoding": "JSON",
"Format": "Command",
"IntervalMs": null,
"Topic": "devicehub.pollonce.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.0671BF01-6365-482B-A08D-404ABB2BB075"
}
],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
},
{
"ID": "07611094-25D2-4FF5-BD6F-8EB4B00C5CE4",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "WaterDelay13SetPoint",
"Description": "",
"ValueType": "string",
"Properties": [
{
"Name": "address",
"Value": "216",
"Description": null
},
{
"Name": "pollingInterval",
"Value": "1000",
"Description": null
},
{
"Name": "DB",
"Value": "155",
"Description": null
},
{
"Name": "count",
"Value": "1",
"Description": null
}
],
"Topics": [
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": 1000,
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.07611094-25D2-4FF5-BD6F-8EB4B00C5CE4"
},
{
"Direction": "Input",
"Encoding": "JSON",
"Format": "Command",
"IntervalMs": null,
"Topic": "devicehub.pollonce.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.07611094-25D2-4FF5-BD6F-8EB4B00C5CE4"
}
],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
},
{
"ID": "08463862-6FF0-48DB-9B38-3B25AC7F13FC",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "WaterDuration12SetPoint",
"Description": "",
"ValueType": "string",
"Properties": [
{
"Name": "pollingInterval",
"Value": "1000",
"Description": null
},
{
"Name": "DB",
"Value": "155",
"Description": null
},
{
"Name": "count",
"Value": "1",
"Description": null
},
{
"Name": "address",
"Value": "246",
"Description": null
}
],
"Topics": [
{
"Direction": "Output",
"Encoding": "JSON",
"Format": "Raw",
"IntervalMs": 1000,
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.08463862-6FF0-48DB-9B38-3B25AC7F13FC"
},
{
"Direction": "Input",
"Encoding": "JSON",
"Format": "Command",
"IntervalMs": null,
"Topic": "devicehub.pollonce.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.08463862-6FF0-48DB-9B38-3B25AC7F13FC"
}
],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
}
],
"TotalCount": 202,
"Last": false
}
}
}
Create Tag
POST {{edgeUrl}}/devicehub/v2
Create Tag
Creates one or more tags on a device in a single batched mutation. Despite the singular name, this is the batch create endpoint -- pass a single-element Registers array for one tag, or many for bulk.
Tags are validated against the parent device's driver template before they are committed. For a non-destructive pre-flight check, use Validate Update Registers (the same validation surface is reused).
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 CreateRegisters($input: CreateRegistersRequest!) {
CreateRegisters(input: $input) {
ID
DeviceID
Name
TagName
Description
ValueType
PublishCoV
TagFormula
}
}
Variables (input: CreateRegistersRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
Registers |
[RegisterInput!]! |
Yes | One or more register inputs (see below). |
RegisterInput fields
| Field | Type | Required | Description |
|---|---|---|---|
DeviceID |
ID |
Yes | UUID of the device that will own this register. |
Name |
String |
Yes | Source-system register identifier (driver-defined). Not the operator alias. |
TagName |
String |
Yes | Operator alias used in topics and downstream systems. Must be unique within the device. |
ValueType |
String |
Yes | Wire type: int, uint, int64, uint64, float32, float64, bool, string, bytes. |
Properties |
[KeyValueInput!]! |
Yes | Register property values. Keys are defined by the parent driver's SupportedRegisters[N].RegisterProperties. Driver-specific examples include address, pollingInterval, count, formula, valueType. |
Description |
String |
No | Free-form description. |
PublishCoV |
Boolean |
No | Default false. true to publish only on Change-of-Value. |
TagFormula |
String |
No | Optional value-transform expression, applied on every read. |
MetaData |
[KeyValueInput!] |
No | Operator metadata. |
Variables (example)
{
"input": {
"Registers": [
{
"DeviceID": "{{deviceID}}",
"Name": "S",
"TagName": "apiTag",
"ValueType": "float64",
"Description": "",
"PublishCoV": false,
"TagFormula": null,
"MetaData": [],
"Properties": [
{ "Key": "valueType", "Value": "float64" },
{ "Key": "pollingInterval", "Value": "1000" },
{ "Key": "tagName", "Value": "apiTag" },
{ "Key": "description", "Value": "" },
{ "Key": "address", "Value": "1" },
{ "Key": "formula", "Value": "sin(t/1000) * 2" },
{ "Key": "min_value", "Value": "-50" },
{ "Key": "max_value", "Value": "50" },
{ "Key": "count", "Value": "1" }
]
}
]
}
}
Response
200 OK -- application/json. Returns the newly created registers with their server-assigned IDs in the same order as the request.
{
"data": {
"CreateRegisters": [
{
"ID": "1A5572B2-8242-40C8-BC63-FFEBC7DAF1E4",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "apiTag1",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
}
]
}
}
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.
Common BAD_USER_INPUT causes
DeviceIDdoes not exist.Propertiesis missing a key the driver marksRequired.Properties.Valuefails the driver's type or range constraints (e.g.addressout ofNumberMin..NumberMax).TagNamecollides with an existing tag on the same device.ValueTypeis not in the supported set for this driver/register kind.
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 CreateRegisters($input: CreateRegistersRequest!) {
CreateRegisters(input: $input) {
ID
DeviceID
Name
TagName
Description
ValueType
PublishCoV
TagFormula
}
}
Variables
{
"input": {
"Registers": [
{
"PublishCoV": false,
"TagFormula": null,
"MetaData": [],
"Name": "S",
"Description": "",
"DeviceID": "{{deviceID}}",
"Properties": [
{
"Key": "valueType",
"Value": "float64"
},
{
"Key": "pollingInterval",
"Value": "1000"
},
{
"Key": "tagName",
"Value": "apiTag"
},
{
"Key": "description",
"Value": ""
},
{
"Key": "address",
"Value": "1"
},
{
"Key": "formula",
"Value": "sin(t/1000) * 2"
},
{
"Key": "min_value",
"Value": "-50"
},
{
"Key": "max_value",
"Value": "50"
},
{
"Key": "count",
"Value": "1"
}
],
"TagName": "apiTag",
"ValueType": "float64"
}
]
}
}
Response
Status: 200 OK
{
"data": {
"CreateRegisters": [
{
"ID": "1A5572B2-8242-40C8-BC63-FFEBC7DAF1E4",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "apiTag1",
"Description": "",
"ValueType": "float64",
"PublishCoV": false,
"TagFormula": null
}
]
}
}
Update a Tag
POST {{edgeUrl}}/devicehub/v2
Update a Tag
Replaces the mutable fields of one or more existing tags. Despite the singular name, this is a batch update -- pass a single-element Registers array for one tag, or many for bulk.
UpdateRegisters is a full replacement of the input shape, like Update Device. Provide the complete Properties array even when changing a single key; omitted keys are reset to server defaults. The ID field is required on each register input.
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 UpdateRegisters($input: UpdateRegistersRequest!) {
UpdateRegisters(input: $input) {
ID
Name
Description
TagName
DeviceID
ValueType
Properties { Value Name }
Topics { Topic Format Direction Encoding IntervalMs }
PublishCoV
MetaData { Name Value Description Type }
TagFormula
}
}
Variables (input: UpdateRegistersRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
Registers |
[RegisterInput!]! |
Yes | One or more register inputs (see below). |
RegisterInput fields for update
Same as Create Tag, plus:
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the existing register to replace. |
Variables (example)
{
"input": {
"Registers": [
{
"ID": "1A5572B2-8242-40C8-BC63-FFEBC7DAF1E4",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Name": "S",
"TagName": "apiTag",
"ValueType": "float64",
"Description": "",
"PublishCoV": false,
"TagFormula": null,
"MetaData": [],
"Properties": [
{ "Key": "valueType", "Value": "float64" },
{ "Key": "pollingInterval", "Value": "1000" },
{ "Key": "address", "Value": "1" }
]
}
]
}
}
Response
200 OK -- application/json. Echoes the new state of each updated register using the selection from the request.
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.
Operational note
Updating Properties does not stop the device's poller. The new values are picked up on the next poll cycle. For changes that affect addressing or data shape, consider Stop Device -> update -> Start Device to avoid a brief window of stale reads.
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 UpdateRegisters($input: UpdateRegistersRequest!) {
UpdateRegisters(
input: $input
) {
ID
Name
Description
TagName
DeviceID
ValueType
Properties {
Value
Name
}
Topics {
Topic
Format
Direction
Encoding
IntervalMs
}
PublishCoV
MetaData {
Name
Value
Description
Type
}
TagFormula
}
}
Variables
{
"input": {
"Registers": [
{
"PublishCoV": false,
"TagFormula": null,
"MetaData": [],
"Name": "S",
"Description": "",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"Properties": [
{
"Key": "valueType",
"Value": "float64"
},
{
"Key": "pollingInterval",
"Value": "1000"
},
{
"Key": "tagName",
"Value": "apiTag"
},
{
"Key": "description",
"Value": ""
},
{
"Key": "address",
"Value": "1"
},
{
"Key": "formula",
"Value": "sin(t/1000) * 2"
},
{
"Key": "min_value",
"Value": "-50"
},
{
"Key": "max_value",
"Value": "50"
},
{
"Key": "count",
"Value": "1"
}
],
"TagName": "apiTag",
"ValueType": "float64",
"ID": "1A5572B2-8242-40C8-BC63-FFEBC7DAF1E4"
}
]
}
}
Response
Status: 200 OK
{
"data": {
"UpdateRegisters": [
{
"ID": "1A5572B2-8242-40C8-BC63-FFEBC7DAF1E4",
"Name": "S",
"Description": "",
"TagName": "apiTag",
"DeviceID": "779F42F3-54FC-4A87-B9A6-CD39CFA4A97D",
"ValueType": "float64",
"Properties": [
{
"Value": "float64",
"Name": "valueType"
},
{
"Value": "apiTag",
"Name": "tagName"
},
{
"Value": "",
"Name": "description"
},
{
"Value": "sin(t/1000) * 2",
"Name": "formula"
},
{
"Value": "-50",
"Name": "min_value"
},
{
"Value": "1000",
"Name": "pollingInterval"
},
{
"Value": "1",
"Name": "address"
},
{
"Value": "50",
"Name": "max_value"
},
{
"Value": "1",
"Name": "count"
}
],
"Topics": [
{
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.1A5572B2-8242-40C8-BC63-FFEBC7DAF1E4",
"Format": "Raw",
"Direction": "Output",
"Encoding": "JSON",
"IntervalMs": 1000
},
{
"Topic": "devicehub.pollonce.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.1A5572B2-8242-40C8-BC63-FFEBC7DAF1E4",
"Format": "Command",
"Direction": "Input",
"Encoding": "JSON",
"IntervalMs": null
}
],
"PublishCoV": false,
"MetaData": [],
"TagFormula": null
}
]
}
}
Delete Tag/s
POST {{edgeUrl}}/devicehub/v2
Delete Tag/s
Deletes one or more tags by ID. Despite the singular Tag/s, this is the batched delete endpoint -- pass any number of IDs in the array. To remove every tag on a device, use Delete all Tags of a Device instead.
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 DeleteRegisters {
DeleteRegisters(input: {
IDs: [
"C09BCEFB-AE93-4B3E-AA72-54B91E7155E2"
]
})
}
Arguments
| Argument | GraphQL type | Required | Description |
|---|---|---|---|
input.IDs |
[ID!]! |
Yes | UUIDs of registers to delete. Unknown IDs are silently ignored (no per-ID error). |
Response
200 OK -- application/json. The mutation returns no data.
{
"data": {
"DeleteRegisters": null
}
}
To confirm a specific register was removed, follow up with List Registers from Single 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 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
mutation DeleteRegisters {
DeleteRegisters(input: {
IDs: [
"C09BCEFB-AE93-4B3E-AA72-54B91E7155E2"
]
}
)
}
Response
Status: 200 OK
{
"data": {
"DeleteRegisters": null
}
}
Delete all Tags of a Device
POST {{edgeUrl}}/devicehub/v2
Delete all Tags of a Device
Deletes every tag belonging to a single device, in one call. Useful when re-onboarding a device with a different register set, or as part of an automation that wipes-and-recreates from a CSV.
This does not delete or stop the device itself -- only its tags. The device remains configured and can be re-populated via Create Tag, Upload CSV, or DeviceHub > Browse.
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 DeleteDeviceRegisters($input: DeleteDeviceRegistersRequest!) {
DeleteDeviceRegisters(input: $input)
}
Variables (input: DeleteDeviceRegistersRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
DevID |
ID |
Yes | UUID of the device whose tags should all be removed. Note the field name is DevID, not DeviceID. |
{
"input": {
"DevID": "{{deviceID}}"
}
}
Response
200 OK -- application/json. The mutation returns no data.
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
mutation DeleteDeviceRegisters($input: DeleteDeviceRegistersRequest!) {
DeleteDeviceRegisters(input: $input)
}
Variables
{
"input": {
"DevID": "{{deviceID}}"
}
}
Browse Tags
POST {{edgeUrl}}/devicehub/v2
Browse Tags
Browses the native namespace of the upstream system reachable by the device -- e.g. the OPC UA address space, the BACnet object list, or the S7 program structure -- without first persisting registers. Operators typically pick interesting nodes from a browse tree and then create tags from them.
This is a driver capability: only drivers with Meta.BrowseSupported = true (see DeviceHub > Drivers > Get Driver Template by DriverID > Meta) respond meaningfully. Unsupported drivers return a BAD_USER_INPUT error.
This is the inspection endpoint; the cart-style multi-step workflow that selects and imports browse results into actual tags lives in DeviceHub > Browse.
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 Browse($input: BrowseRequest!) {
Browse(input: $input) {
Type
Fields { Name Value }
Leaves {
Type
Fields { Name Value }
}
}
}
Variables (input: BrowseRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
DeviceID |
ID |
Yes | UUID of the device to browse through. |
Path |
[String!] |
Yes | Hierarchy path of the current browse cursor. Pass [] for the root, then append child folder names to descend. |
ForceUpdate |
Boolean |
No | Default false. If true, bypass any cached browse result and re-query the upstream device. |
{
"input": {
"DeviceID": "{{deviceID}}",
"Path": [],
"ForceUpdate": false
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.Browse.Type |
String |
Kind of node at the current Path. Typical values: Folder, Variable, Object. Driver-defined. |
data.Browse.Fields |
[Field!]! |
Metadata for the current node (e.g. name, description, path). |
data.Browse.Leaves |
[Leaf!]! |
Immediate children of the current node. Use one of their Fields[Name='path'] to build the next Path. |
data.Browse.Leaves[].Type |
String |
Kind of the child (Folder to descend further, Variable for a leaf you can turn into a tag). |
data.Browse.Leaves[].Fields |
[Field!]! |
Metadata for the child. |
Example response (root)
{
"data": {
"Browse": {
"Type": "Folder",
"Fields": [
{ "Name": "description", "Value": "" },
{ "Name": "name", "Value": "root" }
],
"Leaves": [
{
"Type": "Folder",
"Fields": [
{ "Name": "path", "Value": "Global" }
]
}
]
}
}
}
To descend, set Path: ["Global"] (or whatever the child's path field holds) and re-issue the query.
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.
Browse-specific errors
BAD_USER_INPUTwithdriver does not support browse: the parent device's driver hasMeta.BrowseSupported = false.INTERNAL_SERVER_ERRORwith a timeout: the upstream device did not respond. Retry withForceUpdate: true, or check the connection state viaDashboard > List of DevicesandDevice Connection 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 Browse($input: BrowseRequest!) {
Browse(input:$input){
Type
Fields {
Name
Value
}
Leaves {
Type
Fields {
Name
Value
}
}
}
}
Variables
{
"input": {
"DeviceID": "{{deviceID}}",
"Path": [],
"ForceUpdate": false
}
}
Response
Status: 200 OK
{
"data": {
"Browse": {
"Type": "Folder",
"Fields": [
{
"Name": "description",
"Value": ""
},
{
"Name": "name",
"Value": "root"
}
],
"Leaves": [
{
"Type": "Folder",
"Fields": [
{
"Name": "path",
"Value": "Global"
},
{
"Name": "name",
"Value": "Global"
},
{
"Name": "description",
"Value": ""
}
]
},
{
"Type": "Folder",
"Fields": [
{
"Name": "path",
"Value": "Program:AM_MCP"
},
{
"Name": "name",
"Value": "Program:AM_MCP"
},
{
"Name": "description",
"Value": ""
}
]
},
{
"Type": "Folder",
"Fields": [
{
"Name": "description",
"Value": ""
},
{
"Name": "path",
"Value": "Program:Cell_Control"
},
{
"Name": "name",
"Value": "Program:Cell_Control"
}
]
},
{
"Type": "Folder",
"Fields": [
{
"Name": "path",
"Value": "Program:Common_Controls"
},
{
"Name": "name",
"Value": "Program:Common_Controls"
},
{
"Name": "description",
"Value": ""
}
]
},
{
"Type": "Folder",
"Fields": [
{
"Name": "path",
"Value": "Program:Data_Transfer"
},
{
"Name": "name",
"Value": "Program:Data_Transfer"
},
{
"Name": "description",
"Value": ""
}
]
},
{
"Type": "Folder",
"Fields": [
{
"Name": "path",
"Value": "Program:DT_MCP"
},
{
"Name": "name",
"Value": "Program:DT_MCP"
},
{
"Name": "description",
"Value": ""
}
]
},
{
"Type": "Folder",
"Fields": [
{
"Name": "description",
"Value": ""
},
{
"Name": "path",
"Value": "Program:Inputs"
},
{
"Name": "name",
"Value": "Program:Inputs"
}
]
},
{
"Type": "Folder",
"Fields": [
{
"Name": "path",
"Value": "Program:IO_Diagnostics"
},
{
"Name": "name",
"Value": "Program:IO_Diagnostics"
},
{
"Name": "description",
"Value": ""
}
]
},
{
"Type": "Folder",
"Fields": [
{
"Name": "path",
"Value": "Program:MainProgram"
},
{
"Name": "name",
"Value": "Program:MainProgram"
},
{
"Name": "description",
"Value": ""
}
]
},
{
"Type": "Folder",
"Fields": [
{
"Name": "path",
"Value": "Program:Outputs"
},
{
"Name": "name",
"Value": "Program:Outputs"
},
{
"Name": "description",
"Value": ""
}
]
},
{
"Type": "Folder",
"Fields": [
{
"Name": "path",
"Value": "Program:Periodic_Control"
},
{
"Name": "name",
"Value": "Program:Periodic_Control"
},
{
"Name": "description",
"Value": ""
}
]
},
{
"Type": "Folder",
"Fields": [
{
"Name": "path",
"Value": "Program:trace"
},
{
"Name": "name",
"Value": "Program:trace"
},
{
"Name": "description",
"Value": ""
}
]
}
]
}
}
}
Upload CSV
POST {{edgeUrl}}/devicehub/v2
Upload CSV (bulk tag import)
Imports tags from a CSV file. This is the multipart equivalent of the Import Tags flow in the LE UI. Use it to seed a fresh device from a spreadsheet, or to keep tag definitions under version control as a CSV and re-apply on each change.
Unlike the other endpoints in this folder, this is a multipart form-data request, not a regular GraphQL JSON body. The shape follows the GraphQL multipart request spec.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: multipart/form-data
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 (form-data parts)
| Form key | Type | Description |
|---|---|---|
operations |
text |
JSON envelope describing the GraphQL operation. Reference the file via null placeholders (see example). |
map |
text |
JSON mapping form file keys to placeholder locations within operations. |
0 |
file |
The CSV payload. The form key (0 here) must match what appears in map. |
operations value
{
"operationName": "UploadCsv",
"variables": { "file": null },
"query": "mutation UploadCsv($file: Upload!) { UploadCsv(file: $file) { Warnings { Error Line LineNumber } } }"
}
map value
{ "0": ["variables.file"] }
CSV format
The CSV must match the schema exported by Download Tags CSV. The first row is a header. The columns are driver-dependent -- export a sample with Download Tags CSV from an existing populated device to discover the exact columns expected.
Response
200 OK -- application/json. The mutation returns per-row outcomes in a Warnings array. Despite the field name, this array carries both informational counts and error rows.
| Field | Type | Description |
|---|---|---|
data.UploadCsv.Warnings |
[Warning!]! |
One entry per row that produced a warning, error, or summary line. |
data.UploadCsv.Warnings[].Error |
String |
Error text or summary (e.g. number of created tags 1, updated: 0, skipped tags: 0). |
data.UploadCsv.Warnings[].Line |
String |
Raw CSV line that produced the entry. Empty for the summary line. |
data.UploadCsv.Warnings[].LineNumber |
Int |
1-indexed CSV row number. 0 for the summary line. |
Example response
{
"data": {
"UploadCsv": {
"Warnings": [
{
"Error": "number of created tags 1, updated: 0, skipped tags: 0",
"Line": "",
"LineNumber": 0
}
]
}
}
}
If the CSV is malformed at the top (bad header, unknown columns), the mutation fails with a BAD_USER_INPUT error before any rows are processed.
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.
Tips
- Round-trip first:
Download Tags CSV-> edit ->Upload CSV. The exported CSV is always re-importable. - For large files, increase your client's request timeout. The mutation is synchronous and can run for tens of seconds on thousands of rows.
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
Response
Status: 200 OK
{
"data": {
"UploadCsv": {
"Warnings": [
{
"Error": "number of created tags 1, updated: 0, skipped tags: 0",
"Line": "",
"LineNumber": 0
}
]
}
}
}
Download Tags CSV
GET {{edgeUrl}}/devicehub/registers/csv?deviceIDs=[Array of Strings]
Download Tags CSV (bulk tag export)
Exports tags belonging to one or more devices as a CSV file. The output format round-trips with Upload CSV -- export, edit, import, and the device returns to the new state.
Endpoint
GET {{edgeUrl}}/devicehub/registers/csv?deviceIDs=<array-of-uuids>
The deviceIDs query parameter is repeatable; encode multiple devices either as ?deviceIDs=A&deviceIDs=B or as a JSON-style array depending on your client. Empty or missing means "export every device".
Authentication
HTTP Basic Auth. Username is your API token, password is empty. Tokens are managed under System > Access Control > Tokens.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
deviceIDs |
string[] | No | Device UUIDs to include. Omit to export every device. The Postman example uses the literal token [Array of Strings] -- replace it with your IDs. |
Response
200 OK -- text/csv with a Content-Disposition: attachment header.
The first row is the header, columns are driver-dependent. Use the Send and Download button in Postman to save the response as a file (otherwise Postman renders the CSV in the body pane).
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
Register/Tag Status
POST {{edgeUrl}}/devicehub/v2
Register/Tag Status (subscription)
Streams real-time per-register state updates (OK, Failed, ...). This is the tag-level analogue of DeviceHub > Devices > Device Connection Status, which only reports device-wide state. Useful for dashboards that need to flag individual stale or errored tags.
This is a GraphQL subscription, not a query. A one-shot POST will return at most the first event. For continuous updates, use a WebSocket transport (subscriptions-transport-ws or graphql-ws) or Server-Sent Events.
Endpoint
POST {{edgeUrl}}/devicehub/v2
Content-Type: application/json
WebSocket transport: wss://{{edgeHost}}/devicehub/v2.
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 RegisterStatusEvent($input: RegistersStatesRequest) {
RegisterStatusEvent(input: $input) {
ID
State
}
}
Variables (input: RegistersStatesRequest)
| Field | Type | Required | Description |
|---|---|---|---|
DeviceID |
ID |
Yes | UUID of the device whose registers you want updates for. |
IDs |
[ID!] |
No | Optional filter -- restrict events to these register UUIDs. Omit (or empty) to receive every register on the device. |
{
"input": {
"DeviceID": "{{deviceID}}",
"IDs": ["{{register_id}}"]
}
}
Event shape
Each event has the same data-wrapped shape as a query response:
{
"data": {
"RegisterStatusEvent": [
{
"ID": "2C546FA7-C1CC-4AF5-B344-3877970A6A45",
"State": "OK"
}
]
}
}
| Field | Type | Description |
|---|---|---|
RegisterStatusEvent[].ID |
ID |
UUID of the register whose status changed. |
RegisterStatusEvent[].State |
String |
New state. Common values: OK, Failed, Stale, Disabled, Unknown. Driver-defined. |
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.
Subscription notes
- Reconnect with backoff on transport close. There is no replay buffer.
- On reconnect, also issue
List Registers from Single Deviceto reconcile state. - Filter aggressively with
IDs-- a device with thousands of tags can produce a high event rate.
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 RegisterStatusEvent($input: RegistersStatesRequest) {
RegisterStatusEvent(input: $input) {
ID
State
}
}
Variables
{
"input": {
"DeviceID": "{{deviceID}}",
"IDs": [
"{{register_id}}"
]
}
}
Response
Status: 200 OK
{
"data": {
"RegisterStatusEvent": [
{
"ID": "2C546FA7-C1CC-4AF5-B344-3877970A6A45",
"State": "OK"
}
]
}
}
Server Search
POST {{edgeUrl}}/devicehub/v2
Server Search
Searches the downloaded tag index of a device for tags matching a name pattern. This is useful for protocols where the device exposes a very large native namespace (e.g. an OPC UA server with thousands of nodes) and you want fuzzy lookup before importing.
The search is server-side, so a slow or wide pattern does not pull the full index over the wire. Not every driver maintains a downloaded index; those that don't return an empty result.
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 SearchDownloadedTags($input: SearchTagsRequest) {
SearchDownloadedTags(input: $input) {
Items {
Path
TagName
ID
}
Last
}
}
Variables (input: SearchTagsRequest)
| Field | Type | Required | Description |
|---|---|---|---|
DevID |
ID |
Yes | UUID of the device to search within. Note the field name is DevID, not DeviceID. |
Pattern |
String |
Yes | Tag-name pattern to match. |
Similarity |
Float |
No | Threshold for fuzzy matching, 0.0..1.0. Higher = stricter. Typical value: 0.7. |
Limit |
Int |
No | Page size. Combine with Offset for paging. |
Offset |
Int |
No | Number of results to skip. 0 is the first page. |
{
"input": {
"DevID": "4C4B9CCC-F5E4-4C2E-A4C0-EAF5C32B0D1A",
"Pattern": "cAM_BadVoltageAllPot",
"Similarity": 0.7,
"Limit": 5,
"Offset": 0
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.SearchDownloadedTags.Items |
[Item!]! |
Matching index entries. |
data.SearchDownloadedTags.Items[].Path |
String |
Native namespace path of the tag (e.g. OPC UA node path). |
data.SearchDownloadedTags.Items[].TagName |
String |
Suggested tag alias derived from the source name. |
data.SearchDownloadedTags.Items[].ID |
ID |
Index entry ID. Pass through to Create Tag to materialize it as a tag. |
data.SearchDownloadedTags.Last |
Boolean |
true if this is the final page. |
{
"data": {
"SearchDownloadedTags": {
"Items": [],
"Last": true
}
}
}
An empty Items array with Last: true is also returned when the driver does not maintain a downloaded index or when no rows match.
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 SearchDownloadedTags($input: SearchTagsRequest) {
SearchDownloadedTags(input: $input) {
Items {
Path
TagName
ID
}
Last
}
}
Variables
{
"input":
{
"DevID": "4C4B9CCC-F5E4-4C2E-A4C0-EAF5C32B0D1A",
"Limit": 5,
"Offset": 0,
"Pattern": "cAM_BadVoltageAllPot",
"Similarity": 0.7
}
}
Response
Status: 200 OK
{
"data": {
"SearchDownloadedTags": {
"Items": [],
"Last": true
}
}
}
Validate Update Registers
POST {{edgeUrl}}/devicehub/v2
Validate Update Registers
Performs a dry-run validation of an UpdateRegisters (or CreateRegisters) payload without applying it. Use this for live form validation in custom UIs, or as a pre-flight check in automation pipelines that build register inputs programmatically.
The endpoint reuses the UpdateRegistersRequest input shape, so you can pass either a brand-new register (omit ID) or an existing one (include ID) and get the same per-field validation feedback.
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 ValidateUpdateRegisters($input: UpdateRegistersRequest!) {
ValidateUpdateRegisters(input: $input) {
ObjectID
Errors { FullName TextToDisplay }
Warnings { FullName TextToDisplay }
}
}
Variables
Same shape as Update a Tag -- a Registers array of register inputs. Each entry may include or omit ID depending on whether you are validating a create or an update.
{
"input": {
"Registers": [
{
"ID": "{{register_id}}",
"DeviceID": "{{deviceID}}",
"Name": "DB",
"TagName": "FaultCode_Min_Value",
"ValueType": "int",
"Description": "",
"PublishCoV": false,
"TagFormula": null,
"MetaData": [],
"Properties": [
{ "Key": "valueType", "Value": "int" },
{ "Key": "pollingInterval", "Value": "1000" },
{ "Key": "address", "Value": "36" },
{ "Key": "count", "Value": "1" },
{ "Key": "DB", "Value": "11" }
]
}
]
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.ValidateUpdateRegisters |
[Result!] or null |
Array of validation results, one per register input. null if every register passed without errors or warnings. |
data.ValidateUpdateRegisters[].ObjectID |
ID |
UUID of the register the result applies to (matches the input's ID). |
data.ValidateUpdateRegisters[].Errors |
[Issue!]! |
Hard failures -- the actual UpdateRegisters mutation would reject these. |
data.ValidateUpdateRegisters[].Errors[].FullName |
String |
Dotted path to the offending input field (e.g. Registers[0].Properties.address). |
data.ValidateUpdateRegisters[].Errors[].TextToDisplay |
String |
Human-readable explanation suitable for inline form feedback. |
data.ValidateUpdateRegisters[].Warnings |
[Issue!]! |
Soft warnings -- the mutation would succeed but the operator may want to review. |
Example response (no issues)
{
"data": {
"ValidateUpdateRegisters": null
}
}
A null payload means every register input would be accepted as-is. Use this endpoint after every form change to keep the operator's feedback in sync without round-tripping the create/update mutation.
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 ValidateUpdateRegisters($input: UpdateRegistersRequest!) {
ValidateUpdateRegisters(input: $input) {
ObjectID
Errors {
FullName
TextToDisplay
}
Warnings {
FullName
TextToDisplay
}
}
}
Variables
{
"input": {
"Registers": [
{
"PublishCoV": false,
"TagFormula": null,
"MetaData": [],
"Name": "DB",
"Description": "",
"DeviceID": "{{deviceID}}",
"Properties": [
{
"Key": "valueType",
"Value": "int"
},
{
"Key": "pollingInterval",
"Value": "1000"
},
{
"Key": "address",
"Value": "36"
},
{
"Key": "count",
"Value": "1"
},
{
"Key": "DB",
"Value": "11"
}
],
"TagName": "FaultCode_Min_Value",
"ValueType": "int",
"ID": "{{register_id}}"
}
]
}
}
Response
Status: 200 OK
{
"data": {
"ValidateUpdateRegisters": null
}
}