LitmusEdge 4.0.x API Documentation/Digital Twins - LE, LEM, LUNS API Docs
Dynamic attributes and transformations bind to live tag data, which arrives as a flat DeviceHub/DataHub message (fields
value,tagName,deviceID,datatype,timestamp, ... nopayloadwrapper). Full shape and field types: /reference/devicehub-message-format.md.
List Static Attributes
POST {{edgeUrl}}/digital-twins
List Static Attributes
Lists the static (constant) attributes attached to a model, or to a specific instance via InstanceID. Static attributes are typed key/value pairs that do not carry live data -- use them for things like Manufacturer, Serial, InstallDate.
When InstanceID is null, the result is the model-level definitions (the schema). When InstanceID is set, the result includes per-instance overrides on top.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query ListStaticAttributes($input: ListStaticAttributeRequest!) {
ListStaticAttributes(input: $input) {
ID
ModelID
InstanceID
Key
Value
CreatedAt
UpdatedAt
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the model. |
InstanceID |
ID |
No | UUID of an instance to scope to. Pass null for the model-level definitions. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"InstanceID": null
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.ListStaticAttributes |
[StaticAttr!]! |
Static attributes for the scope. |
data.ListStaticAttributes[].ID |
ID |
Attribute UUID. Used by Update Static Attribute and Delete Static Attribute. |
data.ListStaticAttributes[].ModelID |
ID |
Parent model. |
data.ListStaticAttributes[].InstanceID |
ID |
Parent instance (00000000-... for model-level definitions). |
data.ListStaticAttributes[].Key |
String |
Attribute name (e.g. Manufacturer). |
data.ListStaticAttributes[].Value |
String |
Attribute value. |
data.ListStaticAttributes[].CreatedAt/.UpdatedAt |
Time |
ISO 8601 timestamps. |
{
"data": {
"ListStaticAttributes": [
{
"ID": "189EDB70-1029-4EBF-AB40-27E5423C12CE",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Key": "Manufacturer",
"Value": "API Manufacturer",
"CreatedAt": "2023-08-16T00:03:50.174589529Z",
"UpdatedAt": "2023-08-16T00:03:55.264377178Z"
}
]
}
}
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 ListStaticAttributes($input:ListStaticAttributeRequest!) {
ListStaticAttributes(input: $input) {
ID
ModelID
InstanceID
Key
Value
CreatedAt
UpdatedAt
}
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"InstanceID": null
}
}
Response
Status: 200 OK
{
"data": {
"ListStaticAttributes": [
{
"ID": "189EDB70-1029-4EBF-AB40-27E5423C12CE",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Key": "Manufacturer",
"Value": "API Manufacturer",
"CreatedAt": "2023-08-16T00:03:50.174589529Z",
"UpdatedAt": "2023-08-16T00:03:55.264377178Z"
}
]
}
}
Create Static Attribute
POST {{edgeUrl}}/digital-twins
Create Static Attribute
Creates a new static attribute on a model. The attribute is part of the model's schema and is inherited by every instance unless overridden.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation CreateStaticAttribute($input: CreateStaticAttributeRequest!) {
CreateStaticAttribute(input: $input) {
ID
ModelID
InstanceID
Key
Value
CreatedAt
UpdatedAt
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the model to attach the attribute to. |
Key |
String |
Yes | Attribute name. Must be unique within the model. |
Value |
String |
Yes | Attribute value. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"Key": "Model",
"Value": "New API Model"
}
}
Response
200 OK -- application/json. Same shape as one element of List Static Attributes.
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 CreateStaticAttribute ($input: CreateStaticAttributeRequest!) {
CreateStaticAttribute(input: $input) {
ID
ModelID
InstanceID
Key
Value
CreatedAt
UpdatedAt
}
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"Key": "Model",
"Value": "New API Model"
}
}
Response
Status: 200 OK
{
"data": {
"CreateStaticAttribute": {
"ID": "63E4BD05-CE85-41CD-99A6-F69CCD171240",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Key": "Model",
"Value": "New API Model",
"CreatedAt": "2023-08-16T00:13:38.224123983Z",
"UpdatedAt": "2023-08-16T00:13:38.224126007Z"
}
}
}
Update Static Attribute
POST {{edgeUrl}}/digital-twins
Update Static Attribute
Updates the Key or Value of an existing static attribute. Pass the attribute's ID plus the new values. Identical schema is used to update both model-level definitions and instance-level overrides -- the endpoint behaves the same in either case.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation UpdateStaticAttribute($input: UpdateStaticAttributeRequest!) {
UpdateStaticAttribute(input: $input) {
ID
ModelID
InstanceID
Key
Value
CreatedAt
UpdatedAt
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the static attribute. |
ModelID |
ID |
Yes | UUID of the parent model. |
Key |
String |
Yes | New attribute name. Must be unique within the model. |
Value |
String |
Yes | New attribute value. |
{
"input": {
"ID": "{{digital_twins_static_attribute_id}}",
"ModelID": "{{digital_twins_model_id}}",
"Key": "Model",
"Value": "Updated Value API Model"
}
}
Response
200 OK -- application/json. Same shape as List Static Attributes, reflecting the post-update values and a refreshed UpdatedAt.
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 UpdateStaticAttribute($input:UpdateStaticAttributeRequest!) {
UpdateStaticAttribute(input: $input) {
ID
ModelID
InstanceID
Key
Value
CreatedAt
UpdatedAt
}
}
Variables
{
"input": {
"ID": "{{digital_twins_static_attribute_id}}",
"ModelID": "{{digital_twins_model_id}}",
"Key": "Model",
"Value": "Updated Value API Model"
}
}
Response
Status: 200 OK
{
"data": {
"UpdateStaticAttribute": {
"ID": "63E4BD05-CE85-41CD-99A6-F69CCD171240",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Key": "Model",
"Value": "Updated Value API Model",
"CreatedAt": "2023-08-16T00:13:38.224123983Z",
"UpdatedAt": "2023-08-16T00:23:12.872714078Z"
}
}
}
Delete Static Attribute
POST {{edgeUrl}}/digital-twins
Delete Static Attribute
Deletes one or more static attributes by ID. Despite the singular name, the mutation accepts a list -- pass any number of items in the Items array.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation DeleteStaticAttributes($input: DeleteStaticAttributesRequest!) {
DeleteStaticAttributes(input: $input)
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
Items |
[Item!]! |
Yes | List of {ID} objects -- one per attribute to delete. |
Items[].ID |
ID |
Yes | UUID of the static attribute. |
{
"input": {
"Items": [
{ "ID": "{{digital_twins_static_attribute_id}}" }
]
}
}
Response
200 OK -- application/json. The mutation returns no data on success.
{ "data": { "DeleteStaticAttributes": 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
mutation DeleteStaticAttributes($input: DeleteStaticAttributesRequest!) {
DeleteStaticAttributes(input: $input)
}
Variables
{
"input": {
"Items": [
{
"ID": "{{digital_twins_static_attribute_id}}"
}
]
}
}
Response
Status: 200 OK
{
"data": {
"DeleteStaticAttributes": null
}
}
Upload an Image
POST {{edgeUrl}}/digital-twins
Upload an Image
Uploads an image to associate with a digital twin model (e.g. a photo or diagram of the asset). Multipart form-data request following the GraphQL multipart request spec.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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 |
GraphQL envelope describing the mutation, with null placeholder for the file. |
map |
text |
JSON mapping form file keys to placeholder locations within operations. |
1 |
file |
The image file (binary). The form key (1) must match what appears in map. |
operations value
{
"operationName": "UploadImage",
"variables": { "input": { "ObjectID": "{{digital_twins_model_id}}", "File": null } },
"query": "mutation UploadImage($input: ImageRequest!) { UploadImage(input: $input) }"
}
map value
{ "1": ["variables.input.File"] }
The ObjectID is the model UUID; the same endpoint is reused on instances by passing an instance UUID.
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.UploadImage |
Boolean |
true on success. |
{ "data": { "UploadImage": 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
Response
Status: 200 OK
{
"data": {
"UploadImage": true
}
}
Delete an Image
POST {{edgeUrl}}/digital-twins
Delete an Image
Removes the image previously uploaded by Upload an Image from a model (or instance). Idempotent -- deleting when there is no image is a no-op.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation DeleteImage($input: DeleteImageRequest!) {
DeleteImage(input: $input)
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ObjectID |
ID |
Yes | UUID of the model (or instance) whose image to delete. |
{
"input": {
"ObjectID": "{{digital_twins_model_id}}"
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.DeleteImage |
Boolean |
true on success. |
{ "data": { "DeleteImage": 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
mutation DeleteImage($input: DeleteImageRequest!) {
DeleteImage(input: $input)
}
Variables
{
"input": {
"ObjectID": "{{digital_twins_model_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"DeleteImage": true
}
}
Get Transformations
POST {{edgeUrl}}/digital-twins
Get Transformations
Lists every transformation defined on a model. A transformation is a named JSON Schema that dynamic attributes can reference to validate or shape their payload before it is published.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query ListTransformations($input: ListTransformationRequest!) {
ListTransformations(input: $input) {
ID
Name
Schema
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the model. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.ListTransformations |
[Transformation!]! |
All transformations on the model. |
data.ListTransformations[].ID |
ID |
Transformation UUID. |
data.ListTransformations[].Name |
String |
Display name. |
data.ListTransformations[].Schema |
String |
JSON Schema as a string. Parse client-side. |
{
"data": {
"ListTransformations": [
{
"ID": "ABF0E58E-2D3C-4E85-A42F-18CFE9D94C91",
"Name": "apiTransformation",
"Schema": "{\"key\": \"value\"}"
}
]
}
}
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 ListTransformations ($input:ListTransformationRequest!){
ListTransformations(input: $input) {
ID
Name
Schema
}
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"ListTransformations": [
{
"ID": "ABF0E58E-2D3C-4E85-A42F-18CFE9D94C91",
"Name": "apiTransformation",
"Schema": "{\"key\": \"value\"}"
},
{
"ID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"Name": "Transformation",
"Schema": "{\n \"key\": \"value\"\n}"
}
]
}
}
Create Transformation
POST {{edgeUrl}}/digital-twins
Create Transformation
Creates a new transformation on a model. The Schema is a JSON Schema document represented as a string.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation CreateTransformation($input: CreateTransformationRequest!) {
CreateTransformation(input: $input) {
ID
Name
Schema
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the parent model. |
Name |
String |
Yes | Transformation name. Must be unique in the model. |
Schema |
String |
Yes | JSON Schema as a string. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"Name": "apiTransformation",
"Schema": "{\"key\": \"value\"}"
}
}
Response
200 OK -- application/json. Returns the new transformation.
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 CreateTransformation($input: CreateTransformationRequest!) {
CreateTransformation(input: $input) {
ID
Name
Schema
}
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"Name": "apiTransformation",
"Schema": "{\"key\": \"value\"}"
}
}
Response
Status: 200 OK
{
"data": {
"CreateTransformation": {
"ID": "ABF0E58E-2D3C-4E85-A42F-18CFE9D94C91",
"Name": "apiTransformation",
"Schema": "{\"key\": \"value\"}"
}
}
}
Update Transformation
POST {{edgeUrl}}/digital-twins
Update Transformation
Updates the Name and/or Schema of an existing transformation.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation UpdateTransformation($input: UpdateTransformationRequest!) {
UpdateTransformation(input: $input) {
ID
Name
Schema
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the transformation. |
Name |
String |
Yes | New transformation name. |
Schema |
String |
Yes | New JSON Schema (as a string). |
{
"input": {
"ID": "{{digital_twins_transformation_id}}",
"Name": "updatedTransformation",
"Schema": "{\"updatedKey\": \"updatedValue\"}"
}
}
Response
200 OK -- application/json. Returns the updated transformation.
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 UpdateTransformation ($input: UpdateTransformationRequest!) {
UpdateTransformation(input: $input) {
ID
Name
Schema
}
}
Variables
{
"input": {
"ID": "{{digital_twins_transformation_id}}",
"Name": "updatedTransformation",
"Schema": "{\"updatedKey\": \"updatedValue\"}"
}
}
Response
Status: 200 OK
{
"data": {
"UpdateTransformation": {
"ID": "ABF0E58E-2D3C-4E85-A42F-18CFE9D94C91",
"Name": "updatedTransformation",
"Schema": "{\"updatedKey\": \"updatedValue\"}"
}
}
}
Delete Transformation
POST {{edgeUrl}}/digital-twins
Delete Transformation
Deletes a single transformation by ID. Dynamic attributes that referenced the deleted transformation will fall back to no validation.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation DeleteTransformation($input: DeleteTransformationRequest!) {
DeleteTransformation(input: $input)
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the transformation. |
{
"input": {
"ID": "{{digital_twins_transformation_id}}"
}
}
Response
200 OK -- application/json. No data returned on success.
{ "data": { "DeleteTransformation": 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
mutation DeleteTransformation ($input: DeleteTransformationRequest!){
DeleteTransformation(input: $input)
}
Variables
{
"input": {
"ID": "{{digital_twins_transformation_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"DeleteTransformation": null
}
}
List Parameters
POST {{edgeUrl}}/digital-twins
List Parameters
Returns the parameters defined on the given owner. OwnerID is the UUID of either a model or an instance. Parameters are free-form Name/Value strings used by integrations and the LE UI for ad-hoc configuration that isn't surfaced as static/dynamic attributes.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query ListParameters($input: ListParametersRequest) {
ListParameters(input: $input) {
ID
Name
Value
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
OwnerID |
ID |
Yes | UUID of the model or instance that owns the parameters. |
{
"input": {
"OwnerID": "{{digital_twins_model_id}}"
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.ListParameters |
[Parameter!]! |
All parameters on the owner. |
data.ListParameters[].ID |
ID |
Parameter UUID. |
data.ListParameters[].Name |
String |
Parameter name. |
data.ListParameters[].Value |
String |
Parameter value. |
{
"data": {
"ListParameters": [
{ "ID": "51D2E713-6150-4800-8779-9A1825BE19D7", "Name": "Updated key", "Value": "Updated value" },
{ "ID": "8FA45411-ECA0-44C0-BD2F-60341D55C581", "Name": "key1", "Value": "value1" }
]
}
}
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 ListParameters($input: ListParametersRequest) {
ListParameters(input: $input) {
ID
Name
Value
}
}
Variables
{
"input": {
"OwnerID": "{{digital_twins_model_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"ListParameters": [
{
"ID": "51D2E713-6150-4800-8779-9A1825BE19D7",
"Name": "Updated key",
"Value": "Updated value"
},
{
"ID": "8FA45411-ECA0-44C0-BD2F-60341D55C581",
"Name": "key1",
"Value": "value1"
}
]
}
}
Set Parameters
POST {{edgeUrl}}/digital-twins
Set Parameters (transactional)
Applies a set of parameter changes to a model atomically using the transactional model update mutation. The same mutation is used to create, update, and delete parameters in one call; Delete Parameters uses a payload that includes only the delete portion.
This is the same endpoint used by the LE UI to commit edits to a model's schema in one round-trip.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation TransactionalModelUpdate($input: TransactionalModelUpdateRequest!) {
TransactionalModelUpdate(input: $input)
}
Variables
The input is an envelope of per-operation arrays. Send only the arrays you need; the others can be empty Items: [].
| Field | Type | Description |
|---|---|---|
modelID |
ID |
UUID of the target model. |
createStaticAttributes |
{ Items } |
List of CreateStaticAttribute payloads to apply. |
updateStaticAttributes |
{ Items } |
List of UpdateStaticAttribute payloads. |
delStaticAttributes |
{ Items } |
List of {ID} objects for static attributes to delete. |
createDynamicAttributes |
{ Items } |
List of CreateDynamicAttribute payloads. |
updateDynamicAttributes |
{ Items } |
List of UpdateDynamicAttribute payloads. |
delDynamicAttributes |
{ Items } |
List of {ID} objects. |
createParameters |
{ Items } |
List of {Name, Value, OwnerID} parameter payloads to create. |
updateParameters |
{ Items } |
List of {ID, Name, Value} parameter payloads to update. |
delParameters |
{ Items } |
List of {ID} objects for parameters to delete. |
For the parameter-only use case, leave every attribute-related array empty and populate just createParameters / updateParameters / delParameters.
{
"input": {
"modelID": "{{digital_twins_model_id}}",
"createStaticAttributes": { "Items": [] },
"updateStaticAttributes": { "Items": [] },
"delStaticAttributes": { "Items": [] },
"createDynamicAttributes": { "Items": [] },
"updateDynamicAttributes": { "Items": [] },
"delDynamicAttributes": { "Items": [] }
}
}
Response
200 OK -- application/json. The mutation returns no data; failures surface in the GraphQL errors array.
{ "data": { "TransactionalModelUpdate": 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
mutation TransactionalModelUpdate($input: TransactionalModelUpdateRequest!) {
TransactionalModelUpdate(input: $input)
}
Variables
{
"input": {
"modelID": "{{digital_twins_model_id}}",
"createStaticAttributes": {
"Items": []
},
"updateStaticAttributes": {
"Items": []
},
"delStaticAttributes": {
"Items": []
},
"createDynamicAttributes": {
"Items": []
},
"updateDynamicAttributes": {
"Items": []
},
"delDynamicAttributes": {
"Items": []
},
"createTransformations": [],
"updateTransformations": [],
"deleteTransformations": [],
"setParameters": {
"Items": [
{
"ID": "8fa45411-eca0-44c0-bd2f-60341d55c581",
"Name": "key1",
"Value": "value1"
},
{
"ID": "51d2e713-6150-4800-8779-9a1825be19d7",
"Name": "Updated key",
"Value": "Updated value"
}
]
},
"deleteParameters": {
"Items": []
}
}
}
Response
Status: 200 OK
{
"data": {
"TransactionalModelUpdate": null
}
}
Delete Parameters
POST {{edgeUrl}}/digital-twins
Delete Parameters (transactional)
Variant of Set Parameters for the delete-only case. The mutation is identical (TransactionalModelUpdate); only the populated arrays differ.
To delete one or more parameters, populate delParameters.Items with {ID} objects.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation TransactionalModelUpdate($input: TransactionalModelUpdateRequest!) {
TransactionalModelUpdate(input: $input)
}
Variables (delete-only example)
{
"input": {
"modelID": "{{digital_twins_model_id}}",
"createStaticAttributes": { "Items": [] },
"updateStaticAttributes": { "Items": [] },
"delStaticAttributes": { "Items": [] },
"createDynamicAttributes": { "Items": [] },
"updateDynamicAttributes": { "Items": [] }
}
}
The above example shows the envelope without any deletions populated -- in practice you would fill delParameters.Items: [{ID: "..."}] with the parameter UUIDs to remove. See Set Parameters for the full set of arrays the envelope supports.
Response
200 OK -- application/json. No data returned on success.
{ "data": { "TransactionalModelUpdate": 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
mutation TransactionalModelUpdate($input: TransactionalModelUpdateRequest!) {
TransactionalModelUpdate(input: $input)
}
Variables
{
"input": {
"modelID": "{{digital_twins_model_id}}",
"createStaticAttributes": {
"Items": []
},
"updateStaticAttributes": {
"Items": []
},
"delStaticAttributes": {
"Items": []
},
"createDynamicAttributes": {
"Items": []
},
"updateDynamicAttributes": {
"Items": []
},
"delDynamicAttributes": {
"Items": []
},
"createTransformations": [],
"updateTransformations": [],
"deleteTransformations": [],
"setParameters": {
"Items": [
{
"ID": "56daf3aa-bdec-4e7e-8d6a-a5229eaa2988",
"Name": "hi",
"Value": "hello"
}
]
},
"deleteParameters": {
"Items": [
{
"ID": "51D2E713-6150-4800-8779-9A1825BE19D7"
},
{
"ID": "56DAF3AA-BDEC-4E7E-8D6A-A5229EAA2988"
}
]
}
}
}
Response
Status: 200 OK
{
"data": {
"TransactionalModelUpdate": null
}
}
Get Hierarchy
POST {{edgeUrl}}/digital-twins
Get Hierarchy
Returns the current hierarchy of a model as a nested tree. The hierarchy defines how attributes are organized into folders inside the model -- the same structure the LE UI shows in the model editor's tree view.
Each node references either an attribute (via AttributeID) or is a folder (IsFolder: true). Nodes may have child nodes via Childs.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query GetHierarchy($input: GetHierarchyRequest!) {
GetHierarchy(input: $input)
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the model. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
200 OK -- application/json. data.GetHierarchy is a single root node:
| Field | Type | Description |
|---|---|---|
Name |
String |
Node display name. "root" for the synthetic root. |
Node |
Node? |
Backing node record (null for the synthetic root). |
Node.ID |
ID |
Node UUID. |
Node.ModelID |
ID |
Parent model. |
Node.Position |
Int |
Display order among siblings (0-indexed). |
Node.ParentID |
ID? |
UUID of the parent node, or null for top-level nodes. |
Node.IsFolder |
Boolean |
true for organizational folders; false for attribute references. |
Node.AttributeID |
ID? |
UUID of the referenced static or dynamic attribute. Empty for folders. |
Attr |
object? | Resolved attribute record (denormalized for UI convenience). |
Childs |
[Node] |
Child nodes (recursive). |
{
"data": {
"GetHierarchy": {
"Name": "root",
"Node": null,
"Attr": null,
"Childs": [
{
"Name": "Manufacturer",
"Node": {
"ID": "d476d3df-8794-4d57-a991-623e8811fb6b",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Position": 0,
"ParentID": null,
"Name": "Manufacturer",
"IsFolder": false,
"AttributeID": "189edb70-1029-4ebf-ab40-27e5423c12ce"
}
}
]
}
}
}
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 GetHierarchy ($input : GetHierarchyRequest!){
GetHierarchy(input: $input)
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"GetHierarchy": {
"Name": "root",
"Node": null,
"Attr": null,
"Childs": [
{
"Name": "Manufacturer",
"Node": {
"ID": "d476d3df-8794-4d57-a991-623e8811fb6b",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Position": 0,
"ParentID": null,
"Name": "Manufacturer",
"IsFolder": false,
"AttributeID": "189edb70-1029-4ebf-ab40-27e5423c12ce",
"AttributeType": "static",
"CreatedAt": "2023-08-17T17:31:55.670316457Z",
"IndexUniqueAttrID": "root189edb70-1029-4ebf-ab40-27e5423c12ce",
"IndexType": "hierarchy_nodes",
"IndexModelID": "hierarchy_nodes3a923971-5dfc-4633-b5af-a6bf8c0b60e9"
},
"Attr": {
"ID": "189edb70-1029-4ebf-ab40-27e5423c12ce",
"ParentID": "00000000-0000-0000-0000-000000000000",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Key": "Manufacturer",
"Value": "API Manufacturer",
"CreatedAt": "2023-08-16T00:03:50.174589529Z",
"UpdatedAt": "2023-08-16T00:23:38.740405183Z",
"IndexType": "static_attributes",
"IndexModelID": "static_attributes3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"IndexInstanceID": "static_attributes00000000-0000-0000-0000-000000000000",
"IndexUniqueModelIDName": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9Manufacturer"
},
"Childs": []
},
{
"Name": "New_Node",
"Node": {
"ID": "2562cb6d-36c1-47b2-bfac-1495377db3a5",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Position": 1,
"ParentID": null,
"Name": "New_Node",
"IsFolder": true,
"AttributeID": null,
"AttributeType": null,
"CreatedAt": "2023-08-17T17:31:55.670579242Z",
"IndexUniqueAttrID": "root2562cb6d-36c1-47b2-bfac-1495377db3a5",
"IndexType": "hierarchy_nodes",
"IndexModelID": "hierarchy_nodes3a923971-5dfc-4633-b5af-a6bf8c0b60e9"
},
"Attr": null,
"Childs": [
{
"Name": "Model",
"Node": {
"ID": "e028e1d1-9212-4e5b-8290-46104491ce93",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Position": 0,
"ParentID": "2562cb6d-36c1-47b2-bfac-1495377db3a5",
"Name": "Model",
"IsFolder": false,
"AttributeID": "3f44c811-d8cc-4735-b337-a0f30826641e",
"AttributeType": "static",
"CreatedAt": "2023-08-17T17:31:55.670918962Z",
"IndexUniqueAttrID": "2562cb6d-36c1-47b2-bfac-1495377db3a53f44c811-d8cc-4735-b337-a0f30826641e",
"IndexType": "hierarchy_nodes",
"IndexModelID": "hierarchy_nodes3a923971-5dfc-4633-b5af-a6bf8c0b60e9"
},
"Attr": {
"ID": "3f44c811-d8cc-4735-b337-a0f30826641e",
"ParentID": "00000000-0000-0000-0000-000000000000",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Key": "Model",
"Value": "New API Model",
"CreatedAt": "2023-08-16T17:29:11.461961315Z",
"UpdatedAt": "2023-08-16T17:29:11.461962629Z",
"IndexType": "static_attributes",
"IndexModelID": "static_attributes3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"IndexInstanceID": "static_attributes00000000-0000-0000-0000-000000000000",
"IndexUniqueModelIDName": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9Model"
},
"Childs": []
}
]
}
]
}
}
}
Save All Hierarchy
POST {{edgeUrl}}/digital-twins
Save All Hierarchy
Replaces the entire hierarchy of a model in a single call. The mutation accepts the same nested tree shape that Get Hierarchy returns (with arrays of {Node, Childs} entries). Existing hierarchy nodes are reconciled; missing ones are deleted; new ones are created.
Use this when programmatically building or editing a model's tree -- it is much cheaper than per-node mutations.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation SaveAllHierarchy($modelId: UUID!, $input: [SaveAllHierarchyRequest]!) {
SaveAllHierarchy(modelId: $modelId, input: $input)
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
modelId |
UUID! |
Yes | UUID of the model whose hierarchy to replace. |
input |
[SaveAllHierarchyRequest]! |
Yes | Top-level nodes. Each node has Node (a {AttributeID, AttributeType, IsFolder, Name, Position} payload) and Childs (recursive). |
{
"modelId": "{{digital_twins_model_id}}",
"input": [
{
"Node": {
"AttributeID": "189edb70-1029-4ebf-ab40-27e5423c12ce",
"AttributeType": "static",
"IsFolder": false,
"Name": "Manufacturer",
"Position": 0
},
"Childs": []
}
]
}
AttributeType is "static" or "dynamic" and must match the kind of the attribute referenced by AttributeID.
Response
200 OK -- application/json. Returns the persisted nodes with their freshly-assigned/refreshed UUIDs.
{
"data": {
"SaveAllHierarchy": [
{
"ID": "71ae472d-b2d5-43fd-8824-80aee150791b",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Position": 0,
"ParentID": "8cd29a23-816e-4f53-bd88-aed2a0564724",
"Name": "Model",
"IsFolder": false,
"AttributeID": "3f44c811-d8cc-4735-b337-a0f30826641e",
"AttributeType": "static",
"CreatedAt": "2023-08-18T21:57:49.16464345Z"
}
]
}
}
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 SaveAllHierarchy($modelId: UUID!, $input: [SaveAllHierarchyRequest]!) {
SaveAllHierarchy(modelId: $modelId, input: $input)
}
Variables
{
"modelId": "{{digital_twins_model_id}}",
"input": [
{
"Node": {
"AttributeID": "189edb70-1029-4ebf-ab40-27e5423c12ce",
"AttributeType": "static",
"IsFolder": false,
"Name": "Manufacturer",
"Position": 0
},
"Childs": []
},
{
"Node": {
"AttributeID": null,
"AttributeType": null,
"IsFolder": true,
"Name": "New_Node",
"Position": 1
},
"Childs": [
{
"Node": {
"AttributeID": "3f44c811-d8cc-4735-b337-a0f30826641e",
"AttributeType": "static",
"IsFolder": false,
"Name": "Model",
"Position": 0
},
"Childs": []
},
{
"Node": {
"AttributeID": "31A6EDDC-A455-4126-981C-0A6313915A89",
"AttributeType": "dynamic",
"IsFolder": false,
"Name": "Speed",
"Position": 1
},
"Childs": []
},
{
"Node": {
"AttributeID": null,
"AttributeType": null,
"IsFolder": true,
"Name": "New_Node",
"Position": 2
},
"Childs": [
{
"Node": {
"AttributeID": "3F44C811-D8CC-4735-B337-A0F30826641E",
"AttributeType": "static",
"IsFolder": false,
"Name": "Model",
"Position": 0
},
"Childs": []
}
]
}
]
}
]
}
Response
Status: 200 OK
{
"data": {
"SaveAllHierarchy": [
{
"ID": "71ae472d-b2d5-43fd-8824-80aee150791b",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Position": 0,
"ParentID": "8cd29a23-816e-4f53-bd88-aed2a0564724",
"Name": "Model",
"IsFolder": false,
"AttributeID": "3f44c811-d8cc-4735-b337-a0f30826641e",
"AttributeType": "static",
"CreatedAt": "2023-08-18T21:57:49.16464345Z",
"IndexUniqueAttrID": "8cd29a23-816e-4f53-bd88-aed2a05647243f44c811-d8cc-4735-b337-a0f30826641e",
"IndexType": "hierarchy_nodes",
"IndexModelID": "hierarchy_nodes3a923971-5dfc-4633-b5af-a6bf8c0b60e9"
},
{
"ID": "8424515e-a7f8-4cf4-b577-8ef999388538",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Position": 0,
"ParentID": null,
"Name": "Manufacturer",
"IsFolder": false,
"AttributeID": "189edb70-1029-4ebf-ab40-27e5423c12ce",
"AttributeType": "static",
"CreatedAt": "2023-08-18T21:57:49.163896372Z",
"IndexUniqueAttrID": "root189edb70-1029-4ebf-ab40-27e5423c12ce",
"IndexType": "hierarchy_nodes",
"IndexModelID": "hierarchy_nodes3a923971-5dfc-4633-b5af-a6bf8c0b60e9"
},
{
"ID": "d0d06af4-be65-4d2b-943c-4b2487f7e365",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Position": 0,
"ParentID": "92c483ac-5949-4a55-84c5-4e55c281ff87",
"Name": "Model",
"IsFolder": false,
"AttributeID": "3f44c811-d8cc-4735-b337-a0f30826641e",
"AttributeType": "static",
"CreatedAt": "2023-08-18T21:57:49.165856053Z",
"IndexUniqueAttrID": "92c483ac-5949-4a55-84c5-4e55c281ff873f44c811-d8cc-4735-b337-a0f30826641e",
"IndexType": "hierarchy_nodes",
"IndexModelID": "hierarchy_nodes3a923971-5dfc-4633-b5af-a6bf8c0b60e9"
},
{
"ID": "14ce6813-11b7-41d0-b785-ce1fdcdaf6b0",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Position": 1,
"ParentID": "8cd29a23-816e-4f53-bd88-aed2a0564724",
"Name": "Speed",
"IsFolder": false,
"AttributeID": "31a6eddc-a455-4126-981c-0a6313915a89",
"AttributeType": "dynamic",
"CreatedAt": "2023-08-18T21:57:49.165069353Z",
"IndexUniqueAttrID": "8cd29a23-816e-4f53-bd88-aed2a056472431a6eddc-a455-4126-981c-0a6313915a89",
"IndexType": "hierarchy_nodes",
"IndexModelID": "hierarchy_nodes3a923971-5dfc-4633-b5af-a6bf8c0b60e9"
},
{
"ID": "8cd29a23-816e-4f53-bd88-aed2a0564724",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Position": 1,
"ParentID": null,
"Name": "New_Node",
"IsFolder": true,
"AttributeID": null,
"AttributeType": null,
"CreatedAt": "2023-08-18T21:57:49.164185815Z",
"IndexUniqueAttrID": "root8cd29a23-816e-4f53-bd88-aed2a0564724",
"IndexType": "hierarchy_nodes",
"IndexModelID": "hierarchy_nodes3a923971-5dfc-4633-b5af-a6bf8c0b60e9"
},
{
"ID": "92c483ac-5949-4a55-84c5-4e55c281ff87",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Position": 2,
"ParentID": "8cd29a23-816e-4f53-bd88-aed2a0564724",
"Name": "New_Node",
"IsFolder": true,
"AttributeID": null,
"AttributeType": null,
"CreatedAt": "2023-08-18T21:57:49.165520481Z",
"IndexUniqueAttrID": "8cd29a23-816e-4f53-bd88-aed2a056472492c483ac-5949-4a55-84c5-4e55c281ff87",
"IndexType": "hierarchy_nodes",
"IndexModelID": "hierarchy_nodes3a923971-5dfc-4633-b5af-a6bf8c0b60e9"
}
]
}
}
List all Dynamic Attributes
POST {{edgeUrl}}/digital-twins
List all Dynamic Attributes
Lists every dynamic attribute defined on a model. A dynamic attribute is a live signal -- it carries a real-time value and is bound to a tag topic from DeviceHub (or another publisher).
For instance-level overrides, see Instances > Dynamic Attribute > List all Dynamic Attributes.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query ListDynamicAttributes($input: ListDynamicAttributeRequest!) {
ListDynamicAttributes(input: $input) {
ID
ModelID
InstanceID
Topic
Name
Unit
DataType
SchemaID
CreatedAt
UpdatedAt
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the model. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.ListDynamicAttributes |
[DynamicAttr!]! |
All dynamic attributes for the scope. |
data.ListDynamicAttributes[].ID |
ID |
Attribute UUID. |
data.ListDynamicAttributes[].ModelID |
ID |
Parent model. |
data.ListDynamicAttributes[].InstanceID |
ID |
Parent instance (00000000-... for model-level definitions). |
data.ListDynamicAttributes[].Topic |
String |
Source topic for the live value. Empty for model-level definitions; set per-instance to bind to a DeviceHub tag topic. |
data.ListDynamicAttributes[].Name |
String |
Attribute name. |
data.ListDynamicAttributes[].Unit |
String |
Engineering unit string (kmph, degC, ...). |
data.ListDynamicAttributes[].DataType |
String |
Data type (string, int, float, bool, Dictionary, ...). |
data.ListDynamicAttributes[].SchemaID |
ID |
UUID of the transformation/JSON schema applied to payloads, or empty. |
data.ListDynamicAttributes[].CreatedAt/.UpdatedAt |
Time |
ISO 8601 timestamps. |
{
"data": {
"ListDynamicAttributes": [
{
"ID": "77990102-3613-4D2B-ABFC-EE761383E631",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Topic": "",
"Name": "Dynamic attribute 1",
"Unit": "test1",
"DataType": "Dictionary",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE"
}
]
}
}
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 ListDynamicAttributes ($input: ListDynamicAttributeRequest!) {
ListDynamicAttributes(input:$input) {
ID
ModelID
InstanceID
Topic
Name
Unit
DataType
SchemaID
CreatedAt
UpdatedAt
}
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"ListDynamicAttributes": [
{
"ID": "77990102-3613-4D2B-ABFC-EE761383E631",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Topic": "",
"Name": "Dynamic attribute 1",
"Unit": "test1",
"DataType": "Dictionary",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"CreatedAt": "2023-08-16T19:13:13.808757635Z",
"UpdatedAt": "2023-08-16T20:17:31.074886398Z"
}
]
}
}
Create Dynamic Attribute
POST {{edgeUrl}}/digital-twins
Create Dynamic Attribute
Adds a new dynamic attribute to a model. The new attribute is part of the model schema and will appear on every instance after creation (with empty Topic until each instance is bound).
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation CreateDynamicAttribute($input: CreateDynamicAttributeRequest!) {
CreateDynamicAttribute(input: $input) {
ID
ModelID
InstanceID
Topic
Name
Unit
DataType
SchemaID
CreatedAt
UpdatedAt
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the parent model. |
Name |
String |
Yes | Attribute name. Must be unique within the model. |
Unit |
String |
No | Engineering unit string. |
DataType |
String |
Yes | Data type of the live value (string, int, float, bool, Dictionary, ...). |
SchemaID |
ID |
No | Transformation (JSON Schema) to apply to the payload. Use 00000000-... for none. |
Topic |
String |
No | Source topic. Usually left empty at model scope; set per-instance via Save Instance/Add Topic to Dynamic Attribute. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"Name": "Speed",
"Unit": "kmph",
"DataType": "string",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"Topic": ""
}
}
Response
200 OK -- application/json. Returns the new attribute with the same shape as List all Dynamic Attributes.
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 CreateDynamicAttribute ($input: CreateDynamicAttributeRequest!) {
CreateDynamicAttribute(input: $input) {
ID
ModelID
InstanceID
Topic
Name
Unit
DataType
SchemaID
CreatedAt
UpdatedAt
}
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"Name": "Speed",
"Unit": "kmph",
"DataType": "string",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"Topic": ""
}
}
Response
Status: 200 OK
{
"data": {
"CreateDynamicAttribute": {
"ID": "5B825E58-D3F6-4E0D-B1B2-C172F893D0DF",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Topic": "",
"Name": "Speed",
"Unit": "kmph",
"DataType": "string",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"CreatedAt": "2023-08-16T20:24:54.832165611Z",
"UpdatedAt": "2023-08-16T20:24:54.832165815Z"
}
}
}
Update Dynamic Attribute
POST {{edgeUrl}}/digital-twins
Update Dynamic Attribute
Replaces the editable fields of an existing dynamic attribute. The same mutation is used for model-level and instance-level updates; pass the appropriate ModelID/InstanceID to scope.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation UpdateDynamicAttribute($input: UpdateDynamicAttributeRequest!) {
UpdateDynamicAttribute(input: $input) {
ID
ModelID
InstanceID
Topic
Name
Unit
DataType
SchemaID
CreatedAt
UpdatedAt
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the dynamic attribute to update. |
ModelID |
ID |
Yes | UUID of the parent model. |
Name |
String |
Yes | New attribute name. |
Unit |
String |
No | New engineering unit. |
DataType |
String |
Yes | New data type. |
SchemaID |
ID |
No | New transformation UUID. |
Topic |
String |
No | New source topic (empty for model scope). |
{
"input": {
"ID": "{{digital_twins_dynamic_attribute_id}}",
"ModelID": "{{digital_twins_model_id}}",
"Name": "changedName",
"Unit": "changedUnit",
"DataType": "string",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"Topic": ""
}
}
Response
200 OK -- application/json. Returns the updated attribute.
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 UpdateDynamicAttribute ($input: UpdateDynamicAttributeRequest!) {
UpdateDynamicAttribute(input: $input) {
ID
ModelID
InstanceID
Topic
Name
Unit
DataType
SchemaID
CreatedAt
UpdatedAt
}
}
Variables
{
"input": {
"ID": "{{digital_twins_dynamic_attribute_id}}",
"ModelID": "{{digital_twins_model_id}}",
"Name": "changedName",
"Unit": "changedUnit",
"DataType": "string",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"Topic": ""
}
}
Response
Status: 200 OK
{
"data": {
"UpdateDynamicAttribute": {
"ID": "77990102-3613-4D2B-ABFC-EE761383E631",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Topic": "",
"Name": "changedName",
"Unit": "changedUnit",
"DataType": "string",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"CreatedAt": "2023-08-16T19:13:13.808757635Z",
"UpdatedAt": "2023-08-16T20:27:34.892193102Z"
}
}
}
Download Dynamic Attributes
POST {{edgeUrl}}/digital-twins
Download Dynamic Attributes
Exports the dynamic attributes of a model as a CSV string. The CSV is compatible with Upload Dynamic Attribute CSV for round-trip workflows: download, edit in a spreadsheet, re-upload.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query DownloadDynamicAttributesCSV($input: DownloadCSVRequest!) {
DownloadDynamicAttributesCSV(input: $input)
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the model to export. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
200 OK -- application/json. data.DownloadDynamicAttributesCSV is a CSV-formatted string with header row ID,ModelName,InstanceName,Topic,Name,Unit,DataType,SchemaID.
{
"data": {
"DownloadDynamicAttributesCSV": "ID,ModelName,InstanceName,Topic,Name,Unit,DataType,SchemaID\n68280ec1-1c12-4b0d-a7ea-5a9d5ac32092,apiImportModel,,,Speed,kmph,string,4c67a3e1-d442-4b39-b0f6-eb07cc200066\n"
}
}
Parse the string client-side (it is not a separate file download). To get a true file download, take the string and write it to disk yourself.
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 DownloadDynamicAttributesCSV($input: DownloadCSVRequest!) {
DownloadDynamicAttributesCSV(input: $input)
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"DownloadDynamicAttributesCSV": "ID,ModelName,InstanceName,Topic,Name,Unit,DataType,SchemaID\n68280ec1-1c12-4b0d-a7ea-5a9d5ac32092,apiImportModel,,,Speed,kmph,string,4c67a3e1-d442-4b39-b0f6-eb07cc200066\n"
}
}
Upload Dynamic Attribute CSV
POST {{edgeUrl}}/digital-twins
Upload Dynamic Attribute CSV
Imports dynamic attributes from a CSV file. Uses the GraphQL multipart spec, identical in shape to Models > Static Attributes > Upload an Image.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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 |
GraphQL envelope describing the mutation, with null placeholder for the file. |
map |
text |
JSON mapping form file keys to placeholder locations within operations. |
1 |
file |
The CSV file. The form key (1) must match the key referenced in map. |
operations value
{
"operationName": "UploadDynamicAttributesCSV",
"variables": { "input": { "ModelID": "{{digital_twins_model_id}}", "File": null } },
"query": "mutation UploadDynamicAttributesCSV($input: UploadCSVRequest!) { UploadDynamicAttributesCSV(input: $input) { Errors { Line Column Error } } }"
}
map value
{ "1": ["variables.input.File"] }
The CSV format must match what Download Dynamic Attributes produces (see that endpoint for the header row).
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.UploadDynamicAttributesCSV.Errors |
[CSVError!]! |
One entry per error row, plus a summary row. |
data.UploadDynamicAttributesCSV.Errors[].Line |
Int? |
1-indexed CSV line number with the error. null for the summary. |
data.UploadDynamicAttributesCSV.Errors[].Column |
Int? |
1-indexed column number with the error. null for the summary. |
data.UploadDynamicAttributesCSV.Errors[].Error |
String |
Error text (or created: N updated: N skipped: N summary). |
{
"data": {
"UploadDynamicAttributesCSV": {
"Errors": [
{
"Line": null,
"Column": null,
"Error": "created: 0 updated: 1 skipped: 0"
}
]
}
}
}
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
Response
Status: 200 OK
{
"data": {
"UploadDynamicAttributesCSV": {
"Errors": [
{
"Line": null,
"Column": null,
"Error": "created: 0 updated: 1 skipped: 0",
"__typename": "CSVError"
}
],
"__typename": "UploadCSVResponse"
}
}
}
Remove Dynamic Attribute
POST {{edgeUrl}}/digital-twins
Remove Dynamic Attribute
Deletes one or more dynamic attributes by ID. Despite the singular name, the underlying mutation accepts a list -- but the example below shows the single-ID form taken by the Postman item.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation DeleteDynamicAttribute($input: DeleteDynamicAttributeRequest!) {
DeleteDynamicAttribute(input: $input)
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the dynamic attribute to delete. |
{
"input": {
"ID": "{{digital_twins_dynamic_attribute_id}}"
}
}
Response
200 OK -- application/json. No data returned on success.
{ "data": { "DeleteDynamicAttribute": 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
mutation DeleteDynamicAttribute ($input: DeleteDynamicAttributeRequest!) {
DeleteDynamicAttribute(input: $input)
}
Variables
{
"input": {
"ID": "{{digital_twins_dynamic_attribute_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"DeleteDynamicAttribute": null
}
}
Digital Twins Version
POST {{edgeUrl}}/digital-twins
Digital Twins Version
Returns the running version and git revision of the Digital Twins service. Use as a fast liveness probe or to record the build version for support tickets.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query Version {
Version {
Git
Version
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.Version.Git |
String |
Short git commit hash of the deployed build. |
data.Version.Version |
String |
Semantic version of the Digital Twins service. |
{
"data": {
"Version": {
"Git": "20e4e53e40",
"Version": "1.2.4"
}
}
}
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 ListModels {
Version {
Git
Version
}
}
Response
Status: 200 OK
{
"data": {
"Version": {
"Git": "20e4e53e40",
"Version": "1.2.4"
}
}
}
List Models
POST {{edgeUrl}}/digital-twins
List Models
Returns every model defined on the device, projected to a minimal {ID, Name} shape. Use as the source for a model picker, or to enumerate models when iterating over instances. For full schema, extend the GraphQL selection (e.g. add Description, Assets, IsUNS, ConnectorName).
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query ListModels {
ListModels {
ID
Name
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.ListModels |
[Model!]! |
All models on the device. |
data.ListModels[].ID |
ID |
Model UUID. |
data.ListModels[].Name |
String |
Display name. Unique across models. |
{
"data": {
"ListModels": [
{ "ID": "D9117AE5-3F3E-4436-9A2A-6DD725FBD8FB", "Name": "Digital-Twin-1" }
]
}
}
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 ListModels {
ListModels {
ID
Name
}
}
Response
Status: 200 OK
{
"data": {
"ListModels": [
{
"ID": "D9117AE5-3F3E-4436-9A2A-6DD725FBD8FB",
"Name": "Digital-Twin-1"
}
]
}
}
Create Model
POST {{edgeUrl}}/digital-twins
Create Model
Creates a new digital twin model with the minimum properties needed for the LE UI to show it on the Models page. After creation, populate the schema via the Static Attributes, Dynamic Attribute, Transformation, and Hierarchy subfolders.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation CreateModel($input: CreateModelRequest!) {
CreateModel(input: $input) {
ID
Name
Assets
Description
IsUNS
ConnectorName
}
}
Variables (input: CreateModelRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
Name |
String |
Yes | Display name. Must be unique across all models. |
Assets |
String |
Yes | Asset category for organising models. Default ASSET. Free-form, used for grouping in the UI. |
Description |
String |
No | Free-form description. |
IsUNS |
Boolean |
No | Default false. true if this model participates in the Unified Namespace via a UNS connector. |
ConnectorName |
String |
No | UNS connector to publish under when IsUNS: true (e.g. LitmusEdge). |
{
"input": {
"Name": "{{digital_twins_model}}",
"Assets": "ASSET",
"Description": "",
"IsUNS": true,
"ConnectorName": "{{uns_connector_name}}"
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.CreateModel.ID |
ID |
UUID of the newly created model. Save as {{digital_twins_model_id}}. |
data.CreateModel.Name |
String |
Model name echoed back. |
data.CreateModel.Assets |
String |
Asset category echoed back. |
data.CreateModel.Description |
String |
Description echoed back. |
{
"data": {
"CreateModel": {
"ID": "9C01CCFC-7A94-4554-AFAD-BB14942D5190",
"Name": "apiTest",
"Assets": "ASSET",
"Description": "",
"__typename": "Model"
}
}
}
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 CreateModel($input: CreateModelRequest!) {
CreateModel(input: $input) {
ID
Name
Assets
Description
IsUNS
ConnectorName
}
}
Variables
{
"input": {
"Name": "{{digital_twins_model}}",
"Assets": "ASSET",
"Description": "",
"IsUNS": true,
"ConnectorName": "{{uns_connector_name}}"
}
}
Response
Status: 200 OK
{
"data": {
"CreateModel": {
"ID": "9C01CCFC-7A94-4554-AFAD-BB14942D5190",
"Name": "apiTest",
"Assets": "ASSET",
"Description": "",
"__typename": "Model"
}
}
}
Update Model
POST {{edgeUrl}}/digital-twins
Update Model
Updates the mutable top-level fields of a model. To edit the model's schema (attributes, hierarchy, transformations), use the sub-folder endpoints rather than this one.
UpdateModel is a full replacement of the input shape -- include every field you want to keep.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation UpdateModel($input: UpdateModelRequest!) {
UpdateModel(input: $input) {
ID
Name
Assets
Description
IsUNS
ConnectorName
__typename
}
}
Variables (input: UpdateModelRequest!)
Same fields as Create Model, plus:
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the model to update. |
{
"input": {
"ID": "{{digital_twins_model_id}}",
"Name": "{{digital_twins_model}}",
"Assets": "ASSET",
"Description": "",
"IsUNS": true,
"ConnectorName": "{{uns_connector_name}}"
}
}
Response
200 OK -- application/json. Echoes the model's new state.
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 UpdateModel($input: UpdateModelRequest!) {
UpdateModel(input: $input) {
ID
Name
Assets
Description
IsUNS
ConnectorName
__typename
}
}
Variables
{
"input": {
"Name": "{{digital_twins_model}}",
"Assets": "ASSET",
"Description": "",
"ID": "{{digital_twins_model_id}}",
"IsUNS": true,
"ConnectorName": "{{uns_connector_name}}"
}
}
Response
Status: 200 OK
{
"data": {
"UpdateModel": {
"ID": "5CF29323-A2C7-48E3-A356-6A046AF99B7F",
"Name": "apiTest",
"Assets": "ASSET",
"Description": "",
"IsUNS": true,
"ConnectorName": "LitmusEdge",
"__typename": "Model"
}
}
}
Delete Model
POST {{edgeUrl}}/digital-twins
Delete Model
Deletes a model and all of its instances, attributes, transformations, and hierarchy. Destructive and not idempotent: deleting a missing ID returns a BAD_USER_INPUT error.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation DeleteModel($input: DeleteModelRequest!) {
DeleteModel(input: $input)
}
Variables (input: DeleteModelRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the model to delete. |
{
"input": {
"ID": "{{digital_twins_model_id}}"
}
}
Response
200 OK -- application/json. No data returned on success.
{ "data": { "DeleteModel": 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
mutation DeleteModel($input: DeleteModelRequest!) {
DeleteModel(input: $input)
}
Variables
{
"input": {
"ID": "{{digital_twins_model_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"DeleteModel": null
}
}
Clone a Model
POST {{edgeUrl}}/digital-twins
Clone a Model
Creates a deep copy of an existing model: static attributes, dynamic attributes, transformations, parameters, and hierarchy are all duplicated. Instances are not cloned -- the new model starts with no instances.
Use this to template new asset types from an existing definition without re-entering the schema.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation CloneModel($input: CloneModelRequest!) {
CloneModel(input: $input) {
ID
Assets
Name
Description
}
}
Variables (input: CloneModelRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the source model to clone. |
Name |
String |
Yes | Display name for the new model. Must be unique across models. |
{
"input": {
"ID": "{{digital_twins_model_id}}",
"Name": "{{digital_twins_clone}}"
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.CloneModel.ID |
ID |
UUID of the newly created clone. |
data.CloneModel.Assets |
String |
Asset category copied from the source. |
data.CloneModel.Name |
String |
Name as supplied. |
data.CloneModel.Description |
String |
Description copied from the source. |
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 CloneModel ($input: CloneModelRequest!) {
CloneModel(input: $input) {
ID
Assets
Name
Description
}
}
Variables
{
"input": {
"ID": "{{digital_twins_model_id}}",
"Name": "{{digital_twins_clone}}"
}
}
Response
Status: 200 OK
{
"data": {
"CloneModel": {
"ID": "46946ABE-2235-4B27-833D-CC335DDFCB4C",
"Assets": "ASSET",
"Name": "apiTest2",
"Description": "Digital Twin example 1"
}
}
}
Export Model
POST {{edgeUrl}}/digital-twins
Export Model
Serializes a model and its full schema (static attributes, dynamic attributes, transformations, hierarchy, image) to a JSON document suitable for Import Model on another device. Use this to move models between devices, source-control them, or take backups.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation ExportModel($input: ExportModelRequest!) {
ExportModel(input: $input)
}
Variables (input: ExportModelRequest!)
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the model to export. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
200 OK -- application/json. data.ExportModel is an array of model documents (typically of length 1) containing every nested entity. Each document includes:
id,name,description,assets,imagedynamicAttributes[],staticAttributes[],transformations[]hierarchy[],parameters[]
Persist the response verbatim for re-import.
{
"data": {
"ExportModel": [
{
"id": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"assets": "ASSET",
"name": "apiTest",
"description": "updated model",
"image": "",
"dynamicAttributes": [
{
"id": "31a6eddc-a455-4126-981c-0a6313915a89",
"modelId": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"parentId": "00000000-0000-0000-0000-000000000000"
}
]
}
]
}
}
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 ExportModel ($input: ExportModelRequest!) {
ExportModel(input: $input)
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"ExportModel": [
{
"id": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"assets": "ASSET",
"name": "apiTest",
"description": "updated model",
"image": "",
"dynamicAttributes": [
{
"id": "31a6eddc-a455-4126-981c-0a6313915a89",
"modelId": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"parentId": "00000000-0000-0000-0000-000000000000",
"instanceId": "00000000-0000-0000-0000-000000000000",
"topic": "",
"name": "Speed",
"unit": "kmph",
"dataType": "string",
"schemaId": "30d86400-d103-4c5c-95e4-ab6f02fb00ee"
}
],
"staticAttributes": [
{
"id": "189edb70-1029-4ebf-ab40-27e5423c12ce",
"parentId": "00000000-0000-0000-0000-000000000000",
"modelId": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"instanceId": "00000000-0000-0000-0000-000000000000",
"key": "Manufacturer",
"value": "API Manufacturer"
},
{
"id": "3f44c811-d8cc-4735-b337-a0f30826641e",
"parentId": "00000000-0000-0000-0000-000000000000",
"modelId": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"instanceId": "00000000-0000-0000-0000-000000000000",
"key": "Model",
"value": "New API Model"
},
{
"id": "3af47815-bb4f-4288-84da-02b259a75edb",
"parentId": "00000000-0000-0000-0000-000000000000",
"modelId": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"instanceId": "00000000-0000-0000-0000-000000000000",
"key": "Model1",
"value": "New API Model1"
}
],
"hierarchyNodes": [
{
"id": "60c1f5d0-25ab-4bc0-93a8-52a60a7087d0",
"modelId": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"position": 0,
"parentId": "4c224618-4e24-4bf7-af8b-d87188fdc413",
"name": "Model",
"isFolder": false,
"attributeId": "3f44c811-d8cc-4735-b337-a0f30826641e",
"attributeType": "static",
"CreatedAt": "2023-11-29T00:54:35.953112543Z"
},
{
"id": "81d4226b-12f9-4d89-957d-2f01a8e5bf12",
"modelId": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"position": 0,
"parentId": "a6a8cb25-ba33-41ca-8d2c-6f657949b849",
"name": "Model",
"isFolder": false,
"attributeId": "3f44c811-d8cc-4735-b337-a0f30826641e",
"attributeType": "static",
"CreatedAt": "2023-11-29T00:54:35.954122264Z"
},
{
"id": "997ed034-52de-4ce4-9f7d-731294f70e6a",
"modelId": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"position": 0,
"parentId": null,
"name": "Manufacturer",
"isFolder": false,
"attributeId": "189edb70-1029-4ebf-ab40-27e5423c12ce",
"attributeType": "static",
"CreatedAt": "2023-11-29T00:54:35.951975424Z"
},
{
"id": "4c224618-4e24-4bf7-af8b-d87188fdc413",
"modelId": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"position": 1,
"parentId": null,
"name": "New_Node",
"isFolder": true,
"attributeId": null,
"attributeType": null,
"CreatedAt": "2023-11-29T00:54:35.952255779Z"
},
{
"id": "a6a8cb25-ba33-41ca-8d2c-6f657949b849",
"modelId": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"position": 2,
"parentId": "4c224618-4e24-4bf7-af8b-d87188fdc413",
"name": "New_Node",
"isFolder": true,
"attributeId": null,
"attributeType": null,
"CreatedAt": "2023-11-29T00:54:35.953579776Z"
}
],
"transformationBackup": [
{
"ID": "30d86400-d103-4c5c-95e4-ab6f02fb00ee",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Name": "Transformation",
"Schema": "{\n \"key\": \"value\"\n}"
}
]
}
]
}
}
Import Model
POST {{edgeUrl}}/digital-twins
Import Model
Imports one or more model documents previously produced by Export Model (or hand-authored to the same shape). The mutation accepts the document verbatim -- pass an array of model objects.
Imported models keep their original UUIDs from the source export. If a matching ID already exists on the device, the import fails -- delete or clone the existing one first.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation ImportModel($input: Any!) {
ImportModel(input: $input)
}
The Any! scalar accepts the same JSON structure that Export Model returns. The example below imports a single, minimal model:
{
"input": [
{
"id": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"assets": "ASSET",
"name": "apiImportModel",
"description": "updated model",
"image": "",
"dynamicAttributes": [],
"staticAttributes": []
}
]
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.ImportModel |
Boolean |
true on success. |
{ "data": { "ImportModel": 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
mutation ImportModel($input: Any!) {
ImportModel(input: $input)
}
Variables
{
"input": [
{
"id": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"assets": "ASSET",
"name": "apiImportModel",
"description": "updated model",
"image": "",
"dynamicAttributes": [],
"staticAttributes": [
{
"id": "189edb70-1029-4ebf-ab40-27e5423c12ce",
"parentId": "00000000-0000-0000-0000-000000000000",
"modelId": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"instanceId": "00000000-0000-0000-0000-000000000000",
"key": "Manufacturer",
"value": "API Manufacturer"
}
],
"hierarchyNodes": [],
"transformationBackup": [
{
"ID": "30d86400-d103-4c5c-95e4-ab6f02fb00ee",
"ModelID": "3a923971-5dfc-4633-b5af-a6bf8c0b60e9",
"Name": "Transformation",
"Schema": "{\n \"key\": \"value\"\n}"
}
]
}
]
}
Response
Status: 200 OK
{
"data": {
"ImportModel": true
}
}
Upgrade Instances
POST {{edgeUrl}}/digital-twins
Upgrade Instances
Reconciles one or more instances with the current state of their parent model. Use this after editing a model's schema (adding/removing attributes, changing hierarchy) so that existing instances pick up the change without being deleted and recreated.
Without Upgrade Instances, existing instances continue to operate against the model schema they were created against.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation UpgradeInstances($input: [UUID!]) {
UpgradeInstances(input: $input)
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
input |
[UUID!] |
Yes | Instance UUIDs to upgrade. Pass a single-element array for one. |
{
"input": [
"{{digital_twins_instance_id}}"
]
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.UpgradeInstances |
Boolean |
true on success. |
{ "data": { "UpgradeInstances": 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
mutation UpgradeInstances($input: [UUID!]) {
UpgradeInstances(input: $input)
}
Variables
{
"input": [
"{{digital_twins_instance_id}}"
]
}
Response
Status: 200 OK
{
"data": {
"UpgradeInstances": true
}
}
List Static Attributes
POST {{edgeUrl}}/digital-twins
List Static Attributes (instance scope)
Identical request shape to Models > Static Attributes > List Static Attributes -- the only difference is that an instance scope is expected: pass ModelID plus the InstanceID of the instance whose overrides you want to see. The response includes the model-level defaults plus any per-instance overrides.
For the model-level list (no overrides), pass InstanceID: null. See the Models-side endpoint for the full field reference.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query ListStaticAttributes($input: ListStaticAttributeRequest!) {
ListStaticAttributes(input: $input) {
ID
ModelID
InstanceID
Key
Value
CreatedAt
UpdatedAt
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the parent model. |
InstanceID |
ID |
No | UUID of the instance. Pass null for the model-level view. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"InstanceID": null
}
}
Response
Same shape as Models > Static Attributes > List Static Attributes.
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 ListStaticAttributes($input:ListStaticAttributeRequest!) {
ListStaticAttributes(input: $input) {
ID
ModelID
InstanceID
Key
Value
CreatedAt
UpdatedAt
}
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"InstanceID": null
}
}
Response
Status: 200 OK
{
"data": {
"ListStaticAttributes": [
{
"ID": "189EDB70-1029-4EBF-AB40-27E5423C12CE",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Key": "Manufacturer",
"Value": "API Manufacturer",
"CreatedAt": "2023-08-16T00:03:50.174589529Z",
"UpdatedAt": "2023-08-16T00:03:55.264377178Z"
}
]
}
}
Update Static Attribute
POST {{edgeUrl}}/digital-twins
Update Static Attribute (instance scope)
Identical to Models > Static Attributes > Update Static Attribute. The endpoint is reused for both model-level and instance-level updates -- when the static attribute UUID belongs to an instance override, the override is what's written; otherwise the model-level definition is updated.
See the Models-side endpoint for the request shape and field reference.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation UpdateStaticAttribute($input: UpdateStaticAttributeRequest!) {
UpdateStaticAttribute(input: $input) {
ID
ModelID
InstanceID
Key
Value
CreatedAt
UpdatedAt
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the static attribute (model or instance override). |
ModelID |
ID |
Yes | UUID of the parent model. |
Key |
String |
Yes | New attribute name. |
Value |
String |
Yes | New attribute value. |
{
"input": {
"ID": "{{digital_twins_static_attribute_id}}",
"ModelID": "{{digital_twins_model_id}}",
"Key": "Model",
"Value": "Updated Value API Model"
}
}
Response
Same shape as Models > Static Attributes > Update Static Attribute.
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 UpdateStaticAttribute($input:UpdateStaticAttributeRequest!) {
UpdateStaticAttribute(input: $input) {
ID
ModelID
InstanceID
Key
Value
CreatedAt
UpdatedAt
}
}
Variables
{
"input": {
"ID": "{{digital_twins_static_attribute_id}}",
"ModelID": "{{digital_twins_model_id}}",
"Key": "Model",
"Value": "Updated Value API Model"
}
}
Response
Status: 200 OK
{
"data": {
"UpdateStaticAttribute": {
"ID": "63E4BD05-CE85-41CD-99A6-F69CCD171240",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Key": "Model",
"Value": "Updated Value API Model",
"CreatedAt": "2023-08-16T00:13:38.224123983Z",
"UpdatedAt": "2023-08-16T00:23:12.872714078Z"
}
}
}
List all Dynamic Attributes
POST {{edgeUrl}}/digital-twins
List all Dynamic Attributes (instance scope)
Same shape as Models > Dynamic Attribute > List all Dynamic Attributes -- the endpoint is reused. Pass the parent ModelID to scope. The response includes per-instance overrides if InstanceID is non-zero on the returned records.
See the Models-side endpoint for the full field reference.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query ListDynamicAttributes($input: ListDynamicAttributeRequest!) {
ListDynamicAttributes(input: $input) {
ID
ModelID
InstanceID
Topic
Name
Unit
DataType
SchemaID
CreatedAt
UpdatedAt
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the parent model. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
Same shape as Models > Dynamic Attribute > List all Dynamic Attributes.
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 ListDynamicAttributes ($input: ListDynamicAttributeRequest!) {
ListDynamicAttributes(input:$input) {
ID
ModelID
InstanceID
Topic
Name
Unit
DataType
SchemaID
CreatedAt
UpdatedAt
}
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"ListDynamicAttributes": [
{
"ID": "77990102-3613-4D2B-ABFC-EE761383E631",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Topic": "",
"Name": "Dynamic attribute 1",
"Unit": "test1",
"DataType": "Dictionary",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"CreatedAt": "2023-08-16T19:13:13.808757635Z",
"UpdatedAt": "2023-08-16T20:17:31.074886398Z"
}
]
}
}
Update Dynamic Attribute
POST {{edgeUrl}}/digital-twins
Update Dynamic Attribute (instance scope)
Same mutation as Models > Dynamic Attribute > Update Dynamic Attribute. The endpoint is reused for model-level and instance-level updates; pass the override's ID together with ModelID. To bind a topic to an instance's dynamic attribute, prefer the transactional endpoint Save Instance/Add Topic to Dynamic Attribute, which can update many overrides at once.
See the Models-side endpoint for the request shape and field reference.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation UpdateDynamicAttribute($input: UpdateDynamicAttributeRequest!) {
UpdateDynamicAttribute(input: $input) {
ID
ModelID
InstanceID
Topic
Name
Unit
DataType
SchemaID
CreatedAt
UpdatedAt
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the dynamic attribute (model or instance override). |
ModelID |
ID |
Yes | UUID of the parent model. |
Name/Unit/DataType/SchemaID/Topic |
mixed | mixed | New values; see Models > Dynamic Attribute > Update Dynamic Attribute. |
{
"input": {
"ID": "{{digital_twins_dynamic_attribute_id}}",
"ModelID": "{{digital_twins_model_id}}",
"Name": "changedName",
"Unit": "changedUnit",
"DataType": "string",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"Topic": ""
}
}
Response
Same shape as Models > Dynamic Attribute > Update Dynamic Attribute.
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 UpdateDynamicAttribute ($input: UpdateDynamicAttributeRequest!) {
UpdateDynamicAttribute(input: $input) {
ID
ModelID
InstanceID
Topic
Name
Unit
DataType
SchemaID
CreatedAt
UpdatedAt
}
}
Variables
{
"input": {
"ID": "{{digital_twins_dynamic_attribute_id}}",
"ModelID": {{digital_twins_model_id}},
"Name": "changedName",
"Unit": "changedUnit",
"DataType": "string",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"Topic": ""
}
}
Response
Status: 200 OK
{
"data": {
"UpdateDynamicAttribute": {
"ID": "77990102-3613-4D2B-ABFC-EE761383E631",
"ModelID": "3A923971-5DFC-4633-B5AF-A6BF8C0B60E9",
"InstanceID": "00000000-0000-0000-0000-000000000000",
"Topic": "",
"Name": "changedName",
"Unit": "changedUnit",
"DataType": "string",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE",
"CreatedAt": "2023-08-16T19:13:13.808757635Z",
"UpdatedAt": "2023-08-16T20:27:34.892193102Z"
}
}
}
Upload Dynamic Attribute CSV
POST {{edgeUrl}}/digital-twins
Upload Dynamic Attribute CSV (instance scope)
Same multipart mutation as Models > Dynamic Attribute > Upload Dynamic Attribute CSV. The endpoint is reused; the difference is that the CSV typically contains per-instance overrides (with InstanceID set).
See the Models-side endpoint for the form-data shape, CSV format, and response field reference.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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 |
GraphQL envelope, see Models-side endpoint. |
map |
text |
{"1": ["variables.input.File"]} |
1 |
file |
The CSV file. |
The operations value uses $input.ModelID from the parent model -- the service applies overrides to the appropriate instance based on rows in the CSV.
Response
Same shape as Models > Dynamic Attribute > Upload Dynamic Attribute CSV.
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
Response
Status: 200 OK
{
"data": {
"UploadDynamicAttributesCSV": {
"Errors": [
{
"Line": null,
"Column": null,
"Error": "created: 0 updated: 1 skipped: 0",
"__typename": "CSVError"
}
],
"__typename": "UploadCSVResponse"
}
}
}
List Parameters
POST {{edgeUrl}}/digital-twins
List Parameters (instance scope)
Same query as Models > Parameters > List Parameters -- pass the instance UUID as OwnerID to scope to the instance. See the Models-side endpoint for the request shape and field reference.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query ListParameters($input: ListParametersRequest) {
ListParameters(input: $input) {
ID
Name
Value
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
OwnerID |
ID |
Yes | UUID of the instance. |
{
"input": {
"OwnerID": "{{digital_twins_instance_id}}"
}
}
Response
Same shape as Models > Parameters > List Parameters.
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 ListParameters($input: ListParametersRequest) {
ListParameters(input: $input) {
ID
Name
Value
}
}
Variables
{
"input": {
"OwnerID": "{{digital_twins_instance_id}}"
}
}
Response
Status: 200 OK
{
"data": {
"ListParameters": [
{
"ID": "51D2E713-6150-4800-8779-9A1825BE19D7",
"Name": "Updated key",
"Value": "Updated value"
},
{
"ID": "8FA45411-ECA0-44C0-BD2F-60341D55C581",
"Name": "key1",
"Value": "value1"
}
]
}
}
Get Instances
POST {{edgeUrl}}/digital-twins
Get Instances
Lists every instance across every model on the device. Pass an empty input object ({}) to return all instances; pass { ModelID: "..." } to filter to one model.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
query ListInstances($input: ListInstancesRequest) {
ListInstances(input: $input) {
ID
ModelID
Name
Topic
Interval
FlatHierarchy
__typename
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
No | UUID of a model to scope to. Omit to return every instance. |
{
"input": {}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.ListInstances |
[Instance!]! |
Matching instances. |
data.ListInstances[].ID |
ID |
Instance UUID. |
data.ListInstances[].ModelID |
ID |
UUID of the parent model. |
data.ListInstances[].Name |
String |
Instance display name. Unique across instances. |
data.ListInstances[].Topic |
String |
MQTT topic the instance publishes to (e.g. digitaltwins_<Name>). |
data.ListInstances[].Interval |
Int |
Publish interval in seconds (1 = once per second). |
data.ListInstances[].FlatHierarchy |
Boolean |
true if the instance publishes a flat key-value payload instead of the nested hierarchy. |
{
"data": {
"ListInstances": [
{
"ID": "D0C8844D-EF72-4933-BB5E-B74372B33F4B",
"ModelID": "D9117AE5-3F3E-4436-9A2A-6DD725FBD8FB",
"Name": "Instance1",
"Topic": "digitaltwins_Instance1",
"Interval": 1,
"FlatHierarchy": 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 ListInstances($input: ListInstancesRequest) {
ListInstances(input: $input) {
ID
ModelID
Name
Topic
Interval
FlatHierarchy
__typename
}
}
Variables
{
"input": {}
}
Response
Status: 200 OK
{
"data": {
"ListInstances": [
{
"ID": "D0C8844D-EF72-4933-BB5E-B74372B33F4B",
"ModelID": "D9117AE5-3F3E-4436-9A2A-6DD725FBD8FB",
"Name": "Instance1",
"Topic": "digitaltwins_Instance1",
"Interval": 1,
"FlatHierarchy": false,
"__typename": "Instance"
}
]
}
}
Create Instance
POST {{edgeUrl}}/digital-twins
Create Instance
Creates a new instance of a model. The instance is disabled by default (use Set Instance State to enable). Its dynamic attributes start with empty Topics -- use Save Instance/Add Topic to Dynamic Attribute to bind them to live data sources.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation CreateInstance($input: CreateInstanceRequest!) {
CreateInstance(input: $input) {
ID
ModelID
Name
Topic
Interval
FlatHierarchy
}
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ModelID |
ID |
Yes | UUID of the parent model. |
Name |
String |
Yes | Instance display name. Must be unique across instances. |
Interval |
Int |
Yes | Publish interval in seconds. |
Topic |
String |
Yes | MQTT topic to publish under. Conventionally digitaltwins_<Name>. |
FlatHierarchy |
Boolean |
No | Default false. true to publish a flat payload instead of the nested hierarchy. |
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"Name": "{{digital_twins_instance}}",
"Interval": 1,
"Topic": "digitaltwins_{{digital_twins_instance}}",
"FlatHierarchy": false
}
}
Response
200 OK -- application/json. Returns the new instance.
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 CreateInstance($input: CreateInstanceRequest!) {
CreateInstance(input: $input) {
ID
ModelID
Name
Topic
Interval
FlatHierarchy
}
}
Variables
{
"input": {
"ModelID": "{{digital_twins_model_id}}",
"Name": "{{digital_twins_instance}}",
"Interval": 1,
"Topic": "digitaltwins_{{digital_twins_instance}}",
"FlatHierarchy": false
}
}
Response
Status: 200 OK
{
"data": {
"CreateInstance": {
"ID": "AB89BC5A-3E72-4CFD-B5FA-3F216BB33601",
"ModelID": "D9117AE5-3F3E-4436-9A2A-6DD725FBD8FB",
"Name": "apiInstance",
"Topic": "digitaltwins_apiInstance",
"Interval": 1,
"FlatHierarchy": false
}
}
}
Delete Instance
POST {{edgeUrl}}/digital-twins
Delete Instance
Deletes an instance and all of its per-instance attribute overrides. The parent model is not affected.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation DeleteInstance($input: DeleteInstanceRequest!) {
DeleteInstance(input: $input)
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the instance to delete. |
{
"input": {
"ID": "{{digital_twins_instance_id}}"
}
}
Response
200 OK -- application/json. No data returned on success.
{ "data": { "DeleteInstance": 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
mutation DeleteInstance ($input: DeleteInstanceRequest!) {
DeleteInstance(input:$input)
}
Variables
{
"input": {
"ID":"AB89BC5A-3E72-4CFD-B5FA-3F216BB33601"
}
}
Response
Status: 200 OK
{
"data": {
"DeleteInstance": null
}
}
Update Instance
POST {{edgeUrl}}/digital-twins
Update Instance
Updates the top-level fields of an instance (Name, Topic, Interval, FlatHierarchy). The ModelID is not re-assignable -- delete and recreate to change models.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation UpdateInstance($input: UpdateInstanceRequest!) {
UpdateInstance(input: $input) {
ID
ModelID
Name
Topic
Interval
FlatHierarchy
}
}
Variables
Same fields as Create Instance, plus:
| Field | Type | Required | Description |
|---|---|---|---|
ID |
ID |
Yes | UUID of the instance to update. |
{
"input": {
"ID": "{{digital_twins_instance_id}}",
"ModelID": "{{digital_twins_model_id}}",
"Name": "updated_{{digital_twins_instance}}",
"Interval": 1,
"Topic": "digitaltwins_updated_{{digital_twins_instance}}",
"FlatHierarchy": false
}
}
Response
200 OK -- application/json. Returns the updated instance.
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 UpdateInstance($input: UpdateInstanceRequest!) {
UpdateInstance(input: $input) {
ID
ModelID
Name
Topic
Interval
FlatHierarchy
}
}
Variables
{
"input": {
"ID": "{{digital_twins_instance_id}}",
"ModelID": "{{digital_twins_model_id}}",
"Name": "updated_{{digital_twins_instance}}",
"Interval": 1,
"Topic": "digitaltwins_updated_{{digital_twins_instance}}",
"FlatHierarchy": false
}
}
Response
Status: 200 OK
{
"data": {
"UpdateInstance": {
"ID": "D0C8844D-EF72-4933-BB5E-B74372B33F4B",
"ModelID": "D9117AE5-3F3E-4436-9A2A-6DD725FBD8FB",
"Name": "Instance1",
"Topic": "digitaltwins_Instance1",
"Interval": 1,
"FlatHierarchy": false
}
}
}
Set Instance State
POST {{edgeUrl}}/digital-twins
Set Instance State
Enables or disables an instance. A disabled instance is configured but does not publish to its topic; enabled instances actively run.
Use this to pause/resume publishing without deleting and recreating the instance.
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation SetInstanceState($input: SetInstanceStateRequest!) {
SetInstanceState(input: $input)
}
Variables
| Field | Type | Required | Description |
|---|---|---|---|
InstanceID |
ID |
Yes | UUID of the instance. |
IsEnabled |
Boolean |
Yes | true to enable, false to disable. |
{
"input": {
"InstanceID": "{{digital_twins_instance_id}}",
"IsEnabled": true
}
}
Response
200 OK -- application/json
| Field | Type | Description |
|---|---|---|
data.SetInstanceState |
Boolean |
true on success. |
{ "data": { "SetInstanceState": 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
mutation SetInstanceState ($input: SetInstanceStateRequest!) {
SetInstanceState(input: $input)
}
Variables
{
"input": {
"InstanceID": "{{digital_twins_instance_id}}",
"IsEnabled": true
}
}
Response
Status: 200 OK
{
"data": {
"SetInstanceState": true
}
}
Save Instance/ Add Topic to Dynamic Attribute
POST {{edgeUrl}}/digital-twins/
Save Instance / Add Topic to Dynamic Attribute (transactional)
Applies one or more updates to an instance's per-instance static and dynamic attribute overrides in a single transaction. This is the same shape as Models > Parameters > Set Parameters, but scoped to instance overrides instead of model schema.
The most common use case is adding a topic to a dynamic attribute override -- this is the step that actually binds the dynamic attribute to a live data source (typically a DeviceHub tag topic).
Endpoint
POST {{edgeUrl}}/digital-twins
Content-Type: application/json
The operation is chosen by the GraphQL query body, not the URL path.
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
mutation TransactionalInstanceUpdate($input: TransactionalInstanceUpdateRequest!) {
TransactionalInstanceUpdate(input: $input)
}
Variables
The input is an envelope of per-operation arrays. Send only the arrays you need; the others can be empty Items: [].
| Field | Type | Description |
|---|---|---|
updateStaticAttributes |
{ Items } |
List of per-instance static attribute payloads to update. |
updateDynamicAttributes |
{ Items } |
List of per-instance dynamic attribute payloads to update (e.g. set Topic). |
{
"input": {
"updateStaticAttributes": { "Items": [] },
"updateDynamicAttributes": {
"Items": [
{
"__typename": "DynamicAttribute",
"ID": "{{digital_twins_dynamic_attribute_id}}",
"ModelID": "{{digital_twins_model_id}}",
"InstanceID": "{{digital_twins_instance_id}}",
"Topic": "<devicehub-tag-topic>",
"Name": "Speed",
"Unit": "kmph",
"DataType": "string",
"SchemaID": "30D86400-D103-4C5C-95E4-AB6F02FB00EE"
}
]
}
}
}
To discover the right Topic value for a DeviceHub-backed signal, list the device's registers via DeviceHub > Tags > List Registers from Single Device and inspect Topics[].Topic.
Response
200 OK -- application/json. No data returned on success.
{ "data": { "TransactionalInstanceUpdate": 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
mutation TransactionalInstanceUpdate($input: TransactionalInstanceUpdateRequest!) {
TransactionalInstanceUpdate(input: $input)
}
Variables
{
"input": {
"updateStaticAttributes": {
"Items": []
},
"updateDynamicAttributes": {
"Items": [
{
"__typename": "DynamicAttribute",
"ID":"{{digital_twins_dynamic_attribute_id}}",
"ModelID": "{{digital_twins_model_id}}",
"InstanceID": "{{digital_twins_instance_id}}",
"Topic": "devicehub.raw.779F42F3-54FC-4A87-B9A6-CD39CFA4A97D.1A5572B2-8242-40C8-BC63-FFEBC7DAF1E4",
"Name": "Speed",
"Unit": "kmph",
"DataType": "string",
"AttrDataType": "string",
"SchemaID": "4C67A3E1-D442-4B39-B0F6-EB07CC200066"
}
]
}
}
}
Response
Status: 200 OK
{
"data": {
"TransactionalInstanceUpdate": null
}
}