---
title: Hard-delete a workspace (owner-only, typed-slug confirmation)
description: Permanently deletes the workspace and cascades all member rows.
api_method: DELETE
api_path: "/v1/workspaces/{workspaceId}"
canonical_url: https://wiblo.app/docs/developers/api/workspaces/delete-workspace
last_updated: 2026-07-28T17:31:44+02:00
md_url: https://wiblo.app/docs/developers/api/workspaces/delete-workspace.md
---

# Hard-delete a workspace (owner-only, typed-slug confirmation)

`DELETE /v1/workspaces/{workspaceId}`

Permanently deletes the workspace and cascades all member rows. Owner-only at the route layer; the SECURITY DEFINER RPC is the DB-level defence in depth. The typed `confirm_slug` body field must exactly match the workspace's current slug (case-sensitive). On success, an audit row is written to the service-role-only `workspace_deletion_log` inside the same transaction. Per-user rate-limited at 5/60s.

## Path parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `workspaceId` | `string` | Yes |  |

## Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `confirm_slug` | `string` | Yes |  |

## Request

**curl**

```bash
curl https://api.wiblo.app/v1/workspaces/{workspaceId} \
  -X DELETE \
  -H "Authorization: Bearer $WIBLO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "confirm_slug": "..."
}'
```

**TypeScript**

```ts
import { createSdk, deleteWorkspace } from "@workspace/sdk"

const sdk = createSdk({ baseUrl: "https://api.wiblo.app" })

const { data, error } = await deleteWorkspace({
  client: sdk,
  path: { workspaceId: "..." },
  body: {
    "confirm_slug": "..."
  },
})
```

## Responses

**`204`** — Workspace and all member rows deleted.

**`400`** — Body failed Zod validation (`VALIDATION_FAILED`) — typically a missing or empty `confirm_slug`. Returns `ApiErrorEnvelope`.

**`401`** — No valid Supabase session cookie was present. Returns `ApiErrorEnvelope`.

**`403`** — Caller is a member of the workspace but is not an owner (`OWNER_REQUIRED`). Returns `ApiErrorEnvelope`.

**`404`** — Caller has no active membership in the workspace, or the workspace does not exist (`WORKSPACE_NOT_FOUND`). Both cases share the envelope to avoid leaking existence. Returns `ApiErrorEnvelope`.

**`422`** — Path param failed UUID validation (`INVALID_PARAMS`) or the typed `confirm_slug` did not match the workspace slug (`CONFIRM_MISMATCH`). Returns `ApiErrorEnvelope`.

**`429`** — Rate limit exceeded. The body's `error.code` is `RATE_LIMITED` and `error.details.retry_after` is the same number of seconds as the `Retry-After` header. Returns `ApiErrorEnvelope`.
