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

# Manage file lifecycle

> Update metadata, move, copy, soft-delete, hard-delete, and restore files.

## Update a file

```http theme={null}
PUT /files/update/{fileId}
```

The body is strict. Unknown fields are rejected.

```json theme={null}
{
  "name": "signed-master-agreement",
  "visibility": "private",
  "retentionPeriod": "1Y",
  "metadata": {
    "matter": "ACME-2026"
  },
  "version": 4
}
```

| Field | Type | Notes |
| - | - | - |
| `name` | string | 1–255 characters, trimmed |
| `visibility` | `private` or `public` | Does not by itself create anonymous access |
| `retentionPeriod` | retention value | Cannot shorten or clear an active retention |
| `metadata` | object | Free-form metadata |
| `version` | positive integer | Optimistic-concurrency token accepted by the server |

The change is rejected when:

* the file has active retention,
* the file's bucket has active retention,
* the caller lacks `file:write`,
* the body contains an unknown key.

A no-op update can return an empty string in `data`. Treat the HTTP status as the success signal, then re-read the file if you need the new state.

> [!WARNING]
>
> `version` is accepted for compatibility with the frontend's mutation flow. It is not a general-purpose compare-and-swap contract. Do not build conflict detection solely on it.

## Move a file

```http theme={null}
POST /files/move/{fileId}
```

```json theme={null}
{
  "destinationFolderId": "4d1e2f3a-5b6c-4d7e-8f90-1a2b3c4d5e6f",
  "destinationBucketId": "0f0b0c7e-6a1f-4b8e-9a3e-1f2c3d4e5f60"
}
```

| Field | Required | Notes |
| - | - | - |
| `destinationFolderId` | Yes for same-bucket moves | Target folder, or `null` for the bucket root. Omitting it in a same-bucket move is rejected. |
| `destinationBucketId` | No | Set it for a cross-bucket move. When moving across buckets, omitting `destinationFolderId` targets the destination bucket root. |

Cross-bucket moves are allowed only within the same company. A destination folder must belong to the destination bucket.

Response:

```json theme={null}
{
  "status": 200,
  "message": "File moved",
  "data": {
    "fileId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "destinationFolderId": "4d1e2f3a-5b6c-4d7e-8f90-1a2b3c4d5e6f",
    "destinationBucketId": "0f0b0c7e-6a1f-4b8e-9a3e-1f2c3d4e5f60"
  }
}
```

`destinationBucketId` is omitted when the move stays in the same bucket.

## Copy a file

```http theme={null}
POST /files/copy/{fileId}
```

```json theme={null}
{
  "destinationFolderId": "4d1e2f3a-5b6c-4d7e-8f90-1a2b3c4d5e6f",
  "destinationBucketId": "0f0b0c7e-6a1f-4b8e-9a3e-1f2c3d4e5f60"
}
```

The copy duplicates the stored bytes and consumes storage capacity. The new file's display name gets a ` (copy)` suffix.

Response:

```json theme={null}
{
  "status": 200,
  "message": "File copied",
  "data": {
    "originalFileId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "newFileId": "5b4a3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d",
    "destinationFolderId": "4d1e2f3a-5b6c-4d7e-8f90-1a2b3c4d5e6f",
    "destinationBucketId": "0f0b0c7e-6a1f-4b8e-9a3e-1f2c3d4e5f60",
    "newHashName": "a1b2c3d4e5f6..."
  }
}
```

If capacity is insufficient, the copy fails with `402`. The original is not modified.

## Soft-delete and hard-delete

```http theme={null}
DELETE /files/delete/{fileId}?trash=soft
DELETE /files/delete/{fileId}?trash=hard
```

| Mode | Behavior | Reversible |
| - | - | - |
| `soft` (default) | Marks deleted; starts the trash display window | Yes, during the window |
| `hard` | Permanently removes the file and its versions | No |

The query value is case-insensitive. A soft delete:

* blocks when the file has active retention,
* blocks when the bucket has active retention,
* blocks when a legal hold applies,
* keeps the bytes stored and billed until purge.

A hard delete:

* blocks while retention is active,
* blocks while a legal hold applies,
* removes all versions,
* returns `410` if the item was already purged after the display window.

The success payload is an empty string rather than an object. Check the HTTP status.

> [!WARNING]
>
> Hard deletion is irreversible. Build an explicit confirmation step and never expose it as the default action.

## Restore from trash

```http theme={null}
POST /files/{fileId}/restore
```

```json theme={null}
{
  "status": 200,
  "message": "File restored from trash",
  "data": {
    "status": 200,
    "message": "File restored from trash",
    "data": {
      "fileId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
    }
  }
}
```

The restore payload is nested, and the HTTP status is **always `200`** when the controller returns a service result. The real outcome is in `data.status`:

| Case | HTTP | `data.status` |
| - | - | - |
| File was in trash | `200` | `200` |
| File was not in trash | `200` | `400` |
| Display window elapsed | `200` | `410` |
| File does not exist | `200` | `404` |

Read `data.data.fileId` on success, and branch on `data.status` for failures. Errors thrown before the service result — permission failures, for example — use normal HTTP error codes.

## Retention and legal hold

Before showing destructive actions, read the file's retention state from a list response or folder content:

* `isRetention: true` means an active lock.
* `retentionPeriod` shows the configured period.
* Bucket retention is visible on bucket records.

Legal hold is not exposed as a field on file responses. If a delete unexpectedly returns `403`, a legal hold may be the cause.

## Lifecycle checklist

> [!TIP]
>
> Renames use `PUT /files/update/{fileId}` with only allowed fields.

> [!TIP]
>
> Moves and copies validate the destination bucket and folder before the request.

> [!TIP]
>
> Soft delete is the default; hard delete requires explicit confirmation.

> [!TIP]
>
> Retention and legal hold are checked before offering delete.

> [!TIP]
>
> Restore handles `400`, `404`, and `410` distinctly.

> [!TIP]
>
> Copy operations account for storage capacity.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.