# Files

Base: `/workspaces/{workspaceId}/buckets/{bucketId}/files`

## List & search

`GET .../files` · `files:read`

| Query | Description |
|-------|-------------|
| `prefix` | Key prefix filter |
| `parentPrefix` | Exact parent folder |
| `search` | Case-insensitive key contains (or semantic query) |
| `tag` | Filter by tag |
| `semantic=1` | CLIP/pgvector search when `search` is set |
| `limit` | Max 500 (default 100) |
| `offset` | Pagination |

```bash
curl -s -H "Authorization: Bearer $FR_KEY" \
  "$BASE/workspaces/$WS/buckets/$BUCKET/files?search=italy&semantic=1&limit=10" | jq
```

File shape (serialized):

```json
{
  "id": "...",
  "bucketId": "...",
  "workspaceId": "...",
  "key": "photos/italy.jpg",
  "parentPrefix": "photos/",
  "size": 12345,
  "lastModified": "...",
  "etag": "...",
  "contentType": "image/jpeg",
  "isFolder": false,
  "thumbnailKey": "...",
  "tags": ["travel", "italy"],
  "description": "...",
  "contentHash": null,
  "embeddingStatus": "ready",
  "enrichedAt": "...",
  "url": "https://cdn.example.com/photos/italy.jpg",
  "thumbnailUrl": "https://cdn.example.com/.thumbs/photos/italy.jpg"
}
```

Semantic hits may include `distance`.

`url` is the public CDN URL when the bucket has `publicDomain`. Use it to **display** or embed the file (images, markdown). It does not expire. `thumbnailUrl` is the public thumb when a thumbnail exists. Both are `null` when the bucket has no public domain — then call `presign_view` (inline display) or `presign_download` (attachment). S3 view/download presigns cannot be non-expiring. Public CDN cannot force a download.

## Get / patch / delete

- `GET .../files/{fileId}` · `files:read`
- `PATCH .../files/{fileId}` · `files:write` — body `{ tags?, description? }`
- `DELETE .../files/{fileId}` · `files:delete` — Trash (or hard-delete if Trash is off)

## Trash / move

- `POST .../files/trash` · `files:delete` — `{ "keys": ["a.jpg"] }`
- `POST .../files/move` · `files:write` — `{ "moves": [{ "fromKey", "toKey" }] }`

See [Automations & Trash](/docs/api/automations).

## Similar

`GET .../files/{fileId}/similar?limit=20` · `files:read`

Vector neighbors (requires embedding).

## Folders

`POST .../folders` · `files:write`

```json
{ "key": "albums/2026/" }
```

## Upload

A PUT to the bucket does **not** list the file. file.rocks lists from its index. You must complete the upload.

**Agents: use MCP.** Call `presign_upload`, PUT, then `complete_upload`. Do not POST this REST `upload-complete` route from an agent HTTP client (Cloudflare 1010). Guide: [Upload flow](/docs/mcp/upload).

### Presign

`POST .../files/presign-upload` · `files:upload`

```json
{ "key": "inbox/shot.jpg", "contentType": "image/jpeg" }
```

Returns `{ url, key, method: "PUT", headers, next }`. PUT the bytes to `url`.

### Complete (register)

`POST .../files/upload-complete` · `files:upload` (not `files:write`)

```json
{ "key": "inbox/shot.jpg", "size": 12345, "etag": "...", "contentType": "image/jpeg" }
```

After this, `GET .../files` returns the object. The file payload includes `url` / `thumbnailUrl` when the bucket has a public domain — use `url` to display the image. Tags still need `PATCH .../files/{fileId}` (`files:write`).

If the object is already in the bucket, you can call upload-complete / `complete_upload` with the key and skip presign+PUT.

## Presign view / download

`POST .../files/presign-download` · `files:download`

```json
{ "key": "photos/italy.jpg", "as": "view", "purpose": "preview" }
```

or `{ "fileId": "..." }`.

| Field | Values |
|-------|--------|
| `as` | `view` (default, inline display) or `download` (attachment) |
| `purpose` | `preview` (1 hour, default) or `embed` (7 days) |
| `expiresIn` | seconds, 60–604800, optional override |

Returns `{ url, key, method, as, disposition, durable, purpose, expiresIn, expiresAt, note }`.

- `as=view` + `publicDomain` → durable CDN URL (`file.url`). Browser displays the file.
- `as=download` → always a signed attachment URL (even with `publicDomain`). Browser saves the file. Expires.

MCP exposes these as two tools: `presign_view` and `presign_download`. S3-compatible buckets only for signed URLs.
