Snapshots and volumes
Creating, restoring, copying and deleting persistent state.
POST /v1/sessions/{id}/snapshot capture
GET /v1/snapshots/{id} read
GET /v1/snapshots list
DELETE /v1/snapshots/{id} delete
POST /v1/snapshots/{id}/copy copy to another region
POST /v1/volumes create
GET /v1/volumes/{id} read
GET /v1/volumes list
PATCH /v1/volumes/{id} resize, relabel
DELETE /v1/volumes/{id} delete
Snapshots
Create
curl -sS "$WB_BASE_URL/sessions/$SESSION/snapshot" \
-H "Authorization: Bearer $WB_API_KEY" -H "Content-Type: application/json" \
-d '{
"name": "deps-installed",
"include_memory": true,
"retention_days": 30,
"labels": { "stage": "post-install" }
}'
{
"id": "snap_6Pq8Zt",
"object": "snapshot",
"source_session_id": "sess_2kQ9xwR4",
"tier": 2,
"include_memory": true,
"state": "creating",
"region": "bom1",
"created_at": "2026-10-06T09:31:12Z",
"expires_at": "2026-11-05T09:31:12Z"
}
| Field | Default | Notes |
|---|---|---|
name | auto | Not unique; use labels for lookup |
include_memory | false | Tiers 2–4. Captures running processes |
retention_days | none | Null means keep until deleted |
labels | {} |
The session keeps running throughout. The guest is frozen for 50–200 ms during capture, then thaws while the upload proceeds in the background against the frozen copy.
Poll until state is ready, or wait for the snapshot.ready webhook. Only ready snapshots
restore.
{
"id": "snap_6Pq8Zt",
"state": "ready",
"size_gib": 2.4,
"logical_size_gib": 11.8,
"parent_snapshot_id": null
}
size_gib is what is billed — deduplicated against the base template and compressed.
logical_size_gib is the filesystem size. The gap is usually large, which is what makes
snapshot-based workflows cheap.
Restore
curl -sS "$WB_BASE_URL/sessions" \
-H "Authorization: Bearer $WB_API_KEY" -H "Content-Type: application/json" \
-d '{ "tier": 2, "restore_from": "snap_6Pq8Zt", "idle_timeout_s": 300 }'
Rules:
- Same tier only. A tier 2 snapshot cannot restore at tier 3 — different runtime, different
device model.
snapshot_tier_mismatchotherwise. restore_fromandtemplateare mutually exclusive. The snapshot carries its template.- Resources may differ, within reason. More memory is fine; less than the snapshot's memory footprint fails. vCPU may change freely.
- Region follows the snapshot unless it has been copied.
- With
include_memory, processes resume. A dev server is still listening; a REPL still holds its state.wbagentreseeds the guest CSPRNG and forces a clock sync before any workload runs.
Restore latency:
| Case | Tier 2 | Tier 4 |
|---|---|---|
| Blocks cached on the target host | ~300 ms | ~3 s |
| Cold read from object storage | 2–6 s | 8–25 s |
Frequently restored snapshots are promoted into regional block caches automatically.
Copy across regions
curl -sS "$WB_BASE_URL/snapshots/snap_6Pq8Zt/copy" \
-H "Authorization: Bearer $WB_API_KEY" -H "Content-Type: application/json" \
-d '{ "region": "fra1" }'
Creates a new snapshot in the destination with its own ID. Billed as transfer plus storage in both
regions. Refused with residency_violation if the organization's policy does not allow the
destination.
Delete
curl -sS -X DELETE "$WB_BASE_URL/snapshots/snap_6Pq8Zt" -H "Authorization: Bearer $WB_API_KEY"
Deleting a snapshot that is the parent of another in a dedupe chain marks it deleted but leaves the shared blocks until the last child goes. Billing for those blocks moves to the surviving child, so the organization's total does not change — which surprises people who delete a parent expecting the bill to drop.
Lifecycle
POST /v1/snapshots/policies
{
"project_id": "proj_7fTn21",
"rules": [
{ "match": { "label.stage": "scratch" }, "retention_days": 1 },
{ "match": { "label.stage": "post-install" }, "retention_days": 30 },
{ "match": {}, "retention_days": 90, "max_per_session": 10 }
]
}
Rules are evaluated top to bottom; the first match wins. max_per_session keeps the oldest
snapshots pruned so an agent snapshotting every turn does not accumulate indefinitely.
Volumes
Create
curl -sS "$WB_BASE_URL/volumes" \
-H "Authorization: Bearer $WB_API_KEY" -H "Content-Type: application/json" \
-d '{
"name": "acme-monorepo",
"size_gib": 50,
"region": "bom1",
"zone": "bom1-b",
"filesystem": "ext4",
"end_user_id": "eu_customer_4821",
"labels": { "customer": "acme" }
}'
{
"id": "vol_5Km3Xp",
"object": "volume",
"name": "acme-monorepo",
"size_gib": 50,
"region": "bom1",
"zone": "bom1-b",
"state": "creating",
"attached_session_id": null
}
Omitting zone lets the platform pick the zone with the most warm-pool headroom, which reduces
future cold starts.
Attach
Volumes attach at session creation, not afterwards.
curl -sS "$WB_BASE_URL/sessions" \
-H "Authorization: Bearer $WB_API_KEY" -H "Content-Type: application/json" \
-d '{ "tier": 2, "volume_id": "vol_5Km3Xp", "mount_path": "/workspace" }'
One session at a time. A second attach fails with volume_in_use. The volume's zone constrains
placement, which is the most common reason an otherwise-healthy region cold starts a session.
Resize
curl -sS -X PATCH "$WB_BASE_URL/volumes/vol_5Km3Xp" \
-H "Authorization: Bearer $WB_API_KEY" -H "Content-Type: application/json" \
-d '{ "size_gib": 100 }'
Up only, online — the attached session sees the new size after a filesystem grow, which wbagent
performs automatically. To shrink, create a smaller volume and copy.
Delete
curl -sS -X DELETE "$WB_BASE_URL/volumes/vol_5Km3Xp" -H "Authorization: Bearer $WB_API_KEY"
Fails with volume_in_use if attached. Data is unrecoverable after deletion — snapshot first if the
contents matter.
Choosing between them
| Volume | Snapshot | |
|---|---|---|
| Concurrent use | One session | Many sessions restore the same snapshot |
| Cost | Provisioned GiB-month, always | Deduplicated GiB-month |
| Start latency | Zone-constrained placement, no restore step | Restore step, no zone constraint |
| Mutability | Read-write, persists in place | Immutable |
| Best for | One agent returning to one working state | Many sessions from one prepared state |
The cheapest pattern for an intermittently used workspace is snapshot-and-restore, typically an order of magnitude less than an idle volume and three orders less than an idle session. The volume wins when the working set is large enough that restore latency hurts more than storage cost.
Metering
| Meter | Billed on |
|---|---|
volume_gib_month | Provisioned size, from available onward, attached or not |
snapshot_gib_month | Stored deduplicated size, from ready onward |
snapshot_transfer_gb | Cross-region copies |
snapshot_restore_gb | Blocks read on a cold restore; free when cached |