Device Groups
Base path: /cgg/groups — every route requires authentication, either an API key
or a signed-in session.
A device group binds a set of devices to a project version and to shared settings and tables. Changing the group's firmware, variables or tables applies the change to every member device, and any device added later inherits the group's current configuration.
Groups follow the same access rules as devices: personal groups belong to their
creator, workspace groups are reachable by workspace members, and workspace
operators are read-only.
| Method | Path | Purpose |
|---|---|---|
| GET | /cgg/groups | List groups |
| POST | /cgg/groups | Create a group |
| GET | /cgg/groups/:id | Get one group |
| PUT | /cgg/groups/:id | Rename or re-target a group |
| DELETE | /cgg/groups/:id | Delete a group |
| POST | /cgg/groups/:id/firmware | Push a firmware version to all members |
| POST | /cgg/groups/:id/devices | Add devices to the group |
| DELETE | /cgg/groups/:id/devices/:deviceId | Remove a device from the group |
| POST | /cgg/groups/:id/variables | Set shared settings on all members |
| POST | /cgg/groups/:id/tables | Save a shared table on all members |
| DELETE | /cgg/groups/:id/tables/:tableName | Remove a shared table from the group |
The group object
{
"_id": "664a20fa8c9d0e00112233aa",
"name": "Floor 2 boilers",
"user": "8a3f…",
"workspace": "664a1f2b8c9d0e0011223344",
"tenant": "664a20338c9d0e0011223399",
"project": "664a1f2b8c9d0e0011223301",
"projectVersion": "664a1f9c8c9d0e0011223377",
"settings": [
{ "variable": "setpoint", "value": 21 }
],
"tables": [
{ "name": "schedule", "data": "hour,value\r\n8,21\r\n" }
],
"createdAt": "…",
"updatedAt": "…"
}
settings holds the delegated variable values, tables the delegated table
contents. Group membership itself lives on the device (device.group), not in
the group document.
List groups
GET /cgg/groups
| Query parameter | Description |
|---|---|
start | Offset, default 0 |
count | Page size, default 10 |
search | Case-insensitive match on group name |
workspace | Return groups of this workspace instead of personal groups |
tenant | Restrict to a tenant. With workspace and no tenant, only groups without a tenant are returned |
Each returned group is augmented with a devices array containing the
deviceIds of its member devices.
{
"count": 3,
"data": [
{ "_id": "664a20fa…", "name": "Floor 2 boilers", "devices": ["665f3c1e…", "665f3c22…"] }
]
}
Create a group
POST /cgg/groups
{
"name": "Floor 2 boilers",
"workspace": "664a1f2b8c9d0e0011223344",
"tenant": "664a20338c9d0e0011223399",
"project": "664a1f2b8c9d0e0011223301",
"version": "664a1f9c8c9d0e0011223377"
}
All fields except name are optional. Note that the request field is version
while the stored field is projectVersion. Creating a group inside a tenant
requires tenant admin rights or workspace admin rights; operators cannot
create groups.
Get one group
GET /cgg/groups/:id
Returns the group with project and projectVersion populated as full
documents.
Update a group
PUT /cgg/groups/:id
{
"name": "Floor 2 boilers",
"project": "664a1f2b8c9d0e0011223301",
"version": "664a1fd18c9d0e0011223388"
}
When both project and version are supplied, the group is re-targeted to the
new project version and its delegated configuration is reconciled: each entry in
settings and tables is compared against the new version's stg (settings)
and tbl (tables) feature definitions, and entries that no longer exist or whose
definition changed are dropped. The response is the raw Mongo update result.
Delete a group
DELETE /cgg/groups/:id
Clears the group reference on every member device, then deletes the group. The
devices themselves are kept.
Add and remove devices
POST /cgg/groups/:id/devices
DELETE /cgg/groups/:id/devices/:deviceId
{ "devices": ["665f3c1e9d1b4a0012a7c8d1", "665f3c229d1b4a0012a7c8d2"] }
devices contains device _ids. Each device is assigned to the group and
immediately receives the group's current tables and settings — they are written
to the device's changes and pushed over MQTT. Returns 200 with an empty body.
DELETE …/devices/:deviceId unsets the device's group field; the device keeps
whatever values it already received.
Assign firmware to a group
POST /cgg/groups/:id/firmware
{ "versionId": "664a1f9c8c9d0e0011223377" }
Every device in the group is told to download the version's firmware URL, and
each device's changes.firmware is updated. A single audit log entry of type
firmware records the group, the version and all affected deviceIds.
Returns 400 if the project version does not exist.
Set shared settings
POST /cgg/groups/:id/variables
{
"variables": [
{ "variable": "setpoint", "value": 21 },
{ "variable": "mode", "value": "auto" }
]
}
Each entry is written to changes.variables.<variable> on all member devices and
pushed over MQTT, and the list replaces the group's settings, so devices added
later inherit the same values. One audit log entry of type group_setting is
written per variable.
Shared tables
POST /cgg/groups/:id/tables
DELETE /cgg/groups/:id/tables/:tableName
{
"name": "schedule",
"data": "hour,value\r\n8,21\r\n18,18\r\n",
"action": "import"
}
The table is stored in the group's tables array (added, or updated in place)
and pushed to every member device. If the submitted data is identical to what
the group already holds, the request is a no-op. action defaults to import
for the audit log entry.
Returns 400 when the group document has no tables array at all.
DELETE …/tables/:tableName removes the table from the group so future members
no longer receive it, and writes a tables audit entry with action remove. It
does not delete the table from devices that already have it.