Appearance
Devicegroup
A device group is a named set of devices within one tenant, and the unit access is granted on: a rule on a group's .devices carries its read and update through to every member — those two only, and a deny carries through as a deny. Rules are expanded per request, so a membership change takes effect on the next one, without a new token.
Membership is a link: a device may sit in several groups, and the same link pairs devices to roles and users, so DEVICEGROUP_LINK_DEVICE and DEVICEGROUP_UNLINK_DEVICE also report pairings made through device pairing. A member's own data comes from flake and meta.
| POST | Create a device group/api/v1/group |
| GET | List device groups/api/v1/group |
| GET | Read a device group/api/v1/group/:groupId |
| PATCH | Update a device group/api/v1/group/:groupId |
| DELETE | Delete a device group/api/v1/group/:groupId |
| GET | List devices in a group/api/v1/group/:groupId/devices |
| POST | Add a device to a group/api/v1/group/:groupId/devices |
| DELETE | Remove a device from a group/api/v1/group/:groupId/devices/:deviceId |
Create a device group
Creates an empty group and answers with its CRN; devices join afterwards through …/devices. tenantId is only needed when the caller's access spans several tenants — otherwise the tenant follows from that access.
POST
/api/v1/groupBody
| Name | Description |
|---|---|
namestring | Display name of the group, 1 to 64 characters. min length 1 · max length 64 |
descriptionstringoptional | Free text about the group; may be left out. |
tenantIdstringoptional | Tenant the group belongs to; only needed when the caller's access spans several tenants, otherwise it follows from that access. Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$ |
Response
| Name | Description |
|---|---|
resourceIdentifierstring | Unique Coldwave resource name (CRN) that identifies a resource |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
List device groups
Every group of the caller's tenant that the caller may read — a principal scoped to single groups sees exactly those. Members are not part of a group entry; they are a separate call.
GET
/api/v1/groupResponse
| Name | Description |
|---|---|
namestring | Display name of the group, 1 to 64 characters. min length 1 · max length 64 |
descriptionstringoptional | Free text about the group; absent when none was set. |
resourceIdentifierstring | Unique Coldwave resource name (CRN) that identifies a resource |
createdBystring | Resource identifier of the entity that created this resource |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Read a device group
The group entry without its members — those come from a separate call, GET /group/{groupId}/devices.
GET
/api/v1/group/Yk3pL7rWq2Path Parameters
| Name | Description |
|---|---|
groupIdstring | Resource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID. Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$ |
Response
| Name | Description |
|---|---|
namestring | Display name of the group, 1 to 64 characters. min length 1 · max length 64 |
descriptionstringoptional | Free text about the group; absent when none was set. |
resourceIdentifierstring | Unique Coldwave resource name (CRN) that identifies a resource |
createdBystring | Resource identifier of the entity that created this resource |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
404 | No group with this {groupId} in the tenant — or, on the device routes, a device that is not in this tenant (adding) or not a member of the group (removing). Check the ids against GET /group and its device listing. | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Update a device group
Changes name, description or both; a field left out keeps its value. Membership is not part of the body — it moves through …/devices.
PATCH
/api/v1/group/Yk3pL7rWq2Path Parameters
| Name | Description |
|---|---|
groupIdstring | Resource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID. Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$ |
Body
| Name | Description |
|---|---|
namestringoptional | New display name, 1 to 64 characters. min length 1 · max length 64 |
descriptionstringoptional | New description; leaving it out keeps the previous one rather than clearing it. |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
404 | No group with this {groupId} in the tenant — or, on the device routes, a device that is not in this tenant (adding) or not a member of the group (removing). Check the ids against GET /group and its device listing. | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Delete a device group
Deletes the group and ends the membership of every device in it. The devices themselves stay in the tenant; what goes with the group is the access it granted on its .devices.
DELETE
/api/v1/group/Yk3pL7rWq2Path Parameters
| Name | Description |
|---|---|
groupIdstring | Resource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID. Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$ |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
404 | No group with this {groupId} in the tenant — or, on the device routes, a device that is not in this tenant (adding) or not a member of the group (removing). Check the ids against GET /group and its device listing. | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
List devices in a group
The members of the group as id and CRN — the membership list, not the devices' own data. Gated on read on the group, not on the member devices.
GET
/api/v1/group/Yk3pL7rWq2/devicesPath Parameters
| Name | Description |
|---|---|
groupIdstring | Resource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID. Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$ |
Response
| Name | Description |
|---|---|
deviceIdstring | Id of the member device — what the removal route takes in its path. |
resourceIdentifierstring | Unique Coldwave resource name (CRN) that identifies a resource |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
404 | No group with this {groupId} in the tenant — or, on the device routes, a device that is not in this tenant (adding) or not a member of the group (removing). Check the ids against GET /group and its device listing. | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Add a device to a group
Adds a device to the group; the caller must already be able to read it, and deviceId takes the device id or its IMEI. Adding a member twice changes nothing; the response carries the device's CRN, and access granted on the group's .devices reaches the member from the next request onwards.
POST
/api/v1/group/Yk3pL7rWq2/devicesPath Parameters
| Name | Description |
|---|---|
groupIdstring | Resource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID. Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$ |
Body
| Name | Description |
|---|---|
| deviceId | The device's own id, or its IMEI as an alias. |
Alternative 1string | Resource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID. Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$ |
Alternative 2string | The device's own id, or its IMEI as an alias. max length 16 Pattern: ^[0-9a-fA-F]+$ |
Response
| Name | Description |
|---|---|
resourceIdentifierstring | Unique Coldwave resource name (CRN) that identifies a resource |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
404 | No group with this {groupId} in the tenant — or, on the device routes, a device that is not in this tenant (adding) or not a member of the group (removing). Check the ids against GET /group and its device listing. | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Remove a device from a group
Ends the membership; the device itself is untouched, only the access the group granted on its .devices stops reaching it. The path takes the device's own id, not the IMEI alias the add route accepts — an IMEI there reads as not found.
DELETE
/api/v1/group/Yk3pL7rWq2/devices/Yk3pL7rWq2Path Parameters
| Name | Description |
|---|---|
groupIdstring | Resource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID. Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$ |
deviceIdstring | Resource id: Base58 (9–10 characters) or a 16-character Crockford snowflake. Not an RFC 4122 UUID. Pattern: ^[0-9A-HJ-NP-Za-km-z]{9,16}$ |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
404 | No group with this {groupId} in the tenant — or, on the device routes, a device that is not in this tenant (adding) or not a member of the group (removing). Check the ids against GET /group and its device listing. | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Events
Published on the tenant's event stream and delivered over the websocket to every subscriber holding read on the resource the message names. resourceIdentifier is the resource the action changed; the payload is the shape below.
| Event | Description |
|---|---|
DEVICEGROUP_CREATE | A device group was created, carrying its name and the user who created it. It starts empty — members arrive as their own events. |
DEVICEGROUP_DELETE | A group was deleted and every device in it lost its membership; no unlink event is emitted for those devices. |
DEVICEGROUP_LINK_DEVICE | A device was paired to a group, a role or a user — through the group's device route, through POST /pair, or through POST /user/register with a claim code. resourceIdentifier names the group, role or user, device the device. |
DEVICEGROUP_UNLINK_DEVICE | A pairing between a device and a group, role or user ended — through the group's device route, or through DELETE /pair. Deleting the device, the user or the group drops the pairing without this event. |
DEVICEGROUP_UPDATE | The name or description of a group was changed; the payload carries only what the request sent. |
Device group created
A device group was created, carrying its name and the user who created it. It starts empty — members arrive as their own events.
EVENT
DEVICEGROUP_CREATEPayload
| Name | Description |
|---|---|
namestring | Display name of the group, 1 to 64 characters. min length 1 · max length 64 |
descriptionstringoptional | Free text about the group; absent when none was set. |
resourceIdentifierstring | Unique Coldwave resource name (CRN) that identifies a resource |
createdBystring | Resource identifier of the entity that created this resource |
Device group deleted
A group was deleted and every device in it lost its membership; no unlink event is emitted for those devices.
EVENT
DEVICEGROUP_DELETEPayload
| Name | Description |
|---|
Device paired
A device was paired to a group, a role or a user — through the group's device route, through POST /pair, or through POST /user/register with a claim code. resourceIdentifier names the group, role or user, device the device.
EVENT
DEVICEGROUP_LINK_DEVICEPayload
| Name | Description |
|---|---|
devicestring | Unique Coldwave resource name (CRN) that identifies a resource |
Device unpaired
A pairing between a device and a group, role or user ended — through the group's device route, or through DELETE /pair. Deleting the device, the user or the group drops the pairing without this event.
EVENT
DEVICEGROUP_UNLINK_DEVICEPayload
| Name | Description |
|---|---|
devicestring | Unique Coldwave resource name (CRN) that identifies a resource |
Device group changed
The name or description of a group was changed; the payload carries only what the request sent.
EVENT
DEVICEGROUP_UPDATEPayload
| Name | Description |
|---|---|
namestringoptional | New display name, 1 to 64 characters. min length 1 · max length 64 |
descriptionstringoptional | New description; leaving it out keeps the previous one rather than clearing it. |