# Cove Data Protection (N-able Backup) – Known Information on API Calls Date: 2026-02-10 Status: Research phase (validated with live testing) ## Summary of current findings API access to Cove Data Protection via JSON-RPC **works**, but is **heavily restricted per tenant and per API user scope**. The API is usable for monitoring, but only with a **very limited, allow‑listed set of column codes**. Any request that includes a restricted column immediately fails with: ``` Operation failed because of security reasons (error 13501) ``` This behavior is consistent even when the API user has **SuperUser** and **SecurityOfficer** roles. --- ## Authentication model (confirmed) - Endpoint: https://api.backup.management/jsonapi - Protocol: JSON‑RPC 2.0 - Method: POST only - Authentication flow: 1. Login method is called 2. Response returns a **visa** token (top‑level field) 3. The visa **must be included in every subsequent call** 4. Cove may return a new visa in later responses (token chaining) ### Login request (working) ```json { "jsonrpc": "2.0", "method": "Login", "params": { "partner": "", "username": "", "password": "" }, "id": "1" } ``` ### Login response structure (important) ```json { "result": { "result": { "PartnerId": , "Name": "", "Flags": ["SecurityOfficer","NonInteractive"] } }, "visa": "" } ``` Notes: - `visa` is **not** inside `result`, but at top level - `PartnerId` is found at `result.result.PartnerId` --- ## API user scope (critical finding) - API users are **always bound to a single Partner (customer)** unless created at MSP/root level - In this environment, it is **not possible to create an MSP‑level API user** - All testing was therefore done with **customer‑scoped API users** Impact: - Cross‑customer enumeration is impossible - Only data belonging to the linked customer can be queried - Some enumerate/reporting calls are blocked regardless of role --- ## EnumerateAccountStatistics – what works and what does not ### Method ```json { "jsonrpc": "2.0", "method": "EnumerateAccountStatistics", "visa": "", "params": { "query": { "PartnerId": , "SelectionMode": "Merged", "StartRecordNumber": 0, "RecordsCount": 50, "Columns": [ ... ] } } } ``` ### Mandatory behavior - **Columns are required**; omitting them returns `result: null` - The API behaves as an **allow‑list**: - If *any* requested column is restricted, the **entire call fails** with error 13501 ### Confirmed working (safe) column set The following column set works reliably: - I1 → account / device / tenant identifier - I14 → used storage (bytes) - I18 → computer name (if applicable) - D01F00 – D01F07 → numeric metrics (exact semantics TBD) - D09F00 → numeric status/category code Example (validated working): ```json "Columns": [ "I1","I14","I18", "D01F00","D01F01","D01F02","D01F03", "D01F04","D01F05","D01F06","D01F07", "D09F00" ] ``` ### Confirmed restricted (cause security error 13501) - Entire D02Fxx range - Entire D03Fxx range - Broad I‑ranges (e.g. I1–I10 batches) - Many individually tested I‑codes not in the safe set Even adding **one restricted code** causes the entire call to fail. --- ## EnumerateAccounts - Method consistently fails with `Operation failed because of security reasons` - This applies even with: - SuperUser role - SecurityOfficer flag enabled Conclusion: - EnumerateAccounts is **not usable** in this tenant for customer‑scoped API users --- ## Other tested methods - EnumerateStatistics → Method not found - GetPartnerInfo → works only for basic partner metadata (not statistics) --- ## Practical implications for BackupChecks What **is possible**: - Enumerate accounts implicitly via EnumerateAccountStatistics - Identify devices/accounts via AccountId + I1/I18 - Collect storage usage (I14) - Collect numeric status/metrics via D01Fxx and D09F00 What is **not possible (via this API scope)**: - Reliable last backup timestamp - Explicit success / failure / warning text - Error messages - Enumerating devices via EnumerateAccounts - Cross‑customer aggregation ### Suggested internal model mapping - Customer - external_id = PartnerId - Job - external_id = AccountId - display_name = I1 - hostname = I18 (if present) - Run (limited) - metrics only (bytes, counters) - status must be **derived heuristically** from numeric fields (if possible) --- ## Open questions / next steps 1. Confirm official meaning of: - D01F00 – D01F07 - D09F00 2. Investigate whether: - A token‑based (non‑JSON‑RPC) reporting endpoint exists - N‑able support can enable additional reporting columns - An MSP‑level API user can be provisioned by N‑able 3. Decide whether Cove integration in BackupChecks will be: - Metrics‑only (no run result semantics) - Or require vendor cooperation for expanded API access