Datto RMM Variables
Overview
Variables in Datto RMM store key-value configuration data at account or site level. They're used to customize component scripts, store configuration values, and maintain environment-specific settings. This skill covers variable management, scoping, and usage patterns.
Key Concepts
Variable Scopes
| Scope | Description | Use Case |
|---|---|---|
| Account | Available to all sites | Global configuration |
| Site | Available to specific site | Client-specific settings |
Variable Inheritance
Account Variables (Global)
│
▼ (inherited by)
Site Variables
│
▼ (used in)
Jobs/Components
Site variables can override account variables with the same name.
Variable Types
All variables are stored as strings but can represent:
- Configuration paths
- Credentials (use secure alternatives when possible)
- Feature flags
- Threshold values
- Client-specific data
Field Reference
Variable Object
interface Variable {
id: number; // Variable ID
name: string; // Variable name
value: string; // Variable value
description?: string; // Optional description
scope: VariableScope; // "account" or "site"
siteUid?: string; // Site UID (for site variables)
createdAt: number; // Creation timestamp
modifiedAt: number; // Last modification
}
type VariableScope = 'account' | 'site';
Naming Conventions
Recommended Format: SCREAMING_SNAKE_CASE
Examples:
BACKUP_PATHADMIN_EMAILLOG_RETENTION_DAYSANTIVIRUS_SCAN_SCHEDULE
Reserved Prefixes:
CS_- Datto internal useDATTO_- System variables
API Patterns
List Account Variables
GET /api/v2/account/variables
Authorization: Bearer {token}
Response:
{
"variables": [
{
"id": 1,
"name": "BACKUP_PATH",
"value": "D:\\Backups",
"description": "Default backup destination",
"scope": "account",
"createdAt": 1680000000000,
"modifiedAt": 1707991200000
},
{
"id": 2,
"name": "ADMIN_EMAIL",
"value": "alerts@msp.com",
"scope": "account"
}
]
}
List Site Variables
GET /api/v2/site/{siteUid}/variables
Authorization: Bearer {token}
Response:
{
"variables": [
{
"id": 101,
"name": "BACKUP_PATH",
"value": "E:\\ClientBackups",
"description": "Client-specific backup path",
"scope": "site",
"siteUid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
},
{
"id": 102,
"name": "CLIENT_CODE",
"value": "ACME",
"scope": "site",
"siteUid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
]
}
Create Account Variable
POST /api/v2/account/variables
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "NEW_VARIABLE",
"value": "variable_value",
"description": "Description of the variable"
}
Create Site Variable
POST /api/v2/site/{siteUid}/variables
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "SITE_SPECIFIC_VAR",
"value": "site_value",
"description": "Site-specific configuration"
}
Update Variable
PUT /api/v2/account/variable/{variableId}
Authorization: Bearer {token}
Content-Type: application/json
{
"value": "updated_value",
"description": "Updated description"
}
For site variables:
PUT /api/v2/site/{siteUid}/variable/{variableId}
Delete Variable
DELETE /api/v2/account/variable/{variableId}
Authorization: Bearer {token}
For site variables:
DELETE /api/v2/site/{siteUid}/variable/{variableId}
Workflows
Get Effective Variable Value
Account variables can be overridden by site variables:
async function getEffectiveVariable(client, siteUid, variableName) {
// Try site variable first
const siteVars = await client.request(`/api/v2/site/${siteUid}/variables`);
const siteVar = siteVars.variables?.find(v => v.name === variableName);
if (siteVar) {
return {
name: variableName,
value: siteVar.value,
scope: 'site',
source: `Site: ${siteUid}`
};
}
// Fall back to account variable
const accountVars = await client.request('/api/v2/account/variables');
const accountVar = accountVars.variables?.find(v => v.name === variableName);
if (accountVar) {
return {
name: variableName,
value: accountVar.value,
scope: 'account',
source: 'Account'
};
}
return {
name: variableName,
value: null,
error: 'Variable not found'
};
}
Bulk Variable Setup
async function setupSiteVariables(client, siteUid, variables) {
const results = [];
for (const [name, value] of Object.entries(variables)) {
try {
await client.request(`/api/v2/site/${siteUid}/variables`, {
method: 'POST',
body: JSON.stringify({
name,
value,
description: `Auto-created: ${new Date().toISOString()}`
})
});
results.push({ name, success: true });
} catch (error) {
results.push({ name, success: false, error: error.message });
}
await sleep(100);
}
return results;
}
Variable Audit Report
async function auditVariables(client, siteUids) {
const report = {
account: [],
sites: {}
};
// Get account variables
const accountVars = await client.request('/api/v2/account/variables');
report.account = accountVars.variables || [];
// Get site variables
for (const siteUid of siteUids) {
try {
const siteVars = await client.request(`/api/v2/site/${siteUid}/variables`);
report.sites[siteUid] = siteVars.variables || [];
} catch (error) {
report.sites[siteUid] = { error: error.message };
}
await sleep(100);
}
return report;
}
Find Variable Usage
async function findVariableOverrides(client, variableName) {
const accountVars = await client.request('/api/v2/account/variables');
const accountVar = accountVars.variables?.find(v => v.name === variableName);
const sitesResponse = await client.request('/api/v2/sites?max=250');
const sites = sitesResponse.sites || [];
const overrides = [];
for (const site of sites) {
try {
const siteVars = await client.request(`/api/v2/site/${site.uid}/variables`);
const siteVar = siteVars.variables?.find(v => v.name === variableName);
if (siteVar) {
overrides.push({
siteName: site.name,
siteUid: site.uid,
value: siteVar.value,
isOverride: accountVar ? true : false
});
}
} catch (error) {
// Skip sites with errors
}
await sleep(100);
}
return {
variableName,
accountValue: accountVar?.value || null,
overrides,
overrideCount: overrides.length
};
}
Variable Template Application
async function applyVariableTemplate(client, siteUid, template) {
/*
* Template format:
* {
* "BACKUP_PATH": "D:\\Backups\\{SITE_NAME}",
* "LOG_RETENTION_DAYS": "30",
* "ADMIN_EMAIL": "{inherit}"
* }
*/
const site = await client.request(`/api/v2/site/${siteUid}`);
const results = [];
for (const [name, valueTemplate] of Object.entries(template)) {
// Skip inherited variables
if (valueTemplate === '{inherit}') {
results.push({ name, action: 'inherited' });
continue;
}
// Replace placeholders
const value = valueTemplate
.replace('{SITE_NAME}', site.name)
.replace('{SITE_UID}', siteUid);
try {
await client.request(`/api/v2/site/${siteUid}/variables`, {
method: 'POST',
body: JSON.stringify({ name, value })
});
results.push({ name, action: 'created',