Skip to content

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.

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.

FieldRequiredDescription
nameyesHuman-readable device name
hardware_idyesStable hardware identifier; unique within the tenant
groupsnoGroup names the device joins
tagsnoKey/value tags for filtering and organization
anchor_modenoBlockchain anchoring mode (ANCHOR_MODE_MERKLE_BATCH default, ANCHOR_MODE_PER_EVENT, ANCHOR_MODE_HASH_CHAIN)
profile_idnoDevice profile to inherit defaults from
gateway_idnodevice_id of a parent gateway, if this is a child device
firmwarenoInitial firmware version string
metanoFree-form key/value metadata
confignoDesired-state config delivered to the device
Terminal window
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"
}'

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.

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.

Use manual registration when…Use key claim when…
You have a handful of devicesYou have a factory batch or fleet
An admin/operator is in the loopDevices must come online unattended
You want the device record set up before the hardware shipsThe hardware self-registers on first boot
You’re testing or integrating one deviceYou’re rolling out at scale

For batches, generate keys with bulk import and let devices claim themselves.