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

# Soft deletes

> Every domain record is soft-deletable. Deletes set deletedAt; reads filter on isNull(deletedAt).

WiseYield uses **soft deletes** for every domain record: farms, fields, blocks, crops, tasks, expenses, sales, lab analyses, fertigation events, irrigation events, workers, payroll runs, invoices, and more.

## What "soft delete" means

A `DELETE` API call does **not** remove the row from the database. Instead, it sets the row's `deletedAt` timestamp to the current time. The row remains intact for:

* **Audit trails** — financial records, payroll runs, and lab analyses retain their full history for compliance.
* **Foreign-key integrity** — a deleted crop still satisfies the `crop_expenses.crop_id` FK; the expense row is itself soft-deleted in cascade rather than orphaned.
* **Restoration** — support can restore an accidentally-deleted record by clearing `deletedAt`.

## What this means for read endpoints

All list and read endpoints filter on `deletedAt IS NULL` — soft-deleted records are invisible by default. You don't need to pass any flag; the filter is mandatory on the server.

```bash theme={null}
GET /api/v1/farms        # returns active farms only
GET /api/v1/farms/{id}   # 404 if the farm is soft-deleted
```

Deleted records are not retrievable via the public API.

## What this means for create endpoints

Uniqueness constraints (e.g. one farm name per user) only consider **active** rows. If you delete a farm named "Green Valley", you can create a new one with the same name the next moment — the constraint is `unique(owner_id, name) WHERE deleted_at IS NULL`.

## What this means for delete endpoints

```bash theme={null}
DELETE /api/v1/farms/{id}
```

* Returns `204 No Content` on success.
* Idempotent: deleting an already-deleted row returns `404 NOT_FOUND` (because the row is invisible to subsequent reads).
* Cascades to related rows via the same soft-delete pattern — deleting a farm soft-deletes its fields, blocks, crops, tasks, and financial records, all timestamped with the same `deletedAt`.

## What this means for analytics + financial rollups

Financial aggregations (P\&L, cash-flow forecast, payroll summaries) **exclude soft-deleted rows**. If you delete a sale, it disappears from the next P\&L call. To preserve historical totals while removing a row from operational views, prefer the **archive** status (e.g. `farms.status = "archived"`) over delete.

| Action                       | When to use                                                                              |
| ---------------------------- | ---------------------------------------------------------------------------------------- |
| **Set status to `archived`** | You want the record kept out of active views but still counted in historicals            |
| **Delete (soft)**            | You want the record gone from every view; it's a mistake or no longer represents reality |

## Hard deletes

Hard deletes are not exposed via the public API. They happen only via:

* **Account closure** (user-initiated, 30-day grace period, then hard-deleted by a scheduled cron).
* **GDPR / privacy requests** processed by support.
* **Database housekeeping** by operators.

If you need a record permanently removed for compliance reasons, contact [support@wiseyield.co](mailto:support@wiseyield.co).
