# Restore a file from the trash

Source: https://workroad.app/docs/api/restore-note-file

`POST https://workroad.app/api/v1/files/{fileId}/restore`

Brings a trashed file back to its note's files and returns it. Needs `files:delete`, the scope that trashed it. The note must be out of the trash. An image file removed from the note's content stays out of it. The file never stopped counting toward the file and storage limits, so a restore always succeeds.

- MCP tool: `restoreNoteFile` on `https://workroad.app/api/mcp`
- Required scopes: files:delete
- Test mode: `POST https://workroad.app/api/test/v1/files/{fileId}/restore` checks the request and returns the example response without changing anything.

## Path parameters

- `fileId`: string (uuid), required. Note file id, scoped to the key's user.

## Headers

- `Idempotency-Key`: string, optional, 1-255 visible ASCII characters. Makes the POST safe to retry: a retry with the same key and body replays the first response, and the same key with a different body returns 409 `idempotency_conflict`. Kept for 24 hours. Over MCP it is the `idempotencyKey` argument.

## Response

`200` OK

- `data`: object, required
  - `id`: string (uuid), required
  - `noteId`: string (uuid), required
  - `kind`: one of `"document"`, `"image"`, required. `document` for files the API can upload and complete. `image` for images added in the app, which only the app parses.
  - `name`: string, required
  - `mimeType`: string, required
  - `sizeBytes`: integer or null, required. The size declared when the upload was created. Null for files uploaded before sizes were recorded.
  - `url`: string, required. Where the file is readable once uploaded. Anyone with this URL can read it.
  - `status`: one of `"awaiting_upload"`, `"parsing"`, `"ready"`, `"failed"`, `"expired"`, required. `awaiting_upload` until the file is uploaded and completed, `parsing` while its text is extracted, then `ready`, `failed` or `expired`.
  - `failure`: string or null, required. Why the file is `failed` or `expired`, such as `object-missing`, `unsupported-format` or `too-large`. Null otherwise.
  - `chars`: integer, required. Characters of extracted text.
  - `imageCount`: integer, required. Images extracted from the document.
  - `jobId`: string or null, required. The newest parse job for this file, when there is one.
  - `createdAt`: string (date-time), required. When the upload was created.

### Example

```json
{
  "data": {
    "id": "3c2b1a09-8f7e-4d6c-9b5a-4e3d2c1b0a9f",
    "noteId": "3c2b1a09-8f7e-4d6c-9b5a-4f3e2d1c0b9a",
    "kind": "document",
    "name": "Cell biology lecture.pdf",
    "mimeType": "application/pdf",
    "sizeBytes": 482113,
    "url": "https://storage.example.com/workroad/note/3c2b1a09-8f7e-4d6c-9b5a-4f3e2d1c0b9a/3c2b1a09-8f7e-4d6c-9b5a-4e3d2c1b0a9f-cell-biology-lecture.pdf",
    "status": "ready",
    "failure": null,
    "chars": 18240,
    "imageCount": 3,
    "jobId": "7a6b5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d",
    "createdAt": "2026-01-15T09:30:00.000Z"
  }
}
```

## Errors

Every error has the body `{ "error": { "code", "message", "details" } }`.

- `400`: Invalid request body or query
- `401`: Missing, invalid, disabled or expired API key
- `402`: `api_allowance_reached`: this month's API and AI app requests on the free plan are used up. `details` has `limit`, `used`, `resetsAt` and `upgradeUrl`. Nothing ran; WorkRoad Plus has no monthly limit.
- `403`: The API key lacks the required scope
- `404`: No note file with that id is in the trash for this key's user, on a note outside the trash.
- `405`: Method not allowed. Use a method from the Allow header.
- `409`: The Idempotency-Key was reused with a different request body, or a request with the same key is still in progress.
- `429`: Rate limit exceeded. Wait for Retry-After before retrying. The rate-limit headers are absent when the key's own limiter rejected the request before the per-endpoint bucket check ran.
- `500`: Internal server error
