Workflow 6: Create DeviceHub Device + Tags
You are at https://api.litmus.io/workflows/create-device-with-tags.md Parent: https://api.litmus.io/workflows/agents.md If this is the wrong workflow, back out to the index above.
6. Create DeviceHub Device + Tags
UI trigger: DeviceHub -> Add Device -> (configure) -> Add Tag
This is the most common chain customers struggle with. Each sub-step feeds data into the next.
Step table
| Step | API Name | Method | Endpoint / GraphQL Operation | Input | Output / What to capture |
|---|---|---|---|---|---|
| 1 | List Drivers | POST |
{{edgeUrl}}/devicehub/v2 -> ListDriverGroups |
No input required | DriverID, Name per protocol (e.g. Modbus TCP, OPC UA, etc.) |
| 2 | Get Driver Template | POST |
{{edgeUrl}}/devicehub/v2 -> GetDriver |
{ID: "<DriverID from step 1>"} |
DeviceProperties (required fields/tabs for device config) and SupportedRegisters[].Name, ReadOnly, RegisterProperties (valid register types for this driver) |
| 3 | Validate Device (optional) | POST |
{{edgeUrl}}/devicehub/v2 -> ValidateCreateDevice |
Same CreateDeviceRequest as step 4 |
Errors[]; creates nothing |
| 4 | Create Device | POST |
{{edgeUrl}}/devicehub/v2 -> CreateDevice |
Driver ID + device properties from step 2. StoppedState: true creates it without connecting |
DeviceID |
| 5 | Validate Tags (optional) | POST |
{{edgeUrl}}/devicehub/v2 -> ValidateCreateRegisters |
Same CreateRegistersRequest as step 6 |
Errors[]; creates nothing. Does not check the license tag limit |
| 6 | Create Tags | POST |
{{edgeUrl}}/devicehub/v2 -> CreateRegisters |
DeviceID (step 4) + register type (step 2) + tag properties; one or many in the Registers array |
Tag IDs, tags are live |
| - | Clean Up: Delete Device and its Tags | POST |
{{edgeUrl}}/devicehub/v2 -> DeleteDevices |
IDs: [DeviceID] |
Device and its tags removed (persisted time-series data is kept until retention) |
Why the register types from step 2 are critical: Each driver supports a different set of register types (e.g. Modbus TCP supports
Holding Register,Input Register,Coil,Discrete Input). CallingCreateRegisterswith an unsupported type returns a validation error. Always checkSupportedRegistersbefore building theCreateRegisterspayload.Pre-validation: steps 3 and 5 dry-run the exact payloads of steps 4 and 6 and return
Errors[]without committing anything. A payload that validates clean can be sent unchanged.