Manual registration
Manual registration creates a single device directly, as an authenticated admin. It is the simplest way to bring a device online when you don’t need a self-provisioning flow — a lab device, a one-off integration, or the first device you connect while learning the platform.
The operation is DeviceRegistryService.RegisterDevice, exposed as
POST /api/v1/devices.
Who can call it
Section titled “Who can call it”This is an admin/dashboard operation, authenticated with a dashboard user’s
Ed25519 JWT — not a device credential. The caller must be a tenant_admin (or
platform_admin) for the tenant, or a member with the devices permission. The
tenant is taken from the JWT, never from the request body.
Request fields
Section titled “Request fields”| Field | Required | Description |
|---|---|---|
name | yes | Human-readable device name |
hardware_id | yes | Stable hardware identifier; unique within the tenant |
groups | no | Group names the device joins |
tags | no | Key/value tags for filtering and organization |
anchor_mode | no | Blockchain anchoring mode (ANCHOR_MODE_MERKLE_BATCH default, ANCHOR_MODE_PER_EVENT, ANCHOR_MODE_HASH_CHAIN) |
profile_id | no | Device profile to inherit defaults from |
gateway_id | no | device_id of a parent gateway, if this is a child device |
firmware | no | Initial firmware version string |
meta | no | Free-form key/value metadata |
config | no | Desired-state config delivered to the device |
Example
Section titled “Example”curl -sS -X POST https://api.kronoxdata.com/api/v1/devices \ -H "Authorization: Bearer <DASHBOARD_JWT>" \ -H "Content-Type: application/json" \ -d '{ "name": "Lab Bench Thermometer", "hardware_id": "HW-LAB-0001", "groups": ["lab", "floor-3"], "tags": { "region": "eu", "owner": "qa" }, "anchor_mode": "ANCHOR_MODE_MERKLE_BATCH", "profile_id": "p_temp_sensor_v2" }'Response
Section titled “Response”RegisterDevice returns the full device record, including its generated
device_id and a provisioning credential (an api_key, or a client certificate
depending on the credentials policy):
{ "device_id": "3a9f1d22-6b4c-4e8a-bf21-90c7e5d4a118", "tenant_id": "11111111-1111-1111-1111-111111111111", "name": "Lab Bench Thermometer", "hardware_id": "HW-LAB-0001", "status": "registered", "groups": ["lab", "floor-3"], "tags": { "region": "eu", "owner": "qa" }, "anchor_mode": "ANCHOR_MODE_MERKLE_BATCH", "profile_id": "p_temp_sensor_v2", "api_key": "sk_live_Zr8K2mQx...redacted...", "created_at": "2026-05-29T10:15:00Z"}On success the platform also publishes a device.registered event for downstream
services.
Duplicate hardware_id
Section titled “Duplicate hardware_id”hardware_id is unique within a tenant. Registering a second device with a
hardware_id that already exists in the tenant is rejected:
{ "code": "ALREADY_EXISTS", "message": "device with hardware_id \"HW-LAB-0001\" already exists in this tenant"}No device is created and no event is published. This differs from
key claim, which treats a repeated
hardware_id as an idempotent re-claim of the existing device rather than an
error. The distinction is intentional: an admin registering by hand almost always
means it as a new device, so a clash is surfaced loudly; a device re-booting and
re-claiming means “it’s me again”, so it succeeds quietly.
When to use this vs key claim
Section titled “When to use this vs key claim”| Use manual registration when… | Use key claim when… |
|---|---|
| You have a handful of devices | You have a factory batch or fleet |
| An admin/operator is in the loop | Devices must come online unattended |
| You want the device record set up before the hardware ships | The hardware self-registers on first boot |
| You’re testing or integrating one device | You’re rolling out at scale |
For batches, generate keys with bulk import and let devices claim themselves.