---
title: "Cleanup Expired Workspaces"
method: POST
path: "/v2/internal/cleanup-expired-workspaces"
tags: ["v2 - Internal"]
---

# Cleanup Expired Workspaces

`POST /v2/internal/cleanup-expired-workspaces`

## Request

- Base URL: `https://api.jubjubapp.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.jubjubapp.com/v2/internal/cleanup-expired-workspaces`
- Auth: HTTP bearer

Delete EXPIRED ANONYMOUS TRIAL workspaces. Never a creator's.

🔴 THIS CRON MAY NOT DELETE OWNED WORKSPACES, AND CANNOT.
Creator media is inventory: it is what x402 agents buy through
media_search / purchase_metadata / purchase_content. A timer that deletes
it destroys saleable stock and a creator's archive at once. Owned
workspaces are permanent (decision 2026-09-01, workspace_routes.py:521);
only anonymous "Try Now" sandboxes expire.

Two independent things keep that true, and only the second is load-bearing:

  1. the query below filters `owner_id == None`, so an owned workspace is
     not even considered. This is an efficiency and a statement of intent.
  2. `_delete_trial_workspace_cascade` RE-READS each document and RAISES
     on anything owned. This is the guarantee. Widening the query cannot
     widen what gets deleted.

A refusal is logged and counted, never swallowed: if this cron ever selects
an owned workspace, that is a bug in the selection and the evidence must
survive the run.

Scheduled daily; trials live TrialConfig.SESSION_DURATION_HOURS (72h), so a
daily tick removes them within a day of expiry. Processes up to batch_size
per invocation.

## Query parameters

- `batch_size` integer

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/jubjubapp/apis/jubjub-api.md) - [All operations](https://skmtc.dev/jubjubapp/apis/jubjub-api/llms.txt) - [OpenAPI document](https://skmtc.dev/jubjubapp/apis/jubjub-api/revisions/353157b296f2?raw)
