Descanto Docs
API Reference

Snapshots

List a desktop's Generation history and restore an earlier one.

Every hibernate confirm records a Generation -- a point-in-time snapshot of a desktop's disk (and, for a full snapshot, its memory) -- in that desktop's History. See Concepts: Snapshots and restore for retention buckets, branch semantics, and how this differs from forking.

List generations

GET /v1/desktops/{id}/generations

ParamInRequiredDescription
idpathyesDesktop id
curl -sS "$BASE/desktops/$DESKTOP_ID/generations" -H "$AUTH"
{
  "generations": [
    {
      "id": "gen_...",
      "kind": "full",
      "createdAt": "2026-08-20T12:00:00Z",
      "retentionBucket": "recent",
      "current": true,
      "tombstonedAt": null
    }
  ]
}

Newest first. Only still-restorable Generations are listed -- deleted ones, and ones whose bundle is currently being garbage-collected, are omitted. A hibernating snapshot in flight has no entry yet; rows are recorded at Hibernate confirm.

FieldTypeDescription
idstring
kindstring"full" (disk + memory) or "disk_only".
createdAtstringRFC 3339.
retentionBucketstring"recent" (< 1h old), "hourly" (< 24h), or "daily" -- computed at read time with the same boundaries the retention reconciler uses, so the API can never disagree with what GC is about to collect.
currentbooleanWhether this is the desktop's current head.
tombstonedAtstring | nullSet only on a destroyed desktop's rows (the 7-day recovery window). RFC 3339.
StatusMeaning
200This desktop's History, newest first
400Malformed id
401Missing/invalid credentials
404Desktop not found or belongs to another org

Restore a generation

POST /v1/desktops/{id}/restore

Moves the desktop's head to an earlier Generation. Restoring never destroys newer Generations -- you can always restore forward again.

ParamInRequiredDescription
idpathyesDesktop id
waitquerynoLong-poll until the operation settles (2s cadence, 120s cap)
Idempotency-KeyheadernoClient-supplied dedup key, scoped per-desktop

Request body (RestoreBody, camelCase):

{ "generationId": "gen_...", "expectedGeneration": null }
FieldTypeRequiredDescription
generationIdstringyesThe Generation to restore -- must belong to this desktop's own History (see List generations).
expectedGenerationinteger | nullnoOptional fencing CAS, same semantics as wake/hibernate/destroy -- see Concepts: generation fencing.
curl -sS -X POST "$BASE/desktops/$DESKTOP_ID/restore?wait=true" \
  -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"generationId": "gen_..."}'

On success, the settled operation's result carries {"state", "generation", "capturedGeneration"}:

  • A Hibernated desktop restores registry-only and stays Hibernated -- the target is actually applied on the next wake.
  • An Awake desktop is snapshotted first: its current state enters History as a new Generation (named by capturedGeneration), so nothing live is lost, then it's woken at the target.
StatusMeaning
200Operation settled (result as above), or the ?wait=true cap was reached while still pending/running
202Operation enqueued (no ?wait=true)
400Malformed id or body
401Missing/invalid credentials
404Desktop not found/foreign org, or generationId unknown, belonging to another desktop, or no longer restorable because retention has begun collecting its bundle (byte-identical detail "generation not found")
409Disk-only target (not yet restorable), wrong desktop state (via ?wait=true settle), or stale expectedGeneration
503This node is not the leader

On this page