Mounts
Section titled “Mounts”The Mounts API manages persistent FUSE filesystem mounts for connected backends. All mounts are automatically persisted and restored on server restart — there is no separate persistence flag.
GET /api/v1/mounts
Section titled “GET /api/v1/mounts”List all active filesystem mounts. Supports filtering by label via the label query parameter.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
label | query | string | No | Filter mounts by label. Only mounts with this exact label will be returned. |
Response
Section titled “Response”{ "count": 2, "mounts": [ { "id": "mount_550e8400e29b41d4a716446655440000", "backend_id": "backend_a1b2c3d4e5f6", "label": "Photos", "mount_path": "/hoody/mounts/mount_550e8400e29b41d4a716446655440000", "status": "active", "created_at": 1735689600 }, { "id": "mount_660f9500f30c52e5b827557766551111", "backend_id": "backend_g7h8i9j0k1l2", "label": "Work S3", "mount_path": "/hoody/mounts/mount_660f9500f30c52e5b827557766551111", "status": "active", "created_at": 1735776000 } ]}SDK usage
Section titled “SDK usage”const result = await client.files.mounts.list("Photos");GET /api/v1/mounts/{id}
Section titled “GET /api/v1/mounts/{id}”Get detailed information about a specific mount.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Mount ID |
Response
Section titled “Response”{ "id": "mount_550e8400e29b41d4a716446655440000", "backend_id": "backend_a1b2c3d4e5f6", "label": "Photos", "mount_path": "/hoody/mounts/mount_550e8400e29b41d4a716446655440000", "status": "active", "created_at": 1735689600, "vfs_config": {}}SDK usage
Section titled “SDK usage”const details = await client.files.mounts.getDetails("mount_550e8400e29b41d4a716446655440000");POST /api/v1/mounts
Section titled “POST /api/v1/mounts”Create a persistent FUSE filesystem mount for a connected backend. Every mount is permanent by default. To remove a mount, use DELETE /api/v1/mounts/{id}.
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
backend_id | string | Yes | ID of an existing backend connection |
label | string | No | Human-readable label for this mount (e.g., "My NAS", "Work S3", "Photos Backup"). Used by the UI to identify mounts and filter via GET /api/v1/mounts?label=... |
mount_path | string | No | Path for the mount. If omitted, defaults to /hoody/mounts/mount_{uuid}. Relative paths are resolved under the server’s mount directory (/hoody/mounts/ by default) |
vfs_config | object | No | VFS configuration for performance tuning. Supports cache_max_age, cache_max_size, cache_mode (off, minimal, writes, full), and dir_cache_time |
Response
Section titled “Response”{ "success": true, "message": "Mount created successfully", "data": { "id": "mount_550e8400e29b41d4a716446655440000", "backend_id": "backend_a1b2c3d4e5f6", "label": "Photos", "mount_path": "/hoody/mounts/mount_550e8400e29b41d4a716446655440000", "status": "active" }}SDK usage
Section titled “SDK usage”const mount = await client.files.mounts.create({ backend_id: "backend_a1b2c3d4e5f6", label: "Photos", vfs_config: { cache_mode: "writes", cache_max_size: "10G" }});PATCH /api/v1/mounts/{id}
Section titled “PATCH /api/v1/mounts/{id}”Update the VFS configuration for an existing mount. Allows changing cache settings, buffer sizes, and other VFS parameters.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Mount ID |
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
vfs_config | object | Yes | VFS configuration parameters |
Response
Section titled “Response”{ "success": true, "message": "Mount configuration updated"}{ "success": false, "error": "Invalid cache_mode value"}{ "success": false, "error": "Mount not found"}SDK usage
Section titled “SDK usage”await client.files.mounts.update("mount_550e8400e29b41d4a716446655440000", { vfs_config: { cache_mode: "full", cache_max_size: "20G" }});DELETE /api/v1/mounts/{id}
Section titled “DELETE /api/v1/mounts/{id}”Remove a mount and disconnect the FUSE filesystem.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Mount ID |
Response
Section titled “Response”{ "success": true, "message": "Mount removed successfully"}{ "success": false, "error": "Mount not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MOUNT_NOT_FOUND | Mount not found | No mount exists with the specified ID | Verify the mount ID is correct or list all mounts |
SDK usage
Section titled “SDK usage”await client.files.mounts.unmount("mount_550e8400e29b41d4a716446655440000");Advanced Backends
Section titled “Advanced Backends”Advanced backends are composable filesystem layers that add capabilities — caching, chunking, checksumming, aliasing, merging, or in-memory storage — on top of one or more upstream remotes.
POST /api/v1/backends/alias
Section titled “POST /api/v1/backends/alias”Connect to an alias backend. Creates an alias for an existing remote or local path.
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
remote | string | Yes | Remote or path to alias. Can be "myremote:path/to/dir", "myremote:bucket", "myremote:", or "/local/path". Default: "" |
description | string | No | Description of the remote. Default: "" |
Response
Section titled “Response”{ "success": true, "message": "Backend connected successfully", "data": { "id": "backend_aa11bb22cc33", "type": "alias", "backend_type": "alias", "mount_paths": [] }}{ "success": false, "error": "Invalid remote specification"}SDK usage
Section titled “SDK usage”const backend = await client.files.backends.connectAlias({ remote: "myremote:photos", description: "Photo archive alias"});POST /api/v1/backends/cache
Section titled “POST /api/v1/backends/cache”Connect to a cache backend. Caches file data and metadata from a remote for faster repeated access.
Request Body
Section titled “Request Body”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
remote | string | Yes | "" | Remote to cache. Normally should contain a : and a path, e.g. "myremote:path/to/dir" |
description | string | No | "" | Description of the remote |
db_path | string | No | /home/user/.cache/hoody-vfs/cache-backend | Directory to store file structure metadata DB |
db_purge | boolean | No | false | Clear all cached data for this remote on start |
db_wait_time | integer | No | 1 | How long to wait for the DB to be available — 0 is unlimited (seconds) |
chunk_path | string | No | /home/user/.cache/hoody-vfs/cache-backend | Directory to cache chunk files |
chunk_size | string | No | "5242880" | Size of a chunk. Enum: "1M", "5M", "10M" |
chunk_total_size | string | No | "10737418240" | Total size chunks can take on local disk. Enum: "500M", "1G", "10G" |
chunk_clean_interval | integer | No | 60 | How often to perform chunk cleanup (seconds) |
chunk_no_memory | boolean | No | false | Disable in-memory cache for streaming chunks |
workers | integer | No | 4 | How many workers run in parallel to download chunks |
writes | boolean | No | false | Cache file data on writes through the FS |
read_retries | integer | No | 10 | How many times to retry a read from cache storage |
rps | integer | No | -1 | Hard limit on requests per second to source FS (-1 to disable) |
tmp_upload_path | string | No | "" | Directory to keep temporary files until uploaded |
tmp_wait_time | integer | No | 15 | How long files stay in local cache before upload (seconds) |
info_age | integer | No | 21600 | How long to cache file structure information. Enum: "1h", "24h", "48h" (seconds) |
plex_url | string | No | "" | URL of the Plex server |
plex_username | string | No | "" | Username of the Plex user |
plex_password | string | No | "" | Password of the Plex user |
plex_token | string | No | "" | Plex token for authentication (auto set normally) |
plex_insecure | string | No | "" | Skip all certificate verification when connecting to Plex |
Response
Section titled “Response”{ "success": true, "message": "Backend connected successfully", "data": { "id": "backend_aa11bb22cc33", "type": "cache", "backend_type": "cache", "mount_paths": [] }}{ "success": false, "error": "Invalid remote specification"}SDK usage
Section titled “SDK usage”const backend = await client.files.backends.connectCache({ remote: "myremote:photos", description: "Photo archive cache", chunk_size: "10M", chunk_total_size: "10G"});POST /api/v1/backends/chunker
Section titled “POST /api/v1/backends/chunker”Connect to a chunker backend. Transparently splits large files into smaller chunks.
Request Body
Section titled “Request Body”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
remote | string | Yes | "" | Remote to chunk/unchunk, e.g. "myremote:path/to/dir" |
description | string | No | "" | Description of the remote |
chunk_size | string | No | "2147483648" | Files larger than this size will be split into chunks |
name_format | string | No | "*.hoody-vfs_chunk.###" | String format of chunk file names. Placeholders: * (base file name) and # (chunk number) |
start_from | integer | No | 1 | Minimum valid chunk number |
hash_type | string | No | "md5" | How chunker handles hash sums. Enum: "none", "md5", "sha1", "md5all", "sha1all", "md5quick", "sha1quick" |
meta_format | string | No | "simplejson" | Format of metadata object. Enum: "none", "simplejson" |
transactions | string | No | "rename" | How chunker handles temporary files during transactions. Enum: "rename", "norename", "auto" |
fail_hard | boolean | No | false | How chunker handles files with missing or invalid chunks. Enum: "true", "false" |
Response
Section titled “Response”{ "success": true, "message": "Backend connected successfully", "data": { "id": "backend_aa11bb22cc33", "type": "chunker", "backend_type": "chunker", "mount_paths": [] }}{ "success": false, "error": "Invalid remote specification"}SDK usage
Section titled “SDK usage”const backend = await client.files.backends.connectChunker({ remote: "myremote:large-files", description: "Split large files into chunks", chunk_size: "2147483648", hash_type: "sha1"});POST /api/v1/backends/combine
Section titled “POST /api/v1/backends/combine”Connect to a combine backend. Combines several remotes into a single directory tree.
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
upstreams | string | Yes | Upstreams for combining in the form dir=remote:path dir2=remote2:path. Embedded spaces require quotes |
description | string | No | Description of the remote. Default: "" |
Response
Section titled “Response”{ "success": true, "message": "Backend connected successfully", "data": { "id": "backend_aa11bb22cc33", "type": "combine", "backend_type": "combine", "mount_paths": [] }}{ "success": false, "error": "Invalid upstreams specification"}SDK usage
Section titled “SDK usage”const backend = await client.files.backends.connectCombine({ upstreams: "photos=myremote:photos videos=myremote:videos", description: "Combined media tree"});POST /api/v1/backends/hasher
Section titled “POST /api/v1/backends/hasher”Connect to a hasher backend. Provides better checksums for other remotes.
Request Body
Section titled “Request Body”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
remote | string | Yes | "" | Remote to cache checksums for (e.g. myRemote:path) |
description | string | No | "" | Description of the remote |
hashes | string | No | ["md5","sha1"] | Comma-separated list of supported checksum types |
max_age | integer | No | 0 | Maximum time to keep checksums in cache (0 = no cache, off = cache forever). (seconds) |
auto_size | string | No | "0" | Auto-update checksum for files smaller than this size (disabled by default) |
Response
Section titled “Response”{ "success": true, "message": "Backend connected successfully", "data": { "id": "backend_aa11bb22cc33", "type": "hasher", "backend_type": "hasher", "mount_paths": [] }}{ "success": false, "error": "Invalid remote specification"}SDK usage
Section titled “SDK usage”const backend = await client.files.backends.connectHasher({ remote: "myremote:data", description: "Hashed checksums for data remote", hashes: "md5,sha1,sha256"});POST /api/v1/backends/local
Section titled “POST /api/v1/backends/local”Connect to a local backend backed by a local disk path.
Request Body
Section titled “Request Body”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
description | string | No | "" | Description of the remote |
encoding | string | No | "33554434" | The encoding for the backend |
case_insensitive | boolean | No | false | Force the filesystem to report itself as case insensitive |
case_sensitive | boolean | No | false | Force the filesystem to report itself as case sensitive |
links | boolean | No | false | Translate symlinks to/from regular files with a .hoody-vfslink extension |
copy_links | boolean | No | false | Follow symlinks and copy the pointed-to item |
skip_links | boolean | No | false | Don’t warn about skipped symlinks |
zero_size_links | boolean | No | false | Assume the Stat size of links is zero (deprecated) |
one_file_system | boolean | No | false | Don’t cross filesystem boundaries (Unix/macOS only) |
nounc | boolean | No | false | Disable UNC (long path names) conversion on Windows. Enum: "true" |
no_check_updated | boolean | No | false | Don’t check if files change during upload |
no_set_modtime | boolean | No | false | Disable setting modtime after upload |
no_sparse | boolean | No | false | Disable sparse files for multi-thread downloads |
no_preallocate | boolean | No | false | Disable preallocation of disk space for transferred files |
no_clone | boolean | No | false | Disable reflink cloning for server-side copies |
unicode_normalization | boolean | No | false | Apply unicode NFC normalization to paths and filenames |
time_type | string | No | "0" | Set what kind of time is returned. Enum: "mtime", "atime", "btime", "ctime" |
Response
Section titled “Response”{ "success": true, "message": "Backend connected successfully", "data": { "id": "backend_aa11bb22cc33", "type": "local", "backend_type": "local", "mount_paths": [] }}{ "success": false, "error": "Invalid local backend configuration"}SDK usage
Section titled “SDK usage”const backend = await client.files.backends.connectLocal({ description: "Local data directory", no_preallocate: true});POST /api/v1/backends/memory
Section titled “POST /api/v1/backends/memory”Connect to a memory backend — an in-memory object storage system. Data is lost when the server restarts.
Request Body
Section titled “Request Body”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
description | string | No | "" | Description of the remote |
Response
Section titled “Response”{ "success": true, "message": "Backend connected successfully", "data": { "id": "backend_aa11bb22cc33", "type": "memory", "backend_type": "memory", "mount_paths": [] }}{ "success": false, "error": "Invalid memory backend configuration"}SDK usage
Section titled “SDK usage”const backend = await client.files.backends.connectMemory({ description: "Ephemeral scratch space"});POST /api/v1/backends/union
Section titled “POST /api/v1/backends/union”Connect to a union backend. Merges the contents of several upstream filesystems using configurable policies.
Request Body
Section titled “Request Body”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
upstreams | string | Yes | "" | Space-separated list of upstreams. Can be 'upstreama:test/dir upstreamb:' or quoted paths |
description | string | No | "" | Description of the remote |
search_policy | string | No | "ff" | Policy to choose upstream on SEARCH category |
create_policy | string | No | "epmfs" | Policy to choose upstream on CREATE category |
action_policy | string | No | "epall" | Policy to choose upstream on ACTION category |
cache_time | integer | No | 120 | Cache time of usage and free space (seconds). Only useful with path-preserving policies |
min_free_space | string | No | "1073741824" | Minimum viable free space for lfs/eplfs policies |
Response
Section titled “Response”{ "success": true, "message": "Backend connected successfully", "data": { "id": "backend_aa11bb22cc33", "type": "union", "backend_type": "union", "mount_paths": [] }}{ "success": false, "error": "Invalid upstreams specification"}SDK usage
Section titled “SDK usage”const backend = await client.files.backends.connectUnion({ upstreams: "primary:fast-cdn secondary:bulk-storage", description: "Merged storage union", create_policy: "epmfs", search_policy: "ff"});