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

# Deleting and restoring

> The recovery window, what a deleted secret still answers, and what restoring gives back.

## Deleting and restoring

Deleting a secret removes nothing immediately. It moves the secret into a
**recovery window** and returns `deleted_at` and `scheduled_purge_at`. Once
`scheduled_purge_at` passes, the secret and every version are removed for good.

<Tabs>
  <Tab title="Console">
    Open the secret from **Secrets** and use **Delete secret**, in the **Danger
    zone** on its **Settings** tab. The dialog takes a **Recovery window
    (days)** and will not confirm until you type the secret's name back.
  </Tab>

  <Tab title="API">
    ```bash theme={null}
    DELETE /v1/secrets/{secret_id}
    { "recovery_window_seconds": 1209600 }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    basaltic secrets delete <secret-id> --recovery-window-seconds 1209600
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    sec, err := secrets.New(cfg).DeleteSecret(ctx, secretID, &secrets.DeleteSecretRequest{
        RecoveryWindowSeconds: basaltic.Int(1209600),
    })
    ```

    `sec.ScheduledPurgeAt` is the deadline to restore by.
  </Tab>
</Tabs>

<ResponseField name="recovery_window_seconds" type="86400 – 2592000, default 604800">
  1 to 30 days, defaulting to 7. Set it at creation to give a secret its own
  default, or pass it on the delete call to override it for that deletion.
</ResponseField>

While a secret sits in the window:

* `GET /v1/secrets/{id}` still describes it, so you can see the purge date.
* Reading or writing the value is refused with `409 SECRET_DELETED`.
* Updating metadata is refused the same way.
* It is hidden from `GET /v1/secrets` unless you pass `include_deleted=true`.

Restoring cancels the purge and puts the secret back. Restoring one that was
never deleted is a harmless no-op.

<Tabs>
  <Tab title="Console">
    A secret in the window shows **Restore** in its header, in place of **Put
    New Value**.
  </Tab>

  <Tab title="API">
    ```bash theme={null}
    POST /v1/secrets/{secret_id}/restore
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    basaltic secrets restore <secret-id>
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    sec, err := secrets.New(cfg).RestoreSecret(ctx, secretID)
    ```
  </Tab>
</Tabs>

<Warning>
  Repeating the delete **does not extend the window**. A second `DELETE` during
  the window keeps the original `scheduled_purge_at` rather than pushing it
  out, so a retry loop or a re-run of a teardown script cannot quietly keep a
  secret alive forever. If you need more time, restore the secret and delete it
  again with a longer `recovery_window_seconds`.
</Warning>

<Note>
  Deleting frees the secret's quota straight away, so you can create a
  replacement without waiting out the window. Restoring has to take that quota
  back, which means a restore can fail with `403 QUOTA_EXCEEDED` if your
  account has since filled the slot. Free one before restoring.
</Note>
