---
title: "Archive (soft-delete) a project"
method: DELETE
path: "/projects/v1/{project_id}"
tags: ["Projects"]
---

# Archive (soft-delete) a project

`DELETE /projects/v1/{project_id}`

## Request

- Base URL: `https://api.run402.com`
- URL: `https://api.run402.com/projects/v1/{project_id}`
- Auth: one of:
  - HTTP bearer
  - API key in header `SIGN-IN-WITH-X`
  - HTTP bearer
  - API key in header `x-admin-key`

Archives and soft-deletes a project. Compatibility path accepts service_key or admin auth. Control-plane session / SIWX callers must satisfy the owner-only project.delete policy; browser sessions require passkey step-up, while SIWX wallet signatures are fresh per request.

## Path parameters

- `project_id` string, required: Run402 project ID. Public IDs are not UUIDs.

## Response `200`

Project purged (terminal delete). When the project had a vault, the response additionally discloses that the vault SURVIVES the delete.

- object
  - `status` string
  - `project_id` string: Run402 project ID. Public IDs are not UUIDs.
  - `vault` object: Present ONLY when the deleted project had a vault. Deleting a project does NOT delete its vault: the encrypted history still restores via `git fetch run402::<org>/<project> refs/run402/deploys/latest`, its bytes still count against the organization's pooled storage, and no client command removes it (V0 has no purge verb, and `prune` requires an owner-signed intent plus two verifier receipts). Absent for projects with no vault, whose response is unchanged.
    - `repo_id` string
    - `retained` boolean
    - `source_bytes` string: Retained vault bytes, still pooled against the organization's storage limit (see pool_usage.vault_source_bytes on GET /tiers/v1/status).
    - `counts_against_org_storage` boolean
    - `removable_by_client` boolean: Always false in V0 — no client-invocable purge exists for a retained vault.
  - `warnings` object[]: Present only alongside `vault`: a single `vault_retained` entry stating what survived the delete.
    - `kind` string
    - `message` string
  - `next_actions` NextAction[]: Present only alongside `vault`: `inspect_vault` (the retained vault's record) and `check_usage` (its bytes in pooled storage).
    - `type` string, required: Advisory machine-readable action type such as retry, authenticate, submit_payment, fund_wallet, renew_tier, check_usage, resume_deploy, edit_request, edit_migration, contact_support, upgrade_client, poll (poll the project events feed — appended when the envelope carries a correlated_platform_incident), or hand_to_member (on a commit/promote response that just activated a public site: show the human urls.site and urls.console, relay Run402's offer to promote the build on @run402com, and ask yes or no — see `credited_as` below).
    - `method` string
    - `path` string
    - `auth` string
    - `why` string
    - `credited_as` string, nullable: `hand_to_member` only. The caller's own live presence name in the project's default room, else that room's most recently active live presence, else `null` — in which case `why` tells the agent that joining the room with a name (`run402 rooms join --name ...`) is how the promotion credits it.
    - `body` object: `hand_to_member` only. A ready-to-send `POST /feedback/v1` template: `{ project_id, message: "promote: yes", handle? }`.

## Other responses

- `401`: Missing or invalid authentication. Run402-originated JSON bodies use the canonical ErrorEnvelope.

---

[API](https://skmtc.dev/run402/apis/run402-api.md) · [All operations](https://skmtc.dev/run402/apis/run402-api/llms.txt) · [OpenAPI document](https://skmtc.dev/run402/apis/run402-api/revisions/893607557f50?raw)
