Source profileQuality 94/100

WYRE-AI/msp-claude-plugins/msp-claude-plugins/kaseya/datto-rmm/skills/api-patterns/SKILL.md

Datto RMM API Patterns

Datto RMM REST API v2 fundamentals: OAuth 2.0 client-credentials-style authentication, the 6 regional platforms (Pinotage, Merlot, Concord, Vidal, Zinfandel, Syrah), token lifecycle, cursor-based pagination, rate limiting, Unix-millisecond timestamps, and error handling.

Source repository stars
42
Declared platforms
1
Static risk flags
1
Last source update
2026-08-28
Source checked
2026-08-28

Decision brief

What it does: where it fits

Datto RMM REST API v2 fundamentals: OAuth 2. 0 client-credentials-style authentication, the 6 regional platforms (Pinotage, Merlot, Concord, Vidal, Zinfandel, Syrah), token lifecycle, cursor-based pagination, rate limiting, Unix-millisecond timestamps, and error handling.

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorDeclaredSource recordInstall path and trigger
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/WYRE-AI/msp-claude-plugins --skill "msp-claude-plugins/kaseya/datto-rmm/skills/api-patterns"
    Safe inspection promptEditorial

    Inspect the Agent Skill "Datto RMM API Patterns" from https://github.com/WYRE-AI/msp-claude-plugins/blob/5005f73ba2f52cd299f58aa6bb79f4e70ae87103/msp-claude-plugins/kaseya/datto-rmm/skills/api-patterns/SKILL.md at commit 5005f73ba2f52cd299f58aa6bb79f4e70ae87103. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      Anti-triggers

      Kaseya's other RMM — VSA authenticates with a two-step token

      Kaseya's other RMM — VSA authenticates with a two-step tokenDatto's backup APIs — BCDR signs requests with HMAC-SHA256 and- Kaseya's other RMM — VSA authenticates with a two-step token exchange against a per-tenant host, not OAuth against a regional platform; use kaseya-vsa-api-patterns. - Datto's backup APIs — BCDR signs requests with HMA…
    2. 02

      Key Concepts

      Datto RMM operates across 6 regional platforms. You must use the correct base URL for your account:

      Token Expiry: 100 hours (approximately 4 days)Refresh Strategy: Request new token before expiryStorage: Cache token securely, reuse until near expiry
    3. 03

      Platforms

      Datto RMM operates across 6 regional platforms. You must use the correct base URL for your account:

      Datto RMM operates across 6 regional platforms. You must use the correct base URL for your account:
    4. 04

      Authentication Flow

      Datto RMM uses OAuth 2.0 client credentials flow:

      Datto RMM uses OAuth 2.0 client credentials flow:
    5. 05

      Token Lifecycle

      Token Expiry: 100 hours (approximately 4 days)

      Token Expiry: 100 hours (approximately 4 days)Refresh Strategy: Request new token before expiryStorage: Cache token securely, reuse until near expiry

    Permission review

    Static risk signals and limitations

    Network access

    medium · line 61

    The documentation includes network, browsing, or remote request actions.

    POST https://{platform}-api.centrastage.net/auth/oauth/token

    Network access

    medium · line 99

    The documentation includes network, browsing, or remote request actions.

    `https://${platform}-api.centrastage.net/auth/oauth/token`,

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score94/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars42SourceRepository attention, not individual Skill quality
    Compatibility1 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    WYRE-AI/msp-claude-plugins
    Skill path
    msp-claude-plugins/kaseya/datto-rmm/skills/api-patterns/SKILL.md
    Commit
    5005f73ba2f52cd299f58aa6bb79f4e70ae87103
    License
    Apache-2.0
    Collected
    2026-08-28
    Default branch
    main
    View the original SKILL.md

    Datto RMM API Patterns

    Overview

    The Datto RMM REST API v2 provides programmatic access to device management, alerts, sites, jobs, and audit data. This skill covers authentication, platform selection, pagination, error handling, and performance optimization patterns.

    Anti-triggers

    • Kaseya's other RMM — VSA authenticates with a two-step token exchange against a per-tenant host, not OAuth against a regional platform; use kaseya-vsa-api-patterns.
    • Datto's backup APIs — BCDR signs requests with HMAC-SHA256 and shares no credentials with RMM; use datto-bcdr-api-patterns.

    Key Concepts

    Platforms

    Datto RMM operates across 6 regional platforms. You must use the correct base URL for your account:

    PlatformRegionAPI Base URL
    pinotageUS/Canadahttps://pinotage-api.centrastage.net
    merlotUS/Canadahttps://merlot-api.centrastage.net
    concordEUhttps://concord-api.centrastage.net
    vidalEUhttps://vidal-api.centrastage.net
    zinfandelAPAChttps://zinfandel-api.centrastage.net
    syrahUKhttps://syrah-api.centrastage.net

    Authentication Flow

    Datto RMM uses OAuth 2.0 client credentials flow:

    ┌─────────────┐     1. POST /auth/oauth/token     ┌─────────────────┐
    │   Client    │ ──────────────────────────────>   │  Datto RMM API  │
    │             │     (API Key + Secret)            │                 │
    │             │ <────────────────────────────────  │                 │
    └─────────────┘     2. Access Token (100h TTL)    └─────────────────┘
           │
           │  3. API Request with Bearer Token
           ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │  GET /api/v2/devices                                            │
    │  Authorization: Bearer <access_token>                           │
    └─────────────────────────────────────────────────────────────────┘
    

    Token Lifecycle

    • Token Expiry: 100 hours (approximately 4 days)
    • Refresh Strategy: Request new token before expiry
    • Storage: Cache token securely, reuse until near expiry

    Field Reference

    OAuth Token Request

    POST https://{platform}-api.centrastage.net/auth/oauth/token
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=password&username={API_KEY}&password={API_SECRET}
    

    Response:

    {
      "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
      "token_type": "bearer",
      "expires_in": 360000
    }
    

    API Request Headers

    HeaderValueDescription
    AuthorizationBearer {token}OAuth 2.0 access token
    Content-Typeapplication/jsonRequired for POST/PUT/PATCH
    Acceptapplication/jsonResponse format

    Environment Variables

    export DATTO_API_KEY="your-api-key"
    export DATTO_API_SECRET="your-api-secret"
    export DATTO_PLATFORM="merlot"  # pinotage, merlot, concord, vidal, zinfandel, syrah
    

    API Patterns

    Token Acquisition

    async function getAccessToken(platform, apiKey, apiSecret) {
      const response = await fetch(
        `https://${platform}-api.centrastage.net/auth/oauth/token`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
          },
          body: new URLSearchParams({
            grant_type: 'password',
            username: apiKey,
            password: apiSecret
          })
        }
      );
    
      if (!response.ok) {
        throw new Error(`Authentication failed: ${response.status}`);
      }
    
      const data = await response.json();
      return {
        token: data.access_token,
        expiresAt: Date.now() + (data.expires_in * 1000)
      };
    }
    

    Pagination

    Datto RMM uses cursor-based pagination with nextPageUrl:

    Request:

    GET /api/v2/devices?max=250
    Authorization: Bearer {token}
    

    Response:

    {
      "devices": [...],
      "pageDetails": {
        "count": 250,
        "nextPageUrl": "/api/v2/devices?max=250&page=xyz123",
        "prevPageUrl": null
      }
    }
    

    Pagination Constants:

    ParameterMax ValueDefault
    max25050

    Efficient Pagination Pattern:

    async function fetchAllDevices(token, platform) {
      const allDevices = [];
      let url = `/api/v2/devices?max=250`;
    
      while (url) {
        const response = await fetch(
          `https://${platform}-api.centrastage.net${url}`,
          {
            headers: { Authorization: `Bearer ${token}` }
          }
        );
    
        const data = await response.json();
        allDevices.push(...data.devices);
    
        // Get next page URL from response
        url = data.pageDetails?.nextPageUrl || null;
      }
    
      return allDevices;
    }
    

    Rate Limiting

    Datto RMM enforces strict rate limits:

    Limit TypeThresholdConsequence
    Requests per minute600HTTP 429
    Sustained high volume-IP blocking (1 hour)

    Rate Limit Headers:

    HeaderDescription
    X-RateLimit-LimitMax requests per window
    X-RateLimit-RemainingRemaining requests
    X-RateLimit-ResetSeconds until reset

    Retry Strategy:

    async function requestWithRetry(url, options, maxRetries = 5) {
      for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
          const response = await fetch(url, options);
    
          if (response.status === 429) {
            const retryAfter = response.headers.get('Retry-After') || 60;
            console.log(`Rate limited. Waiting ${retryAfter}s...`);
            await sleep(retryAfter * 1000);
            continue;
          }
    
          return response;
        } catch (error) {
          if (attempt === maxRetries - 1) throw error;
    
          // Exponential backoff with jitter
          const delay = Math.pow(2, attempt) * 1000 + Math.random() * 1000;
          await sleep(delay);
        }
      }
    }
    

    Timestamp Handling

    Datto RMM uses Unix milliseconds for all timestamps:

    // Convert ISO date to Datto timestamp
    const dattoTimestamp = new Date('2024-02-15T10:00:00Z').getTime();
    // Result: 1707991200000
    
    // Convert Datto timestamp to Date
    const jsDate = new Date(1707991200000);
    // Result: 2024-02-15T10:00:00.000Z
    
    // Calculate timestamp for "last 24 hours"
    const oneDayAgo = Date.now() - (24 * 60 * 60 * 1000);
    

    Timestamp Query Example:

    GET /api/v2/alerts/open?since=1707991200000
    

    Workflows

    See references/examples.md for a complete DattoRMMClient class that ties together token caching, retry, and requests.

    Site-Scoped Queries

    Many endpoints support site-level filtering:

    # Get devices for a specific site
    GET /api/v2/site/{siteUid}/devices
    
    # Get alerts for a specific site
    GET /api/v2/site/{siteUid}/alerts/open
    
    # Get resolved alerts for a site
    GET /api/v2/site/{siteUid}/alerts/resolved
    

    Error Handling

    HTTP Status Codes

    CodeMeaningAction
    200SuccessProcess response
    201CreatedEntity created successfully
    400Bad RequestCheck request format/parameters
    401UnauthorizedRefresh token and retry
    403ForbiddenCheck API permissions
    404Not FoundEntity doesn't exist
    429Rate LimitedWait and retry with backoff
    500Server ErrorRetry with backoff

    Error Response Format

    {
      "errorCode": "INVALID_PARAMETER",
      "message": "The device UID is not valid",
      "details": {
        "field": "deviceUid",
        "value": "invalid-uid"
      }
    }
    

    See references/errors.md for the full DattoAPIError class and status-code-to-message mapping pattern.

    Best Practices

    1. Cache tokens - Reuse tokens until near expiry (100 hours)
    2. Use correct platform - Verify your account's platform before making requests
    3. Respect rate limits - Stay under 600 req/min to avoid IP blocking
    4. Use pagination - Always handle nextPageUrl for large result sets
    5. Handle timestamps - Datto uses Unix milliseconds, not seconds
    6. Implement retry logic - Use exponential backoff for transient errors
    7. Cache reference data - Sites and account info change infrequently
    8. Scope queries to sites - Use site-level endpoints when possible
    9. Monitor rate limit headers - Track remaining requests proactively

    Common Query Patterns

    Filter by Time Range

    // Alerts in last 24 hours
    const since = Date.now() - (24 * 60 * 60 * 1000);
    const url = `/api/v2/alerts/open?since=${since}`;
    

    Device Lookups

    // By hostname (requires fetching all and filtering)
    const devices = await client.getDevices();
    const device = devices.find(d =>
      d.hostname.toLowerCase() === hostname.toLowerCase()
    );
    
    // By UID (direct lookup)
    const device = await client.getDevice(deviceUid);
    

    Batch processing with rate-limit-friendly delays is shown in references/examples.md.

    Related Skills

    Frequently asked questions

    What to verify before installation and use

    What does the Datto RMM API Patterns source document cover?

    Datto RMM REST API v2 fundamentals: OAuth 2. 0 client-credentials-style authentication, the 6 regional platforms (Pinotage, Merlot, Concord, Vidal, Zinfandel, Syrah), token lifecycle, cursor-based pagination, rate limiting, Unix-millisecond timestamps, and error handling.

    How do I install Datto RMM API Patterns?

    The source record exposes this install command: npx skills add https://github.com/WYRE-AI/msp-claude-plugins --skill "msp-claude-plugins/kaseya/datto-rmm/skills/api-patterns". Inspect the command and pinned source before running it.

    Which Agent platforms does the source record declare?

    The pinned source record declares support for: cursor.

    Which permission-related actions were detected?

    Static rules flagged network in the source; the page lists the matching lines and excerpts.

    Alternatives

    Compare before choosing