6.1 KiB
name, description
| name | description |
|---|---|
| msp360 | Manage ACG's MSP360 Managed Backup Service (MBS) tenant via the provider REST API: the authoritative fleet backup-status source (who is backing up, last run, failures, stale plans) plus user/company/license provisioning. Reads run freely; writes (create/delete user or company, grant/release/revoke license) are gated --confirm. Triggers: msp360, mspbackups, managed backup, is X backing up, backup status, backup failures, create backup user, add backup company, grant backup license. |
MSP360 Managed Backup Service Skill
Live client for ACG's MSP360 Managed Backup Service (MBS) provider tenant. This is the authoritative answer to "is client X actually backing up" — the monitoring feed reports every backup plan's last run, status, and data across the whole fleet. B2/Seafile/ownCloud are just where the data lands; MSP360 is where you see whether a backup ran.
Built as a sibling to the b2 / seafile / owncloud / datto-workplace backup skills;
shares .claude/scripts/backup_common.py for repo-root/vault/HTTP plumbing.
Running
MSP=".claude/skills/msp360/scripts/msp360.py"
# --- reads (free) ---
py "$MSP" status # reachable + counts + plans needing attention
py "$MSP" monitoring # every plan: company/computer/status/last-run/data
py "$MSP" monitoring --failed # only plans NOT in a clean state (the triage view)
py "$MSP" monitoring --company Dataforth # scope to one client
py "$MSP" monitoring --stale 30 # plans whose last run is >=30 days old (or never)
py "$MSP" companies # 37 companies with ids + storage limits
py "$MSP" users --company "Business Services" # backup users (+ space used) in a company
py "$MSP" licenses --available # free vs taken licenses
py "$MSP" billing --json # billing feed
py "$MSP" raw GET /api/Users/{id} # generic passthrough for any GET endpoint
# --- writes (require --confirm; without it you get a dry-run preview) ---
py "$MSP" create-company --name "New Client LLC" --confirm
py "$MSP" create-user --email backup@client.com --company "New Client LLC" \
--first Jane --last Doe --notify admin@acg.com --confirm
py "$MSP" grant-license --user-id <UUID> --license-id <UUID> --confirm
py "$MSP" release-license --user-id <UUID> --confirm
py "$MSP" delete-user --id <UUID> [--keep-data] --confirm
py "$MSP" delete-company --id <UUID> --confirm
py "$MSP" raw POST /api/Accounts/CreateDestination --data '{...}' --confirm
Add --json to any read for machine-readable output. --base overrides the API URL.
Credentials
Loaded at runtime from the SOPS vault (never hardcoded):
msp-tools/msp360-api.sops.yaml -> credentials.login / credentials.password.
These are the API-specific creds
generated in the MSP360 console (Settings > General) by the main admin account — NOT the
console login. Auth flow: POST /api/Provider/Login {UserName, Password} -> Bearer
access_token (per-run, never cached to disk) -> Authorization: Bearer <token> on every
request. Base: https://api.mspbackups.com.
What "backing up?" looks like
monitoring returns one row per backup plan with Status (0/1=Success, 2=Warning,
3=Failed, 4=Running, 6=Interrupted, 7=Completed-with-warnings), LastStart, DataCopied,
CompanyName, ComputerName, PlanName. Key reads:
- A company with 0 rows in
monitoringis not backing up even if it exists (this is how the GPS audit found Arizona Medical Transit + T&C Sorensen billed-but-unprotected). --failedsurfaces failing/warning plans;--stale Nsurfaces plans that stopped running.- A B2 bucket with files does NOT prove a recent backup — always confirm with
monitoring.
Writes & safety
- Every write is gated
--confirm. Without it the command prints a[DRY-RUN]line (and, for create-*, the exact JSON payload) and changes nothing. delete-userdefaults to removing metadata and all backup data; pass--keep-datato drop only the metadata (DELETE /api/Users/{id}/Account) and retain the backups.delete-company/delete-userprint a[WARNING]describing the blast radius first.- create-user / grant-license payloads are built from the live API schema (User fields: Email/FirstName/LastName/Company/Enabled/NotificationEmails; grant: UserID + LicenseID). On first real provisioning, eyeball the API's response — it returns the created object or a validation error, which the command prints verbatim.
Full endpoint surface (via raw when a typed command doesn't exist)
The MBS API groups (all reachable through raw <METHOD> <path>): Provider (login),
Users (GET/POST/PUT, DELETE /{id} or /{id}/Account), Companies (GET/POST/PUT/DELETE),
Monitoring (GET), Licenses (GET, POST Grant/Release/Revoke), Destinations
(GET/POST/PUT/DELETE), Accounts (GET/POST/PUT + Add/Create/Edit/RemoveDestination),
Packages (GET/POST/PUT/DELETE), Billing (GET/PUT), Builds (GET, POST
RequestCustomBuilds), Administrators (GET/POST/PUT/DELETE). Reference:
https://help.mspbackups.com/mbs-api-specification/methods.
Notes / gotchas
/api/Computersreturns HTTP 400 "Remote Management API methods are not enabled" — that feature is off on this account.computersprints a clean [INFO] and points you atusers+monitoring, which cover endpoint/backup data without it.- Git-Bash path mangling: a leading-slash
rawpath like/api/Usersgets rewritten toC:/Program Files/Git/api/Usersby MSYS. Therawcommand auto-recovers the/api/...tail, so pass the path normally. - MSP360 CompanyName is the join key to B2 buckets (e.g.
ACG-PST=Peaceful Spirit,ACG-TCA=Tucson Coin and Autograph) — useful when reconciling destinations. - Backup targets are a per-client decision: report mismatches, don't provision jobs off a
billing count. See memory
feedback_backup_targets_never_guessed+reference_msp360_backup_monitoring. - Failures are logged to the fleet
errorlog.mdvia the canonical helper; expected conditions (feature-gated endpoint, no matching rows) are not.