# Backend API Contract v1.0

UnifiedFiler can run frontend-first with IndexedDB, Local Disk, and Google Drive. When a Host connects a PHP/Node backend, the backend should implement this v1.0 contract so that `BackendApiAdapter` can be reused without custom UI code.

## Endpoint map

Default endpoint root: `/filer`

| Operation | Method | Path | Notes |
|---|---:|---|---|
| list | GET | `/filer/entries?path=/...` | Direct children of a folder |
| search | GET | `/filer/search?path=/...&q=...` | Server-side search |
| read | GET | `/filer/entries/{id}/content` | Returns Blob/binary content |
| upload | POST | `/filer/entries/upload` | `multipart/form-data` with `file`, `path`, `name` |
| createFolder | POST | `/filer/folders` | JSON body with `path`, `name` |
| rename | PATCH | `/filer/entries/{id}` | JSON body with `name` |
| remove | DELETE | `/filer/entries/{id}` | Remove or trash according to backend policy |
| copy | POST | `/filer/entries/{id}/copy` | JSON body with `targetPath`, `overwrite` |
| move | POST | `/filer/entries/{id}/move` | JSON body with `targetPath`, `overwrite` |
| metadata | GET/PATCH | `/filer/entries/{id}/metadata` | Read/update metadata |
| thumbnail | GET | `/filer/entries/{id}/thumbnail` | Thumbnail descriptor or binary |
| exportFile | GET | `/filer/entries/{id}/export` | Optional backend export |

All endpoint paths can be overridden through `BackendApiAdapter({ endpoints: ... })`.

## Request context

UnifiedFiler passes Host scope values as query/body fields and HTTP headers where applicable.

| Field | Header | Purpose |
|---|---|---|
| tenantId | X-Tenant-Id | Multi-tenant boundary |
| appId | X-App-Id | Host app/module boundary |
| userId | X-User-Id | Authenticated user |
| workspaceId | X-Workspace-Id | Workspace/project boundary |
| ownerObjectType | X-Owner-Object-Type | Linked business object type |
| ownerObjectId | X-Owner-Object-Id | Linked business object ID |
| permissionScope | X-Permission-Scope | Backend permission profile |
| contractVersion | X-UnifiedFiler-Contract-Version | Contract version, currently `1.0` |

## Entry shape

A backend entry should return as many of these fields as possible:

```json
{
  "id": "file_001",
  "name": "document.md",
  "path": "/Documents/document.md",
  "parentPath": "/Documents",
  "isFolder": false,
  "mimeType": "text/markdown",
  "size": 1234,
  "createdAt": "2026-06-09T00:00:00.000Z",
  "updatedAt": "2026-06-09T00:00:00.000Z",
  "metadata": { "description": "optional" },
  "tags": ["demo"],
  "permissions": { "role": "owner" },
  "capabilities": {
    "canRead": true,
    "canWrite": true,
    "canRename": true,
    "canDelete": true,
    "canPreview": true,
    "canUpdateMetadata": true
  },
  "thumbnailUrl": null,
  "webUrl": null,
  "workspaceId": "workspace-001",
  "ownerObjectType": "property",
  "ownerObjectId": "P-001"
}
```

## Error shape

Backends should prefer a JSON error body:

```json
{
  "error": "FORBIDDEN",
  "code": "PERMISSION_DENIED",
  "message": "You do not have permission to rename this file.",
  "detail": {}
}
```

## In-browser demo backend

`MemoryApiBackendService` implements the same logical backend methods in the browser, including metadata and thumbnail descriptors, so demos can run without server code.
