Devices Domain
The Devices domain provides endpoints for querying devices registered within a client organization. Devices are machines running the desktop agent. They are identified by a stable id and may be associated with one or more users over time via the user_devices junction table.
For embedding and endpoint design decisions, see the Design Guidelines.
Endpoints
| Endpoint | Method | Description |
|---|---|---|
| List Devices | GET | Paginated list of devices. Use for inventory tables and search. |
| Get Device | GET | Fetch a single device directly by ID. |
| Device Summary | GET | Fleet-level aggregate stats: total count, agent versions, browser extension versions, deployment errors. |
| Device Users | GET | Users observed on a specific device. |
| Device Deployments | GET | Enrollment deployment history for a device. |
| Update Device Controls | PATCH | Update a single device's collection state and log shipping. |
| Bulk Enable Devices | POST | Enable collection on multiple devices. |
| Bulk Disable Devices | POST | Disable collection on multiple devices. |
| Bulk Delete Devices | POST | Mark multiple devices as deleted. |
Getting Devices by User
To retrieve devices used by a specific user, use the List Devices endpoint with the user_id filter:
GET /clients/{client_id}/devices?user_id=a1d97031-04e2-4907-a249-093f7436207b
Devices are not embedded in user responses because a user can use many devices over time -- an unbounded, paginated relationship. See Why devices are not embedded below.
Data Transfer Objects (DTOs)
DeviceRef
Minimal device reference for embedding inside other domain responses (e.g. as a cross-domain link). Contains only fields available directly from the devices table that are useful in a reference context. No joins required.
{
"id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"name": "DESKTOP-DEV-ALICE",
"status": "active",
"os_name": "Windows",
"os_version": "10.0.19045",
"last_seen_at": "2026-02-24T21:23:53.082Z"
}
| Field | Type | Nullable | Description |
|---|---|---|---|
id | string (uuid) | No | Stable unique identifier for the device |
name | string | Yes | Device hostname or friendly name |
status | string | Yes | Last known device status: active, inactive, pending |
os_name | string | Yes | Operating system name (e.g. Windows, macOS, Linux) |
os_version | string | Yes | Operating system version string |
last_seen_at | string (ISO 8601) | Yes | When the device last sent a heartbeat |
DB source: devices.id, devices.name, devices.status, devices.os_name, devices.os_version, devices.last_seen_at_utc
Used in: Any domain response that references a device as a non-primary resource.
Device
Full device representation returned by device-primary endpoints. Extends DeviceRef with hardware specs, browser extension versions, agent info, collection control fields, and audit timestamps.
{
"id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"name": "DESKTOP-DEV-ALICE",
"status": "active",
"serial_number": "5CG1234567",
"unique_key": "DESKTOP-DEV-ALICE-HWID-5CG1234567",
"os_name": "Windows",
"os_version": "10.0.19045",
"last_seen_at": "2026-02-24T21:23:53.082Z",
"installed_at": "2025-11-01T08:00:00.000Z",
"agent_version": "1.2.3",
"collection_state": "enabled",
"log_shipping_enabled": false,
"effective_mode": "saas_usage",
"deployment_status": "success",
"hardware": {
"manufacturer": "Dell Inc.",
"model": "XPS 15 9520",
"cpu_model": "Intel(R) Core(TM) i7-12700H",
"cpu_cores": 8,
"ram": 17179869184
},
"extensions": [
{
"browser_id": "chrome",
"browser_family": "chromium",
"version": "1.11.0",
"installed": true,
"auto_update": true,
"last_activity_at": "2026-02-24T21:23:53.082Z"
},
{
"browser_id": "edge",
"browser_family": "chromium",
"version": "1.11.0",
"installed": true,
"auto_update": false,
"last_activity_at": "2026-02-24T21:22:00.000Z"
}
],
"created_at": "2025-11-01T08:00:00.000Z",
"updated_at": "2026-02-24T21:23:53.082Z"
}
| Field | Type | Nullable | Description |
|---|---|---|---|
All DeviceRef fields | id, name, status, os_name, os_version, last_seen_at -- see DeviceRef | ||
serial_number | string | Yes | Device serial number reported by the agent |
unique_key | string | Yes | Unique hardware fingerprint used to identify the device |
installed_at | string (ISO 8601) | Yes | When the agent was first installed on this device |
agent_version | string | Yes | Currently installed agent version |
collection_state | string | No | Device-level collection state: enabled, disabled, deleted. Default: enabled. |
log_shipping_enabled | boolean | No | Whether full log shipping is enabled for this device. Default: false. |
effective_mode | string | No | Computed effective collection mode after applying client > device precedence: discovery, saas_usage, disabled, deleted. See Effective Mode Computation. |
deployment_status | string | Yes | Latest deployment status for this device: success, error, pending. Derived from the most recent device_deployments record. null when no deployments exist. |
hardware | object | No | Hardware specifications |
hardware.manufacturer | string | Yes | Device manufacturer (e.g. Dell Inc., Apple Inc.) |
hardware.model | string | Yes | Device model name |
hardware.cpu_model | string | Yes | CPU model string |
hardware.cpu_cores | integer | Yes | Number of CPU cores |
hardware.ram | integer | Yes | Total RAM in bytes |
extensions | object[] | No | Browser extension installation status entries |
extensions[].browser_id | string | No | Browser identifier (for example chrome, edge, firefox) |
extensions[].browser_family | string | No | Browser family (for example chromium, firefox) |
extensions[].version | string | Yes | Installed extension version. null if not installed. |
extensions[].installed | boolean | No | Whether the extension is installed |
extensions[].auto_update | boolean | No | Whether the extension is set to auto-update |
extensions[].last_activity_at | string (ISO 8601) | Yes | Last activity timestamp for this extension |
created_at | string (ISO 8601) | No | When this device record was first created |
updated_at | string (ISO 8601) | No | When this device record was last modified |
DB source:
| DTO Field | DB Column |
|---|---|
| (DeviceRef fields) | see DeviceRef |
serial_number | devices.serial_number |
unique_key | devices.unique_key |
installed_at | devices.installed_at_utc |
agent_version | devices.agent_version |
collection_state | devices.collection_state |
log_shipping_enabled | devices.log_shipping_enabled |
effective_mode | computed from clients.collection_mode + devices.collection_state (requires JOIN) |
deployment_status | derived subquery: latest device_deployments.status ordered by enrollment_date DESC NULLS LAST, created_at DESC |
hardware.manufacturer | devices.manufacturer |
hardware.model | devices.model |
hardware.cpu_model | devices.cpu_model |
hardware.cpu_cores | devices.cpu_cores |
hardware.ram | devices.ram |
extensions[] | devices.browser_extensions when present; otherwise synthesized from legacy devices.chrome_extension_*, devices.edge_extension_*, devices.firefox_extension_* and corresponding last-activity columns |
created_at | devices.created_at |
updated_at | devices.updated_at |
Omitted internal fields: client_id (in URL path), partner_id, created_by, updated_by, cpu_avg_percent, cpu_min_percent, cpu_max_percent, ram_avg_mb, ram_min_mb, ram_max_mb, resource_recorded_at_utc (metrics -- not device identity)
Used in: Get Device, List Devices, Update Device Controls
Why collection control fields are not on DeviceRef: DeviceRef is a minimal reference for embedding in other domain responses with no joins required. collection_state and log_shipping_enabled are operational control metadata (not identity/reference data), and effective_mode requires a JOIN to the clients table -- both violate DeviceRef's purpose.
DeviceUserRef
A user observed on a device, returned by Device Users. Wraps UserRef with the junction-level last_seen_at from user_devices.
The user identity fields (UserRef) come from the users table. The enrolled_at and last_seen_at fields come from the user_devices junction table and are specific to this device-user pairing.
{
"id": "a1d97031-04e2-4907-a249-093f7436207b",
"username": "mikechang",
"user_key": "mikechang",
"status": "active",
"last_activity": {
"at": "2026-02-24T21:23:53.082Z",
"desktop_at": "2026-02-22T08:00:00.000Z",
"web_at": "2026-02-24T21:23:53.082Z"
},
"enrolled_at": "2025-11-01T08:00:00.000Z",
"last_seen_at": "2026-02-24T21:23:53.082Z"
}
| Field | Type | Nullable | Description |
|---|---|---|---|
All UserRef fields | id, username, user_key, status, last_activity -- see UserRef | ||
enrolled_at | string (ISO 8601) | No | When this user was first associated with this device |
last_seen_at | string (ISO 8601) | Yes | When this user was last seen on this device |
DB source:
| DTO Field | DB Column |
|---|---|
| (UserRef fields) | see UserRef |
enrolled_at | user_devices.created_at |
last_seen_at | user_devices.last_seen_at_utc |
Used in: Device Users
DeviceDeploymentRef
Minimal deployment reference for list views. Represents a single desktop-agent deployment event for a device, including the metadata needed to label the deployed agent version in the UI.
{
"id": "d1e2f3a4-b5c6-7890-abcd-ef1234567890",
"deployment_type": "desktop_agent",
"agent_version": "2.14.3",
"status": "success",
"enrollment_date": "2026-01-30T14:30:00.000Z"
}
| Field | Type | Nullable | Description |
|---|---|---|---|
id | string (uuid) | No | Unique deployment event identifier |
deployment_type | string | No | Type of deployed software. Currently always desktop_agent for this endpoint version. |
agent_version | string | Yes | Desktop agent version deployed in this event. |
status | string | Yes | Deployment status: success, error, pending |
enrollment_date | string (ISO 8601) | Yes | When the device was enrolled via this deployment |
DB source: device_deployments.id, desktop-agent release metadata joined from the deployed artifact record, device_deployments.status, device_deployments.enrollment_date
Used in: Deployment list endpoint
DeviceDeployment
Full deployment record returned by the deployment detail endpoint. Extends DeviceDeploymentRef with the enrollment token reference, user linkage, error logs, and audit timestamps.
{
"id": "d1e2f3a4-b5c6-7890-abcd-ef1234567890",
"deployment_type": "desktop_agent",
"agent_version": "2.14.2",
"status": "error",
"enrollment_date": "2026-01-30T14:30:00.000Z",
"enrollment_token_id": "e1f2a3b4-c5d6-7890-abcd-ef1234567890",
"user_id": "a1d97031-04e2-4907-a249-093f7436207b",
"error_logs": [
"2026-01-30T14:30:05Z: Downloading agent package...",
"2026-01-30T14:30:15Z: Installation failed - insufficient permissions",
"2026-01-30T14:30:15Z: Deployment aborted"
],
"created_at": "2026-01-30T14:30:00.000Z",
"updated_at": "2026-01-30T14:30:15.000Z"
}
| Field | Type | Nullable | Description |
|---|---|---|---|
All DeviceDeploymentRef fields | id, deployment_type, agent_version, status, enrollment_date -- see DeviceDeploymentRef | ||
enrollment_token_id | string (uuid) | No | The enrollment token used for this deployment |
user_id | string (uuid) | Yes | The user associated with this deployment |
error_logs | string[] | Yes | Deployment log entries (chronological). null or empty for successful deployments. |
created_at | string (ISO 8601) | No | When this deployment record was created |
updated_at | string (ISO 8601) | No | When this deployment record was last modified |
DB source:
| DTO Field | DB Column |
|---|---|
| (DeviceDeploymentRef fields) | see DeviceDeploymentRef |
enrollment_token_id | device_deployments.enrollment_token_id |
user_id | device_deployments.user_id |
error_logs | device_deployments.error_logs |
created_at | device_deployments.created_at |
updated_at | device_deployments.updated_at |
Omitted internal fields: device_id (in URL path), created_by, updated_by
Used in: Deployment detail endpoint
Effective Mode Computation
effective_mode is a computed field resolved at query time by applying the three-tier precedence model: Client > Device > User. Client-level controls always take precedence over device-level controls.
Client collection_mode | Device collection_state | effective_mode |
|---|---|---|
disabled or deleted | (any) | client mode (overrides device) |
discovery or saas_usage | disabled or deleted | device state |
discovery or saas_usage | enabled | client mode |
This field requires a JOIN to the clients table, which is acceptable on full Device queries but would violate DeviceRef's "no joins" rule.
BulkDeviceControlResult
Response shape for all bulk device control endpoints (Enable, Disable, Delete).
{
"succeeded": [
"f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"a9b8c7d6-e5f4-3210-fedc-ba9876543210"
],
"failed": [
{
"id": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"error": "Device not found"
}
]
}
| Field | Type | Description |
|---|---|---|
succeeded | string (uuid)[] | Device IDs successfully updated |
failed | object[] | Device IDs that failed with error details |
failed[].id | string (uuid) | The device ID that failed |
failed[].error | string | Reason for the failure |
Why devices are not embedded
User does not include a devices array. This is intentional:
| Relationship | Cardinality | Strategy | Reason |
|---|---|---|---|
| User → Devices | 1:many (unbounded) | GET /devices?user_id= | Unbounded, needs pagination |
| Device → Users | 1:many (usually 1–3) | GET /devices/{id}/users | Sub-resource with junction context |
The device-to-user relationship uses a sub-resource endpoint (/devices/{id}/users) rather than a filter because it is device-primary -- the device is the subject. The user-to-device direction uses the filter pattern (/devices?user_id=) to stay consistent with V2's filter-based cross-resource queries.
To get devices for a user:
GET /clients/{client_id}/devices?user_id=a1d97031-04e2-4907-a249-093f7436207b