---
parent: /workflows/agents.md
back_out_url: /workflows/agents.md
---

# 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 of Drivers | `POST` | `{{edgeUrl}}/devicehub/v2` -> `ListDrivers` | No input required | `DriverID`, `Name` per protocol (e.g. Modbus TCP, OPC UA, etc.) |
| 2 | Get Driver Template by DriverID | `POST` | `{{edgeUrl}}/devicehub/v2` -> `GetDriver` | `{ID: "<DriverID from step 1>"}` | `DeviceProperties` - required fields/tabs for device config |
| 3 | Create New Device | `POST` | `{{edgeUrl}}/devicehub/v2` -> `CreateDevice` | Driver ID + device properties from step 2 | `DeviceID` |
| 4 | Get Driver Supported Registers | `POST` | `{{edgeUrl}}/devicehub/v2` -> `GetDriver` with `SupportedRegisters` | `{ID: "<DriverID>"}` | `SupportedRegisters[].Name`, `ReadOnly`, `RegisterProperties` - valid register types and value types for this driver |
| 5 | Create Tag | `POST` | `{{edgeUrl}}/devicehub/v2` -> `CreateRegisters` | `DeviceID` (step 3) + register type (step 4) + tag properties | Tag ID, tag is live |

> **Why step 4 is critical**: Each driver supports a different set of register types (e.g. Modbus TCP supports `Holding Register`, `Input Register`, `Coil`, `Discrete Input`). Calling `CreateRegisters` with an unsupported type returns a validation error. Always check `SupportedRegisters` before building the `CreateRegisters` payload.

> **Optional pre-validation**: Use `ValidateUpdateRegisters` (GraphQL query) to dry-run a tag payload before actually calling `CreateRegisters`. The query returns `Errors[]` without committing anything.


---
