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

# Sample expiration

> Set when samples expire, restore samples from Trash within 7 days, and override the org default per sample.

Every sample on Strand AI has an **expiration**: the date it will move to
Trash. Trash holds samples for 7 days, after which they are permanently
deleted. You can set a custom expiration on any sample, or turn expiration
off entirely.

## Org default expiration

Every org has a default expiration window (in days). Owners and admins set
it from **Settings → Sample expiration**. When you upload a sample, it
inherits this default. The setting is **off** by default, so samples never
expire until an owner or admin sets a policy.

<Note>
  Changing the org default updates expiration on samples that are still on
  the org default. It leaves samples with a custom expiration unchanged.
</Note>

## What happens when a sample expires

When a sample expires, it moves to Trash. Trash holds samples for 7 days.
During that window, you can restore them from the **Trash** tab on the
Samples page. After 7 days, samples in Trash are permanently deleted,
including all marker predictions. Billing history is retained.

## Per-sample expiration

You can set a custom expiration on any sample you can edit (sample
creator, org owner/admin, or Strand admin). Three modes:

* **Expire on a specific date**: the sample expires on the date you pick.
* **Never expire**: the sample has no expiration date and is unaffected
  by future org-policy changes.
* **Use org default**: clears the custom expiration and follows the
  current org policy.

Custom expirations (both "Expire on" and "Never expire") survive future
org-policy changes. Samples on the org default move with the policy.

## Restoring from Trash

Open the Samples page and switch to the **Trash** tab. Click **Restore**
on any sample within the 7-day window. Restoring brings the sample back
to the active list and extends its expiration so it isn't immediately
re-trashed.

Samples past the 7-day Trash window are gone and cannot be restored.

## Permissions

| Action                        | Allowed for                                                  |
| ----------------------------- | ------------------------------------------------------------ |
| Change org default expiration | Org owner · org admin (via **Settings → Sample expiration**) |
| Set per-sample expiration     | Sample creator · org owner/admin · Strand admin              |
| Bulk set expiration (≤ 500)   | Sample creator · org owner/admin · Strand admin              |
| Restore from Trash            | Sample creator · org owner/admin · Strand admin              |

## API examples

<CodeGroup>
  ```bash curl theme={null}
  # Set a sample to never expire.
  curl -X PATCH "https://app.strandai.com/api/v1/samples/$SAMPLE_ID/expiration" \
    -H "Authorization: Bearer $STRAND_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"expiresAt": null, "reason": "Active research project"}'

  # Bulk: set 50 samples to expire on a fixed date.
  curl -X PATCH "https://app.strandai.com/api/v1/samples/expiration" \
    -H "Authorization: Bearer $STRAND_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"sampleIds": ["...", "..."], "expiresAt": "2026-12-31T00:00:00Z"}'

  # Restore a sample from Trash within the 7-day window.
  curl -X POST "https://app.strandai.com/api/v1/samples/$SAMPLE_ID/restore" \
    -H "Authorization: Bearer $STRAND_API_KEY"
  ```

  ```python Python theme={null}
  from strand import Client

  client = Client()

  # Set a single sample to never expire.
  client.samples.set_expiration(sample_id, expires_at=None, reason="Active research project")

  # Expire on a specific date.
  from datetime import datetime, timezone
  client.samples.set_expiration(sample_id, expires_at=datetime(2026, 12, 31, tzinfo=timezone.utc))

  # Bulk: set never-expire.
  client.samples.set_expiration_bulk([id1, id2, id3], expires_at=None)

  # Restore from Trash.
  client.samples.restore(sample_id)
  ```

  ```r R theme={null}
  library(strandai)
  client <- strand_client()

  # Set a single sample to never expire.
  strand_set_expiration(client, sample_id, expires_at = NULL,
                        reason = "Active research project")

  # Expire on a specific date.
  strand_set_expiration(client, sample_id,
                        expires_at = as.POSIXct("2026-12-31", tz = "UTC"))

  # Bulk: set never-expire.
  strand_set_expiration_bulk(client, c(id1, id2, id3), expires_at = NULL)

  # Restore from Trash.
  strand_restore(client, sample_id)
  ```
</CodeGroup>

## Email notifications

Two expiration-related emails are sent (both opt-out under
**Account → Email preferences**):

* **Weekly digest**: Mondays at 13:00 UTC. One email per org owner/admin
  listing samples that expire in the next 7 days.
* **Policy-change notice**: sent whenever an owner or admin shortens the
  org expiration policy and the change creates near-term expirations
  (\< 30 days). Goes to every org member so they can set a custom
  expiration on samples they need to keep.
