> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squarecloud.app/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK: snapshots and backups

> List, create and restore snapshots of applications and databases, list every snapshot of the account, and download a snapshot file with api.downloadSnapshot().

Snapshots are backups of an app's or database's storage. Apps and databases share the same three methods:

* `api.apps.snapshots`: `list(appId)`, `create(appId)`, `restore(appId, name, versionId)`
* `api.databases.snapshots`: `list(databaseId)`, `create(databaseId)`, `restore(databaseId, name, versionId)`

How many snapshots you can create per day depends on your plan (see [Limits](#limits)).

Examples use the `api` client from [Creating the client](/en/sdks/js/client#creating-the-client). `appId` is the id of one of your apps: [`api.account.me()`](/en/sdks/js/client#account) lists them.

## Listing snapshots

```typescript theme={"system"}
for (const snapshot of await api.apps.snapshots.list(appId)) {
    console.log(snapshot.name, snapshot.version_id, snapshot.size, snapshot.modified);
}
```

| Field | Description |
| - | - |
| `name` | The snapshot id that `restore` takes |
| `version_id` | The version that `restore` takes |
| `size` | Size in bytes |
| `modified` | When it was taken |
| `url` | Signed download URL, **valid for 30 days** |
| `key` | Signed query string of the URL |
| `runtime` | Database engine or app language (`null` on old snapshots) |
| `origin` | `"automatic"`, `"manual"` or `null` |

## Creating a snapshot

`create()` waits for the snapshot (at least 120 s before timing out). A large snapshot may not finish in time: the API then answers 202 and the SDK returns `{ pending: true }`. The snapshot keeps generating and shows up in `list()` on its own, usually within 2 minutes.

```typescript theme={"system"}
const result = await api.apps.snapshots.create(appId);

if (result.pending) {
    // Poll list() later. Do not call create() again: that starts a new snapshot.
} else {
    console.log(result.url); // signed download URL, valid 30 days
}
```

<Warning>
  Never call `create()` again to check on a pending snapshot: it starts a new one and counts against the plan's daily snapshot quota. Poll `list()` instead.
</Warning>

## Restoring a snapshot

`restore(id, name, versionId)` takes the `name` and `version_id` of a listed snapshot.

```typescript theme={"system"}
const [latest] = await api.apps.snapshots.list(appId);

await api.apps.snapshots.restore(appId, latest.name, latest.version_id);
```

| Status | Code | When |
| - | - | - |
| 400 | `MISSING_PARAMETERS` | `name` or `versionId` is missing |
| 400 | `INVALID_SNAPSHOT_ID`, `INVALID_VERSION_ID` | Not a `name`/`version_id` from the listing |
| 400 | `SNAPSHOT_DATABASE_MISMATCH` | The snapshot's engine does not match the database's type (databases only) |
| 404 | `SNAPSHOT_NOT_FOUND` | No snapshot with that name and version |
| 404 | `SNAPSHOT_RESTORE_FAILED` | The restore could not be dispatched (the usual failure) |
| 413 | `PAYLOAD_TOO_LARGE` | The snapshot is too large to restore |

## Downloading a snapshot

`api.downloadSnapshot(url, { signal })` streams a snapshot file from its signed `url` (from `list()` or `create()`). It does **not** call the API: the API key is never sent to the storage host. It returns a `ReadableStream<Uint8Array>`, with nothing buffered in memory, and has no timeout (pass a `signal`).

```typescript theme={"system"}
import { createWriteStream } from "node:fs";
import { Writable } from "node:stream";

const [latest] = await api.apps.snapshots.list(appId);
const stream = await api.downloadSnapshot(latest.url);

await stream.pipeTo(Writable.toWeb(createWriteStream("backup.zip")));
```

An expired or invalid URL throws a `SquareCloudAPIError` with the storage host's HTTP status and `UNKNOWN_ERROR`.

## Account snapshots

`api.account.snapshots({ scope })` lists every snapshot of the account, optionally only `"applications"` or `"databases"`. It needs an active plan and shares the network endpoints' rate limit (429 `RATE_LIMITED`).

```typescript theme={"system"}
const all = await api.account.snapshots();
const databases = await api.account.snapshots({ scope: "databases" });
```

| Status | Code | When |
| - | - | - |
| 400 | `INVALID_SCOPE` | `scope` is not `applications` or `databases` |
| 402 | `UPGRADE_REQUIRED` | The account has no active plan |
| 429 | `RATE_LIMITED` | Rate limit reached |

## Limits

* `create()` is limited to one call per 180 seconds and to a daily quota that depends on the plan: going over the quota is 429 `DAILY_SNAPSHOTS_LIMIT_REACHED`.
* While a restore runs, deleting the app or starting the database is 403 `RESTORE_IN_PROGRESS`.

## Next steps

<CardGroup cols={3}>
  <Card title="Databases" icon="database" href="/en/sdks/js/databases">
    Create and manage databases.
  </Card>

  <Card title="Snapshot API reference" icon="code" href="/en/api-reference/endpoint/apps/snapshots/list">
    The REST endpoints behind these methods.
  </Card>

  <Card title="Snapshots from the CLI" icon="terminal" href="/en/cli-reference/snapshots">
    The same actions from the terminal.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.