Skip to content
Back to skills

Api Patterns

ASecurity

Spanning Cloud Backup REST API fundamentals: admin-email + API-token auth, the per-platform endpoint surface (M365, Google Workspace, Salesforce), the user/license model, backup status queries, and restore operations.

  • 48 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 2, 2026
ai-agentsgonodeapi

Works with

  • cursor
  • api
  • mcp

Security analysis

A100/100

Scanned October 2, 2026

npx -y skills add wyre-technology/msp-claude-plugins --skill api-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Api Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Api Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/wyre-technology-api-patterns-2602ea04/badge)](https://www.skillsdirectory.com/skills/wyre-technology-api-patterns-2602ea04)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "Spanning API Patterns"
description: >
  Spanning Cloud Backup REST API fundamentals: admin-email + API-token auth,
  the per-platform endpoint surface (M365, Google Workspace, Salesforce),
  the user/license model, backup status queries, and restore operations.
when_to_use: >-
  When working with the Spanning Cloud Backup REST API. Use when: spanning, spanning backup,
  spanning api, saas backup spanning, or cloud backup.
---

# Spanning API Patterns

## Status note

The MCP server (`spanning-mcp`) and SDK (`@wyre-technology/node-spanning`) are in development.

## Overview

Spanning Cloud Backup provides daily SaaS backup for Microsoft 365, Google Workspace, and Salesforce. Each platform has its own REST API surface but a shared auth model.

Base URLs:

```
https://o365-api.spanningbackup.com/external/   (Microsoft 365)
https://api.spanningbackup.com/external/        (Google Workspace)
https://salesforce-api.spanningbackup.com/      (Salesforce)
```

The MCP server takes a `platform` credential field (`m365` | `gws` | `salesforce`) plus the appropriate region if applicable.

## Anti-triggers

- **Datto SaaS Protection** — Kaseya's other cloud-to-cloud backup
  product, covering the same Microsoft 365 and Google Workspace
  workloads under separate credentials and a separate API; use
  `datto-saas-protection-api-patterns`.
- **Appliance-based backup** — SIRIS/Alto and Unitrends protect servers
  and images, not SaaS tenants; use `datto-bcdr-api-patterns` or
  `unitrends-api-patterns`.

## Authentication

Spanning uses **HTTP Basic auth** per the public OpenAPI spec
(<http://o365-docs.spanningbackup.com/swagger/json>):

```
Authorization: Basic base64(<admin_email>:<api_token>)
```

The admin email and API token are pair-bound — both must match the
pair on file in the Spanning admin console or the API returns 401.

Token issuance:

1. Spanning admin console → Settings → API Token
2. Copy token (shown once)
3. Tokens are tenant-scoped — one per Spanning org

## Object model

```
Org (a Spanning customer)
 └── User (a backed-up M365 / GWS / Salesforce user)
      └── Backup runs (one per day per service per user)
           └── Restorable items (mail / drive / calendar / records)
```

## Common endpoints (M365 example)

| Domain | Endpoint | Notes |
|--------|----------|-------|
| Users | `GET /external/users` | All users in the org |
| Single user | `GET /external/users/{userId}` | License + backup state |
| User services | `GET /external/users/{userId}/services` | Mail, OneDrive, etc. |
| Backup runs | `GET /external/users/{userId}/services/{service}/backups` | |
| Restore (queue) | `POST /external/users/{userId}/services/{service}/restores` | |
| Restore status | `GET /external/restores/{restoreId}` | |
| Audit log | `GET /external/audit` | Date-ranged |
| License usage | `GET /external/license` | Seats used vs purchased |

Google Workspace and Salesforce surfaces mirror this with platform-appropriate substitutions.

## Pagination

Cursor-based:

```
GET /external/users?limit=100
→ { items: [...], next: "<cursor>" }

GET /external/users?limit=100&cursor=<cursor>
```

Default `limit` 50, max 200.

## Restore operations

Async, similar pattern to Datto SaaS Protection:

```
1. POST /external/users/{userId}/services/{service}/restores
   body: { items: [...], restoreDestination: "..." }
   → { restoreId, status: "queued" }
2. Poll GET /external/restores/{restoreId} every 30s
3. status: queued → running → completed | failed
```

## Rate limits

**100 req/min per token**. HTTP 429 includes `Retry-After`. Long-running list operations (e.g. iterating audit logs across 90 days) should chunk by date and serialize.

## Error handling

| HTTP | Meaning | Action |
|------|---------|--------|
| 200 | OK | |
| 400 | Bad request | Validate |
| 401 | Bad / expired token, or admin email mismatch | Re-issue |
| 403 | Token lacks scope | Verify role |
| 404 | Unknown user / backup / restore | |
| 409 | Conflicting restore in flight | Surface to user |
| 429 | Rate limited | Back off |
| 500-503 | Transient | Exponential backoff |

## Gotchas

- **Admin email + token must match**: The token is bound to the admin email. If either is wrong, the API returns 401 with a generic message — surface a clear "verify both fields" error.
- **Platform-specific URL bases**: A token that works for M365 won't work against the GWS endpoint. Cross-platform org reporting requires separate tokens (or one platform-agnostic token at the partner level for partner-tier customers).
- **Spanning vs Datto SaaS Protection**: Despite shared Kaseya branding, these are different products. Don't mix tokens.
- **Salesforce API quirks**: The Salesforce surface uses Salesforce object IDs (15- or 18-character) rather than the user-friendly identifiers used by M365/GWS endpoints.

## Related skills

When the build-out lands, expect domain skills for: users, backups, restores, audit, license.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…