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

# Data retention and deletion

> Choose archive or permanent deletion, enable zero data retention, and understand what is retained.

## Archive is not delete

| Action                        | Can you resume the sandbox? | What happens to data?                                                                       |
| ----------------------------- | --------------------------- | ------------------------------------------------------------------------------------------- |
| **Stop/archive**              | Yes                         | Sandbox filesystem snapshots are retained for resume or fork.                               |
| **Delete**                    | No                          | Sandbox content, unshared snapshots, and machine data are queued for irreversible deletion. |
| **Zero data retention (ZDR)** | No after archive            | Every archived sandbox is automatically queued for deletion.                                |

A delete request returns `202 Accepted` with an operation. The Sandbox or snapshot disappears from normal reads immediately; poll the operation until its status is `completed`.

Everything on this page is available on all four surfaces:

|                         | CLI                          | API                              | SDKs                   | Dashboard                                                          |
| ----------------------- | ---------------------------- | -------------------------------- | ---------------------- | ------------------------------------------------------------------ |
| Delete a sandbox        | `boat delete <id>`           | `DELETE /sandboxes/{sandboxId}`  | `deleteSandbox`        | [Sandboxes](https://boat.dev/dashboard?tab=sandboxes) `⋯` → Delete |
| Delete a snapshot       | `boat snapshot delete <id>`  | `DELETE /snapshots/{snapshotId}` | `deleteSnapshot`       | [Snapshots](https://boat.dev/dashboard?tab=snapshots)              |
| Delete a named snapshot | `boat snapshot rm <name>`    | `DELETE /named-snapshots/{name}` | `deleteNamedSnapshot`  | [Snapshots](https://boat.dev/dashboard?tab=snapshots)              |
| Poll an operation       | `boat deletion status <id>`  | `GET /deletion-operations/{id}`  | `getDeletionOperation` | shown inline while deleting                                        |
| Read ZDR                | `boat data-retention status` | `GET /account/data-retention`    | `getDataRetention`     | [Account](https://boat.dev/dashboard?tab=account)                  |
| Enable ZDR              | `boat data-retention enable` | `PATCH /account/data-retention`  | `updateDataRetention`  | [Account](https://boat.dev/dashboard?tab=account)                  |

<Warning>
  Deletion operations cannot be canceled. Disabling ZDR only changes future archives; it does not stop operations already accepted.
</Warning>

## Delete a sandbox

Every Sandbox or snapshot delete requires `X-Ascii-Confirm-Delete` to exactly equal the target id. The CLI and the dashboard fill that header in for you.

<CodeGroup>
  ```bash CLI theme={null}
  boat delete bx_f7k2q9hd          # asks first, then follows the operation to completion
  boat delete bx_f7k2q9hd --yes    # no prompt, for scripts
  ```

  ```bash curl theme={null}
  curl -sS -X DELETE "$BOAT_API_BASE/sandboxes/$BOAT_ID" \
    -H "Authorization: Bearer $BOAT_API_KEY" \
    -H "X-Ascii-Confirm-Delete: $BOAT_ID"
  ```

  ```ts TypeScript theme={null}
  const accepted = await sandbox.deleteSandbox({
    sandboxId: "bx_f7k2q9hd",
    xAsciiConfirmDelete: "bx_f7k2q9hd",
  });
  console.log(accepted.operation.id, accepted.operation.status);
  ```

  ```python Python theme={null}
  accepted = sandbox.delete_sandbox(
      x_ascii_confirm_delete="bx_f7k2q9hd",
      sandbox_id="bx_f7k2q9hd",
  )
  print(accepted.operation.id, accepted.operation.status)
  ```
</CodeGroup>

In the dashboard, use the `⋯` menu on the sandbox's row in [Sandboxes](https://boat.dev/dashboard?tab=sandboxes) and choose **Delete**.

## Poll the operation

A delete returns an operation id (`bdop_…`). Poll it until `status` is `completed`.

<CodeGroup>
  ```bash CLI theme={null}
  boat deletion status bdop_0123456789abcdef0123456789abcdef
  ```

  ```bash curl theme={null}
  curl -sS "$BOAT_API_BASE/deletion-operations/$OPERATION_ID" \
    -H "Authorization: Bearer $BOAT_API_KEY"
  ```

  ```ts TypeScript theme={null}
  const current = await sandbox.getDeletionOperation({ operationId: accepted.operation.id });
  console.log(current.operation.status);   // pending | processing | blocked | completed
  ```

  ```python Python theme={null}
  current = sandbox.get_deletion_operation(accepted.operation.id)
  print(current.operation.status)
  ```
</CodeGroup>

`boat delete` already polls for you and prints the operation as it finishes, so `boat deletion status` is for checking back later on an operation you started elsewhere.

## Delete one snapshot

`DELETE /snapshots/{snapshotId}` takes the snapshot id in the same confirmation header. It returns `409` while another incremental snapshot or an active restore still depends on that snapshot. Named snapshots are removed by name instead, and do not use the header.

<CodeGroup>
  ```bash CLI theme={null}
  boat snapshot delete <snapshotId>     # one ordinary filesystem snapshot
  boat snapshot rm web-stack            # a named snapshot, by name
  ```

  ```bash curl theme={null}
  curl -sS -X DELETE "$BOAT_API_BASE/snapshots/$SNAPSHOT_ID" \
    -H "Authorization: Bearer $BOAT_API_KEY" \
    -H "X-Ascii-Confirm-Delete: $SNAPSHOT_ID"

  curl -sS -X DELETE "$BOAT_API_BASE/named-snapshots/web-stack" \
    -H "Authorization: Bearer $BOAT_API_KEY"
  ```

  ```ts TypeScript theme={null}
  await sandbox.deleteSnapshot({
    snapshotId: "<snapshotId>",
    xAsciiConfirmDelete: "<snapshotId>",
  });

  await sandbox.deleteNamedSnapshot({ name: "web-stack" });
  ```

  ```python Python theme={null}
  sandbox.delete_snapshot(
      snapshot_id="<snapshotId>",
      x_ascii_confirm_delete="<snapshotId>",
  )

  sandbox.delete_named_snapshot("web-stack")
  ```
</CodeGroup>

Both are also on the [Snapshots](https://boat.dev/dashboard?tab=snapshots) tab of the dashboard.

Deletion and retention responses use `Cache-Control: no-store`.

## Shared and named snapshots

Deleting a sandbox does not delete a named snapshot that you saved from it. Named snapshots are independent shared artifacts and may also share deduplicated storage with other snapshots. Physical objects are removed only after no retained artifact references them.

Removing a named snapshot makes it unavailable immediately, but its backing data is scheduled no earlier than **six hours** later. Snapshot upload URLs are signed for six hours; this fence prevents an already-issued upload from recreating data after deletion.

Enabling ZDR removes named snapshots and queues their backing data for deletion. You cannot create a named snapshot while ZDR is enabled.

## Enable zero data retention

Read the setting from anywhere, including with an API key:

<CodeGroup>
  ```bash CLI theme={null}
  boat data-retention status
  ```

  ```bash curl theme={null}
  curl -sS "$BOAT_API_BASE/account/data-retention" \
    -H "Authorization: Bearer $BOAT_API_KEY"
  ```

  ```ts TypeScript theme={null}
  const policy = await sandbox.getDataRetention();
  console.log(policy.enabled);
  ```

  ```python Python theme={null}
  policy = sandbox.get_data_retention()
  print(policy.enabled)
  ```
</CodeGroup>

It is also in the `zeroDataRetention` fields returned by `GET /me`.

<Warning>
  **Changing** the setting requires an interactive browser session, not an API key. Run `boat login` without a key first, or use the dashboard. An SDK client configured with `BOAT_API_KEY` gets `403 session_required`, by design: turning this on queues every archived sandbox for deletion, so it should never be reachable from a leaked service credential.
</Warning>

Enabling also requires the exact phrase `delete archived sandbox data`:

<CodeGroup>
  ```bash CLI theme={null}
  boat data-retention enable          # prompts for the confirmation phrase
  boat data-retention enable --yes    # skip the prompt
  ```

  ```bash curl theme={null}
  curl -sS -X PATCH "$BOAT_API_BASE/account/data-retention" \
    -H "Authorization: Bearer $BOAT_SESSION_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"enabled":true,"confirmation":"delete archived sandbox data"}'
  ```

  ```ts TypeScript theme={null}
  // Requires a browser session token, not an API key.
  await sandbox.updateDataRetention({
    dataRetentionUpdateRequest: {
      enabled: true,
      confirmation: "delete archived sandbox data",
    },
  });
  ```

  ```python Python theme={null}
  from boat_sdk.models.data_retention_update_request import DataRetentionUpdateRequest

  # Requires a browser session token, not an API key.
  sandbox.update_data_retention(DataRetentionUpdateRequest(
      enabled=True,
      confirmation="delete archived sandbox data",
  ))
  ```
</CodeGroup>

In the dashboard, the toggle is under **Data & privacy** on the [Account](https://boat.dev/dashboard?tab=account) tab.

When enabled:

* Existing archived sandboxes are queued for deletion.
* Future Sandboxes discard data when they archive.
* Named snapshots are removed and queued for deletion.
* Accepted deletion continues in the background until verified complete.

## Close your account

Closing takes the whole account with it, not one sandbox. It happens on the [Account](https://boat.dev/dashboard?tab=account) tab and nowhere else: it needs a dashboard sign-in session, and is refused to an API key and to the CLI.

Closing does all of this at once:

* Cancels your subscription **immediately**, not at the end of the period. Remaining plan time and unused credits are forfeited, so close after a renewal only if you mean to.
* Archives every running sandbox, with a snapshot.
* Revokes every API key and every other session. The one you closed from stays alive so you can still read your invoices.
* Emails you a confirmation with the date your data is purged.

You then have **30 days**. During that window the account is closed but recoverable: **Reopen** on the same tab brings it back, subscription aside. After 30 days the sandbox data is purged for good, and reopening after that returns a working but empty account.

<Warning>
  The same screen offers permanent erasure instead, for GDPR requests. It skips the 30 days, scrubs the data and your identity as soon as the sandboxes finish archiving, and **cannot be cancelled or reopened**. Ordinary closing is what you want unless you specifically need erasure.
</Warning>

## Records retained after content deletion

Ascii retains only records needed for security, abuse prevention, compliance, and billing. This includes machine-assignment history (internally `MachineAssignmentLog`), network attribution such as assigned IP/MAC records, security audit events, and billing/usage records.

These records identify who controlled infrastructure and when; they do not retain your sandbox filesystem, prompts, messages, secrets, or generated artifacts.

## Related

* [Privacy Policy](https://boat.dev/privacy)
* [Snapshots](/snapshots)
* [CLI reference](/cli-reference)
* [Boat Public API v1](/api/v1)
* [Delete Boat API](/api/reference/sandboxes/permanently-delete-sandbox-data)
* [Update data retention API](/api/reference/account/update-account-data-retention-policy)
