---
title: "Archive (soft-delete) or purge an app (v2)"
method: DELETE
path: "/v2/apps/{appId}"
tags: ["Apps"]
---

# Archive (soft-delete) or purge an app (v2)

`DELETE /v2/apps/{appId}`

## Request

- Base URL: `https://api.chat.ethora.com`
- URL: `https://api.chat.ethora.com/v2/apps/{appId}`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer

**Auth**: Tenant Actor

Default behavior is **soft archive**: the app's `status` flips to `archived`,
login and listing endpoints hide it, and all child entities (users, chats,
messages, files) are retained. The archive is reversible via
`POST /v2/apps/{appId}/restore`.

Pass `?mode=hard` for a **cascade purge** (irreversible). The app is
immediately flipped to `status: 'deleting'` and a backend-jobs worker
drains every related collection (users + XMPP accounts, chats + MUC
rooms + MAM, files + MinIO objects, sources, AppAcl, RefreshToken,
SessionsLog, BotInstance, AppStat, Owner2App, App doc).

The hard-delete response is `202 Accepted` with a `jobId` and `statusUrl`
so the admin panel can poll progress via
`GET /v2/apps/purge-jobs/{jobId}`. Soft archive returns `200` immediately
since it has no async work.

Optional `?reason=...` is stored alongside the archive metadata for audit
purposes (visible to the tenant owner via the list endpoint with
`?status=archived`).

Supports `User JWT` and `B2B Server JWT`.

## Path parameters

- `appId` string, required

## Query parameters

- `mode` 'soft' | 'hard'
- `reason` string

## Response `200`

archived ok (mode=soft)

## Other responses

- `202`: purge enqueued (mode=hard); poll the returned statusUrl
- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: app not found
- `409`: app already in an unrecoverable state (deleted)
- `422`: Unprocessable Entity
- `500`: Internal Server Error

---

[API](https://skmtc.dev/ethora/apis/platform-api.md) · [All operations](https://skmtc.dev/ethora/apis/platform-api/llms.txt) · [OpenAPI document](https://skmtc.dev/ethora/apis/platform-api/revisions/01b6e64378ee?raw)
