# Snapshots API

> List snapshots, boot new devices from them, and delete them. Snapshots are created from a device with POST /v1/devices/:id/snapshot.

Source: https://akaphone-docs.pages.dev/api/snapshots/

Read [Snapshots](https://akaphone-docs.pages.dev/concepts/snapshots/) first: snapshots are pinned to the host that took them, have per-plan quotas, and can be `lost`. To create one, use [`POST /v1/devices/:id/snapshot`](https://akaphone-docs.pages.dev/api/devices/#snapshot-a-device).

## The snapshot object

```json
{
  "id": "snp_01m5vqsywgez2ntdv5fq42",
  "device_id": "dev_s6zr7mr4f2f1",
  "node_id": "nod_01m5vqsywg84jv64rmmqf9",
  "name": "signed-in-v2.3",
  "size_bytes": 1873215488,
  "status": "ready",
  "created_at": "2026-10-26T09:20:44.000Z"
}
```

| Field | Type | Description |
|---|---|---|
| `id` | string | `snp_…` |
| `device_id` | string | The device it was taken from. |
| `node_id` | string | The host that stores it. Restored devices are placed on this host. |
| `name` | string or null | Your label. |
| `size_bytes` | integer or null | Size on disk, once `ready`. |
| `status` | string | `pending`, `ready`, `error` or `lost`. |
| `created_at` | string | When it was taken. |

## List snapshots

`GET /v1/snapshots`

Returns a JSON **array** of your snapshots (the 200 most recent, deleted ones excluded), newest first.

```bash title="curl"
curl https://akaphone.abhgnx-417.workers.dev/v1/snapshots \
  -H "Authorization: Bearer $AKAPHONE_API_KEY"
```
```typescript title="TypeScript"
const snapshots = await fetch("https://akaphone.abhgnx-417.workers.dev/v1/snapshots", {
  headers: { Authorization: `Bearer ${process.env.AKAPHONE_API_KEY}` },
}).then((r) => r.json());
const ready = snapshots.filter((s: { status: string }) => s.status === "ready");
```
```python title="Python"
import os, requests

snapshots = requests.get(
    "https://akaphone.abhgnx-417.workers.dev/v1/snapshots",
    headers={"Authorization": f"Bearer {os.environ['AKAPHONE_API_KEY']}"},
).json()
```

**Response** `200 OK`

```json
[
  { "id": "snp_01m5vqsywgez2ntdv5fq42", "device_id": "dev_s6zr7mr4f2f1", "node_id": "nod_01m5vqsywg84jv64rmmqf9", "name": "signed-in-v2.3", "size_bytes": 1873215488, "status": "ready", "created_at": "2026-10-26T09:20:44.000Z" }
]
```

## Restore a snapshot

`POST /v1/snapshots/:id/restore`

Creates a **new device** from a `ready` snapshot. Equivalent to [`POST /v1/devices`](https://akaphone-docs.pages.dev/api/devices/#create-a-device) with `snapshot_id`, and subject to the same credit, concurrency and rate limits.

| Body field | Type | Default | Description |
|---|---|---|---|
| `name` | string | `null` | Name for the new device. |
| `profile` | string | `"pixel_8"` | Screen profile for the new device. |
| `android` | string | `"14"` | Android version. |
| `wait` | boolean | `false` | Hold the request until the device is running (max 90 s). |

`?wait=true&timeout=<seconds>` works too.

```bash title="curl"
curl -X POST https://akaphone.abhgnx-417.workers.dev/v1/snapshots/snp_01m5vqsywgez2ntdv5fq42/restore \
  -H "Authorization: Bearer $AKAPHONE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "run-1842", "wait": true}'
```
```typescript title="TypeScript"
const device = await fetch("https://akaphone.abhgnx-417.workers.dev/v1/snapshots/snp_01m5vqsywgez2ntdv5fq42/restore", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.AKAPHONE_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ name: "run-1842", wait: true }),
}).then((r) => r.json());
```
```python title="Python"
device = requests.post(
    "https://akaphone.abhgnx-417.workers.dev/v1/snapshots/snp_01m5vqsywgez2ntdv5fq42/restore",
    headers={"Authorization": f"Bearer {os.environ['AKAPHONE_API_KEY']}"},
    json={"name": "run-1842", "wait": True},
).json()
```

**Response** `201 Created` with the new [device](https://akaphone-docs.pages.dev/api/devices/#the-device-object):

```json
{ "id": "dev_qj196bgdqs10", "name": "run-1842", "status": "running", "profile": "pixel_8", "android": "14", "region": "eu-central", "node_id": "nod_01m5vqsywg84jv64rmmqf9", "snapshot_id": "snp_01m5vqsywgez2ntdv5fq42", "created_at": "2026-10-26T10:02:17.000Z", "ready_at": "2026-10-26T10:02:21.000Z", "terminated_at": null, "last_activity_at": "2026-10-26T10:02:17.000Z", "billed_minutes": 1, "error": null }
```

| Error | When |
|---|---|
| `404 not_found` | Unknown or deleted snapshot. |
| `409 conflict` | The snapshot is `lost` (*Snapshot was lost with the host that stored it and cannot be restored*), or is `pending` or `error`. |
| `402 insufficient_credits` | Balance below 1. |
| `409 concurrency_limit` | Plan device limit reached. |
| `429 rate_limited` | More than 10 device creations in a minute. |

If the snapshot's host is full, the device stays `queued` until a slot frees up there, and goes to `error` with `no_capacity` after 10 minutes.

## Delete a snapshot

`DELETE /v1/snapshots/:id`

Deletes the snapshot and frees its quota slot. The host removes the image in the background. Devices already restored from it keep running.

```bash title="curl"
curl -X DELETE https://akaphone.abhgnx-417.workers.dev/v1/snapshots/snp_01m5vqsywgez2ntdv5fq42 \
  -H "Authorization: Bearer $AKAPHONE_API_KEY"
```
```typescript title="TypeScript"
await fetch("https://akaphone.abhgnx-417.workers.dev/v1/snapshots/snp_01m5vqsywgez2ntdv5fq42", {
  method: "DELETE",
  headers: { Authorization: `Bearer ${process.env.AKAPHONE_API_KEY}` },
});
```
```python title="Python"
requests.delete(
    "https://akaphone.abhgnx-417.workers.dev/v1/snapshots/snp_01m5vqsywgez2ntdv5fq42",
    headers={"Authorization": f"Bearer {os.environ['AKAPHONE_API_KEY']}"},
)
```

**Response** `204 No Content`. `404 not_found` if it does not exist or was already deleted.
