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

# Delete a teardown

> Hard delete removes the row + storage files.

Permanently removes a teardown owned by your organization. The teardown
row is hard-deleted from the database; every attached file is
best-effort deleted from Supabase Storage.

<Warning>
  This is **irreversible**. The row is gone, and storage files are
  scheduled for deletion. If you want a recoverable "delete", use the
  [transition endpoint](/api-reference/teardowns/transition) with
  `action="archive"` instead the teardown drops out of the active feed
  but the data stays intact.
</Warning>

## Headers

<ParamField header="Authorization" type="string" required>
  `Bearer tdao_live_…`
</ParamField>

<ParamField header="X-Organization-Id" type="string" required>
  Your organization's UUID.
</ParamField>

## Path parameters

<ParamField path="teardown_id" type="string (UUID)" required />

## Auth requirements

Requires the **`seller`** capability on the user who minted the key
(same gate as create / update). Cross-org access returns **404
not\_found** never reveals existence in another org.

## What happens, in order

1. The teardown row is fetched and ownership checked. If it doesn't
   belong to your org, 404.
2. A `teardown.deleted` audit row is written with key fields
   snapshotted in `previous_state` (tail\_number, msn, status, label,
   start\_date, country). The `entity_id` keeps pointing at the deleted
   teardown's UUID audit logs outlive the entity.
3. Every URL in `documents[]`, `images[]`, and the four slot fields
   (`harvest_list`, `occm`, `aircraft_details_doc`,
   `non_incident_statement`) is parsed back to its Supabase Storage
   path and deleted. Individual file failures are logged but never
   fail the call storage orphans are recoverable; a failed delete
   is not.
4. The teardown row is hard-deleted from the database in the same
   transaction as the audit write.
5. `204 No Content` is returned with an empty body.

No other table foreign-keys back to `teardowns` (verified across
migrations 001-023), so there are no cascading dependents to clean up.

## Response

`204 No Content`. Empty body.

<RequestExample>
  ```bash curl theme={null}
  curl -X DELETE "$base_url/public/v1/teardowns/$teardown_id" \
    -H "Authorization: Bearer $api_key" \
    -H "X-Organization-Id: $org_id"
  ```

  ```python python theme={null}
  import requests
  resp = requests.delete(
      f"{base_url}/public/v1/teardowns/{teardown_id}",
      headers={
          "Authorization": f"Bearer {api_key}",
          "X-Organization-Id": org_id,
      },
  )
  if resp.status_code == 204:
      print("Deleted")
  elif resp.status_code == 404:
      print("Not found (or not yours)")
  else:
      resp.raise_for_status()
  ```
</RequestExample>

<ResponseExample>
  ```http 204 No Content theme={null}
  HTTP/1.1 204 No Content
  ```

  ```jsonc 404 Not Found theme={null}
  {
    "detail": "Teardown not found"
  }
  ```
</ResponseExample>

## Soft delete (recoverable alternative)

If you want the teardown to disappear from browse / search but keep
the data and the row for compliance / restoration:

```bash theme={null}
curl -X POST "$base_url/public/v1/teardowns/transition/$teardown_id" \
  -H "Authorization: Bearer $api_key" \
  -H "X-Organization-Id: $org_id" \
  -H "Content-Type: application/json" \
  -d '{"action": "archive"}'
```

The teardown's `status` becomes `archived`, it drops out of browse
results, but the row, attachments, and audit history all stay intact.
A subsequent `{"action":"restore"}` transition puts it back as a
draft.

## Idempotency

DELETE is **not** idempotent in the strict HTTP sense: the second
call returns `404 Teardown not found` because the row is gone after
the first call.

If your ERP needs idempotent semantics, treat both `204` and `404` as
"effectively deleted" the end-state is the same.

## See also

* [Transition](/api-reference/teardowns/transition) for soft deletes.
* [Errors](/concepts/errors) for `404` semantics.
