Datto RMM Devices · git:20260713.1fbd3f3 · 2026-07-13 · sha256 280a4cff4ad58a97
Datto RMM Devices git:20260713.1fbd3f3A
Immutable. This exact content never changes and is served at /api/v1/blob/280a4cff4ad58a97.
---
name: "Datto RMM Devices"
description: >
Use this skill when working with Datto RMM devices - listing, searching,
managing, and monitoring endpoints. Covers device identifiers (UID, hostname, MAC),
device types (workstation, server, ESXi, network), statuses, user-defined fields (UDF1-30),
warranty information, and device operations.
when_to_use: >-
When listing, searching, managing, and monitoring endpoints. Use when: datto device, rmm device,
device status, device lookup, managed device, device hostname, device online, device offline,
endpoint management, or device udf.
---
# Datto RMM Device Management
## Overview
Devices are the core managed entities in Datto RMM. Each device represents an endpoint with the Datto agent installed - workstations, servers, ESXi hosts, or network devices. This skill covers device identification, status monitoring, user-defined fields, and common device operations.
## Key Concepts
### Device Identifiers
Every device has multiple identifiers:
| Identifier | Type | Description | Example |
|------------|------|-------------|---------|
| `deviceUid` | string | Globally unique identifier | `d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a` |
| `deviceId` | integer | Legacy numeric ID | `123456` |
| `hostname` | string | Computer name | `ACME-DC01` |
| `intIpAddress` | string | Internal IP address | `192.168.1.100` |
| `extIpAddress` | string | External/public IP | `203.0.113.50` |
| `macAddresses` | array | Network interface MACs | `["00:1A:2B:3C:4D:5E"]` |
### Device Types
| Type | Description | Typical Use |
|------|-------------|-------------|
| `Desktop` | Workstation/PC | End-user computers |
| `Laptop` | Portable workstation | Mobile workers |
| `Server` | Windows/Linux server | Infrastructure |
| `ESXi Host` | VMware hypervisor | Virtualization |
| `Network Device` | Router/switch/firewall | SNMP-monitored |
| `Printer` | Network printer | Print infrastructure |
### Device Status
| Status | Description | Business Impact |
|--------|-------------|-----------------|
| `online` | Agent checking in | Normal operation |
| `offline` | No agent communication | May require attention |
| `rebooting` | Restart in progress | Temporary state |
| `unknown` | Status undetermined | Check connectivity |
## Field Reference
### Core Device Fields
```typescript
interface Device {
// Identifiers
uid: string; // Unique device ID
deviceId: number; // Legacy numeric ID
hostname: string; // Computer name
description: string; // Custom description
// Site Association
siteUid: string; // Parent site UID
siteName: string; // Site display name
// Type and Status
deviceType: DeviceType; // Desktop, Laptop, Server, etc.
deviceClass: string; // device, esxihost, printer, etc.
status: DeviceStatus; // online, offline, rebooting
// Network
intIpAddress: string; // Internal IP
extIpAddress: string; // External IP
macAddresses: string[]; // MAC addresses
// Operating System
operatingSystem: string; // "Windows 11 Pro"
osType: string; // "Windows", "macOS", "Linux"
osVersion: string; // "10.0.22631"
osSerialNumber: string; // Windows product key
// Hardware
manufacturer: string; // "Dell Inc."
model: string; // "OptiPlex 7090"
serialNumber: string; // Hardware serial
// Agent Info
agentVersion: string; // "2.5.0.1234"
agentPlatform: string; // Platform agent was installed from
// Timestamps (Unix milliseconds)
lastSeen: number; // Last agent check-in
lastReboot: number; // Last system restart
createdAt: number; // When device was added
warrantyExpiry: number; // Warranty end date
// User-Defined Fields
udf1: string; // Custom field 1
udf2: string; // Custom field 2
// ... up to udf30
// Counts
openAlertCount: number; // Active alerts
patchStatus: PatchStatus; // Patch compliance
}
type DeviceType = 'Desktop' | 'Laptop' | 'Server' | 'ESXi Host' | 'Network Device' | 'Printer';
type DeviceStatus = 'online' | 'offline' | 'rebooting' | 'unknown';
```
### User-Defined Fields (UDF)
Datto RMM provides 30 custom fields per device:
| Field | Type | Max Length | Description |
|-------|------|------------|-------------|
| `udf1` - `udf30` | string | 255 chars | Custom data fields |
**Common UDF Uses:**
- `udf1`: Asset tag
- `udf2`: Department
- `udf3`: Primary user
- `udf4`: Location/floor
- `udf5`: Purchase date
- `udf6`: Lease expiration
## API Patterns
### List All Devices
```http
GET /api/v2/devices?max=250
Authorization: Bearer {token}
```
**Response:**
```json
{
"devices": [
{
"uid": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a",
"hostname": "ACME-DC01",
"siteUid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"siteName": "Acme Corporation",
"deviceType": "Server",
"status": "online",
"intIpAddress": "192.168.1.10",
"operatingSystem": "Windows Server 2022 Standard",
"lastSeen": 1707991200000,
"openAlertCount": 2
}
],
"pageDetails": {
"count": 250,
"nextPageUrl": "/api/v2/devices?max=250&page=abc123"
}
}
```
### Get Single Device
```http
GET /api/v2/device/{deviceUid}
Authorization: Bearer {token}
```
**Response:**
```json
{
"uid": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a",
"hostname": "ACME-DC01",
"description": "Primary Domain Controller",
"siteUid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"siteName": "Acme Corporation",
"deviceType": "Server",
"deviceClass": "device",
"status": "online",
"intIpAddress": "192.168.1.10",
"extIpAddress": "203.0.113.50",
"macAddresses": ["00:1A:2B:3C:4D:5E"],
"operatingSystem": "Windows Server 2022 Standard",
"osVersion": "10.0.20348",
"manufacturer": "Dell Inc.",
"model": "PowerEdge R640",
"serialNumber": "ABC1234567",
"agentVersion": "2.5.0.1234",
"lastSeen": 1707991200000,
"lastReboot": 1707800000000,
"createdAt": 1680000000000,
"warrantyExpiry": 1750000000000,
"udf1": "ASSET-00123",
"udf2": "IT Infrastructure",
"udf3": "John Admin",
"openAlertCount": 2,
"patchStatus": {
"patchesApproved": 5,
"patchesPending": 2,
"patchesFailed": 0
}
}
```
### Get Devices by Site
```http
GET /api/v2/site/{siteUid}/devices?max=250
Authorization: Bearer {token}
```
### Update Device
```http
POST /api/v2/device/{deviceUid}
Authorization: Bearer {token}
Content-Type: application/json
{
"description": "Updated description",
"udf1": "NEW-ASSET-TAG",
"udf2": "Finance Department"
}
```
### Delete Device
```http
DELETE /api/v2/device/{deviceUid}
Authorization: Bearer {token}
```
**Note:** Deleting a device removes it from Datto RMM but does not uninstall the agent.
## Workflows
### Device Lookup by Hostname
```javascript
async function findDeviceByHostname(client, hostname) {
// Fetch all devices (with pagination)
const allDevices = [];
let url = '/api/v2/devices?max=250';
while (url) {
const response = await client.request(url);
allDevices.push(...response.devices);
url = response.pageDetails?.nextPageUrl;
}
// Search case-insensitive
const matches = allDevices.filter(d =>
d.hostname.toLowerCase().includes(hostname.toLowerCase())
);
if (matches.length === 0) {
return { found: false, suggestions: [] };
}
if (matches.length === 1) {
return { found: true, device: matches[0] };
}
return {
found: false,
ambiguous: true,
suggestions: matches.map(d => ({
hostname: d.hostname,
uid: d.uid,
site: d.siteName
}))
};
}
```
### Device Lookup by IP Address
```javascript
async function findDeviceByIP(client, ipAddress) {
const allDevices = await fetchAllDevices(client);
const device = allDevices.find(d =>
d.intIpAddress === ipAddress || d.extIpAddress === ipAddress
);
return device || null;
}
```
### Device Lookup by MAC Address
```javascript
async function findDeviceByMAC(client, macAddress) {
const normalizedMAC = macAddress.toUpperCase().replace(/[:-]/g, ':');
const allDevices = await fetchAllDevices(client);
const device = allDevices.find(d =>
d.macAddresses?.some(mac =>
mac.toUpperCase().replace(/[:-]/g, ':') === normalizedMAC
)
);
return device || null;
}
```
### Offline Device Report
```javascript
async function getOfflineDevices(client, options = {}) {
const {
siteUid,
offlineThresholdMinutes = 30
} = options;
const url = siteUid
? `/api/v2/site/${siteUid}/devices?max=250`
: '/api/v2/devices?max=250';
const allDevices = await fetchAllPaginated(client, url);
const now = Date.now();
const threshold = offlineThresholdMinutes * 60 * 1000;
return allDevices.filter(device => {
if (device.status === 'offline') return true;
if (!device.lastSeen) return true;
// Check if last seen exceeds threshold
return (now - device.lastSeen) > threshold;
}).map(device => ({
hostname: device.hostname,
uid: device.uid,
site: device.siteName,
lastSeen: new Date(device.lastSeen).toISOString(),
offlineMinutes: Math.floor((now - device.lastSeen) / 60000)
}));
}
```
### Bulk UDF Update
```javascript
async function bulkUpdateUDF(client, updates) {
// updates: [{ deviceUid, udf1, udf2, ... }, ...]
const results = [];
for (const update of updates) {
try {
const { deviceUid, ...fields } = update;
await client.request(`/api/v2/device/${deviceUid}`, {
method: 'POST',
body: JSON.stringify(fields)
});
results.push({ deviceUid, success: true });
} catch (error) {
results.push({ deviceUid, success: false, error: error.message });
}
// Respect rate limits
await sleep(100);
}
return results;
}
```
## Error Handling
### Common Device API Errors
| Error | Status | Cause | Resolution |
|-------|--------|-------|------------|
| Device not found | 404 | Invalid UID | Verify device exists |
| Invalid field value | 400 | UDF too long | Max 255 characters |
| Permission denied | 403 | API key restrictions | Check API permissions |
| Device locked | 409 | Concurrent update | Retry after delay |
### Error Response Example
```json
{
"errorCode": "DEVICE_NOT_FOUND",
"message": "Device with UID 'd4e5f6a7-...' not found",
"details": {
"deviceUid": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a"
}
}
```
### Device Validation
```javascript
function validateDeviceUpdate(fields) {
const errors = [];
// Check UDF lengths
for (let i = 1; i <= 30; i++) {
const field = `udf${i}`;
if (fields[field] && fields[field].length > 255) {
errors.push(`${field} exceeds 255 character limit`);
}
}
// Validate description
if (fields.description && fields.description.length > 1000) {
errors.push('Description exceeds 1000 character limit');
}
return {
valid: errors.length === 0,
errors
};
}
```
## Best Practices
1. **Use UID not hostname for lookups** - UIDs are guaranteed unique
2. **Cache device lists** - Full device list changes infrequently
3. **Use site-scoped queries** - Reduce data transfer when possible
4. **Monitor offline devices** - Set up alerts for extended offline status
5. **Standardize UDF usage** - Document which UDFs are used for what
6. **Handle pagination** - Always process `nextPageUrl`
7. **Normalize MAC addresses** - Handle different formats (colons, dashes, none)
8. **Check lastSeen vs status** - Status may lag behind actual connectivity
9. **Track agent versions** - Plan upgrades based on version distribution
10. **Document warranty info** - Use UDFs for hardware lifecycle management
## Device Status Business Logic
### Determining True Online Status
```javascript
function getDeviceEffectiveStatus(device) {
const now = Date.now();
const lastSeenMinutesAgo = (now - device.lastSeen) / 60000;
if (device.status === 'online' && lastSeenMinutesAgo < 15) {
return 'online';
}
if (device.status === 'rebooting') {
return 'rebooting';
}
if (lastSeenMinutesAgo > 60) {
return 'offline';
}
if (lastSeenMinutesAgo > 30) {
return 'stale';
}
return device.status;
}
```
### Device Health Summary
```javascript
function getDeviceHealthSummary(device) {
const issues = [];
// Check online status
if (device.status !== 'online') {
issues.push({ severity: 'warning', message: `Device is ${device.status}` });
}
// Check open alerts
if (device.openAlertCount > 0) {
const severity = device.openAlertCount > 5 ? 'critical' : 'warning';
issues.push({
severity,
message: `${device.openAlertCount} open alert(s)`
});
}
// Check patch status
if (device.patchStatus?.patchesFailed > 0) {
issues.push({
severity: 'warning',
message: `${device.patchStatus.patchesFailed} failed patch(es)`
});
}
// Check warranty
if (device.warrantyExpiry && device.warrantyExpiry < Date.now()) {
issues.push({
severity: 'info',
message: 'Warranty expired'
});
}
return {
healthy: issues.length === 0,
issues
};
}
```
## Related Skills
- [Datto RMM Alerts](../alerts/SKILL.md) - Device alert management
- [Datto RMM Audit](../audit/SKILL.md) - Device hardware/software inventory
- [Datto RMM Jobs](../jobs/SKILL.md) - Running jobs on devices
- [Datto RMM Sites](../sites/SKILL.md) - Site-level device management
- [Datto RMM API Patterns](../api-patterns/SKILL.md) - Authentication and pagination