Metadata REST API
The metadata server exposes a REST API alongside its RPC protocol. The REST endpoints serve utilities and monitoring. All query parameters use kebab-case (e.g., volume-id, base-path). Each endpoint responds only to the HTTP method(s) shown below; a request to a valid path with an unsupported method receives 405 Method Not Allowed.
Common Query Parameters
Section titled “Common Query Parameters”These parameters are accepted by most endpoints:
| Parameter | Type | Description |
|---|---|---|
vid / volume-id | string | Volume UUID or name. Required by most endpoints; the volume-keyed and maintenance endpoints make it optional (omit = all open volumes). |
base-path | string | Base32-encoded base path to scope the query |
at-time | uint64 | Point-in-time in nanoseconds since epoch (for time-travel mounts) |
pretty | bool | On JSON endpoints, pretty=true indents the response (default is compact). No effect on text endpoints. |
Endpoints
Section titled “Endpoints”Analyze Files
Section titled “Analyze Files”GET /analyze/filesReturns the top files by size, size_bin, or cost within a volume or subtree.
| Parameter | Type | Default | Description |
|---|---|---|---|
vid / volume-id | string | Volume UUID or name (required) | |
base-path | string | Base32-encoded path prefix | |
at-time | uint64 | Point-in-time (nanoseconds since epoch) | |
header | bool | false | Include column headers |
limit | uint32 | 100 | Maximum results (1-1000) |
order-by | string | cost | Sort field: size, size_bin, or cost |
Response: 200 OK with tab-separated text, one file per line.
Analyze Folders
Section titled “Analyze Folders”GET /analyze/foldersReturns per-directory recursive size and cost.
| Parameter | Type | Default | Description |
|---|---|---|---|
vid / volume-id | string | Volume UUID or name (required) | |
base-path | string | Base32-encoded path prefix | |
at-time | uint64 | Point-in-time (nanoseconds since epoch) | |
header | bool | false | Include column headers |
max-depth | uint32 | 0 | Maximum depth (0 = unlimited) |
Response: 200 OK with tab-separated text.
Analyze Users
Section titled “Analyze Users”GET /analyze/usersReturns per-user size and cost.
| Parameter | Type | Default | Description |
|---|---|---|---|
vid / volume-id | string | Volume UUID or name (required) | |
base-path | string | Base32-encoded path prefix | |
at-time | uint64 | Point-in-time (nanoseconds since epoch) | |
header | bool | false | Include column headers |
limit | uint32 | 100 | Maximum results (1-1000) |
order-by | string | cost | Sort field: size or cost |
Response: 200 OK with tab-separated text (UID, size, cost).
GET /findSearches the filesystem with filters on inode attributes.
| Parameter | Type | Description |
|---|---|---|
vid / volume-id | string | Volume UUID or name (required) |
base-path | string | Base32-encoded path prefix |
fields | string | Comma-separated output fields |
header | bool | Include column headers |
name | string | Dentry name filter (supports glob) |
type | string | Inode type: b, c, d, f, l, p, s |
uid | uint32 | UID filter |
gid | uint32 | GID filter |
ino | uint64 | Inode number filter |
limit | uint64 | Maximum number of results (0 or omit for unlimited) |
empty | bool | Empty file/directory filter |
sparse | bool | Sparse file filter |
perm | string | Required permission bits (octal string, e.g. 0755). Matches when (mode & perm-mask) == perm. |
perm-mask | string | Bits of the file mode to test (octal string, default 0777, max 07777) |
min-size, max-size | uint64 | Byte size range |
min-blocks, max-blocks | uint64 | Block count range |
min-cost, max-cost | float64 | Monthly cost range |
min-nlink, max-nlink | uint32 | Hard link count range |
min-depth, max-depth | uint32 | Depth range |
min-atime, max-atime | uint64 | Access time range (seconds since epoch) |
min-btime, max-btime | uint64 | Birth time range (seconds since epoch) |
min-ctime, max-ctime | uint64 | Change time range (seconds since epoch) |
min-mtime, max-mtime | uint64 | Modification time range (seconds since epoch) |
min-size-bin, max-size-bin | uint32 | Size bin range (0-74) |
Response: 200 OK with tab-separated text.
Find Old
Section titled “Find Old”GET /find-oldLists non-directory files whose access time is older than a cutoff — useful for identifying stale data. The Find endpoint is more capable and covers the same need via its max-atime filter.
| Parameter | Type | Default | Description |
|---|---|---|---|
vid / volume-id | string | Volume UUID or name (required) | |
co | int64 | 2 years ago | Cutoff access time, in seconds since epoch. Files with atime older than this are returned. |
lim | uint64 | 100000 | Maximum number of results |
Response: 200 OK with one line per file in the form size:atime:btime:base32path, where size is the effective size (min(size, blksize × blocks)) and atime/btime are seconds since epoch.
Duplicates
Section titled “Duplicates”GET /duplicatesReturns groups of files that share the same size and block count, which are candidates for deduplication.
| Parameter | Type | Description |
|---|---|---|
vid / volume-id | string | Volume UUID or name (required) |
base-path | string | Base32-encoded path prefix |
at-time | uint64 | Point-in-time (nanoseconds since epoch) |
limit | uint64 | Maximum number of duplicate groups (0 or omit for unlimited). When set, the largest groups by file size are retained. |
min-size, max-size | uint64 | Byte size range |
min-blocks, max-blocks | uint64 | Block count range |
Response: 200 OK with a JSON array of group objects, ordered by size descending then blocks descending. Each group has size (uint64), blocks (uint64), and files (array of {path, ino, nlink, btime} objects). Multiple paths for the same inode (hard links) are included as separate entries. When limit is set, only the largest groups are returned.
GET /locksLists the volume’s currently held file locks.
| Parameter | Type | Description |
|---|---|---|
vid / volume-id | string | Volume UUID or name (required) |
Response: 200 OK with a JSON array of active lock objects (empty array if the volume holds no locks).
Sessions
Section titled “Sessions”GET /sessionsReturns the client sessions currently connected to the server.
| Parameter | Type | Description |
|---|---|---|
vid / volume-id | string | Volume UUID or name. Omit to report every volume. |
Response: 200 OK — a JSON object keyed by volume ID; each value is that volume’s array of session objects (empty if it has no clients). A specified volume yields just that one; omitting it yields all. Each session object:
| Field | Type | Description |
|---|---|---|
id | string | Session UUID |
remote_addr | string | Client remote address |
local_addr | string | Server-side local address |
build_version | string | Client build version |
proto_version | string | Negotiated protocol version |
command | string | Client command line |
kernel | string | Client kernel version |
cpus | uint32 | Client CPU count |
ram | uint64 | Client RAM in bytes |
uid | uint32 | Client user ID |
gid | uint32 | Client group ID |
started | string | Session start time |
blocks_read | uint64 | Blocks read this reporting period |
blocks_written | uint64 | Blocks written this reporting period |
bytes_read | uint64 | Bytes read this reporting period |
bytes_written | uint64 | Bytes written this reporting period |
Fields with zero or empty values are omitted. The read/write counters reflect the current reporting period and reset periodically.
Size Bins
Section titled “Size Bins”GET /size-binsReturns the distribution of files across logarithmic size bins.
| Parameter | Type | Description |
|---|---|---|
vid / volume-id | string | Volume UUID or name. Omit to report every open volume. |
Response: 200 OK — a JSON object keyed by volume ID; each value maps size-bin index (0–74) to file count. A specified volume yields just that one; omitting it yields all open volumes.
Missing Objects
Section titled “Missing Objects”GET /missing-objectsScans block keys and reports any whose backing object is absent from the block store. Each key is verified with a HEAD against the block store.
| Parameter | Type | Default | Description |
|---|---|---|---|
vid / volume-id | string | Volume UUID or name. Omit to scan every open volume. | |
live-only | bool | false | Restrict the scan to live block keys |
retired-only | bool | false | Restrict the scan to retired block keys (mutually exclusive with live-only) |
concurrency | int | 32 | Number of parallel HEAD requests |
Response: 200 OK — a JSON object keyed by volume ID; each value is that volume’s array of entries (empty if none). A specified volume yields just that one; omitting it yields all open volumes. Each entry has kind (missing or error), ino, idx, retired, key, and error (error entries only). In all-volumes mode, a volume whose scan fails (e.g. one already running) is logged and skipped rather than failing the request.
| Status | Meaning |
|---|---|
200 | Scan ran; results returned keyed by volume ID. |
400 | An invalid parameter: unresolvable volume, live-only and retired-only both set, or a malformed concurrency/boolean value. |
409 | A single-volume scan was requested and one is already in progress for it. |
500 | A single-volume scan failed. |
Verify
Section titled “Verify”GET /verifyRuns a read-only integrity check of a volume’s metadata (attr, block-key, and dentry scans plus counter comparisons). This endpoint never modifies data; use the offline CLI (meta.flexfs verify --fix) to repair.
| Parameter | Type | Description |
|---|---|---|
vid / volume-id | string | Volume UUID or name. Omit to verify all open volumes. |
Response: 200 OK — a JSON object keyed by volume ID; each value is that volume’s VerifyReport (per-scan counts plus an overall ok boolean). A specified volume yields just that one; omitting it yields all open volumes.
Metrics
Section titled “Metrics”GET /metricsReturns Prometheus-format metrics for the metadata server.
Status
Section titled “Status”GET /statusReturns server health status.
Maintenance
Section titled “Maintenance”Backup
Section titled “Backup”POST /backupAuthorization: Bearer $META_TOKENWrites a consistent, point-in-time checkpoint of one or all volumes into a staging directory while the server keeps running. The staging directory is safe to rsync offsite. See Maintenance → Online backup for the recommended workflow.
$META_TOKEN is the metadata server’s token (the UUID configured with meta.flexfs init creds).
| Parameter | Type | Default | Description |
|---|---|---|---|
dest | string | <dbFolder>/.backup | Staging directory for the checkpoint. Must be on the same filesystem as --dbFolder for hard-linking, and must not be or contain the data directory. |
vid / volume-id | string | A single volume UUID or name. Omit to checkpoint all open volumes. | |
blocking | bool | false | Wait for the checkpoint and return a summary. See the maintenance note above. |
Response: with blocking=true, 200 OK and body checkpointed N volume(s) (the count distinguishes a real backup from a no-op, e.g. zero open volumes). Otherwise 202 Accepted, no body.
| Status | Meaning |
|---|---|
200 | (blocking=true) Checkpoint completed; body reports the number of volumes written. |
202 | Checkpoint started in the background. |
400 | The vid / volume-id value could not be resolved to a volume. |
401 | Missing or invalid bearer token. |
409 | (async only) A conflicting checkpoint is already in progress. |
500 | Checkpoint failed, or (either mode) dest is or contains the data directory. |
Example — an automated backup that must fail loudly waits for completion (-f fails on non-2xx; self-signed cert, so -k):
curl -fk -X POST \ -H "Authorization: Bearer $META_TOKEN" \ "https://<meta-host>:443/backup?blocking=true"Compact
Section titled “Compact”POST /compactAuthorization: Bearer $META_TOKENTriggers a manual compaction of the metadata database for one or all volumes.
| Parameter | Type | Default | Description |
|---|---|---|---|
vid / volume-id | string | A single volume UUID or name. Omit to compact all open volumes. | |
blocking | bool | false | Wait for the compaction and return a summary. See the maintenance note above. |
Response: with blocking=true, 200 OK and body compacted N volume(s). Otherwise 202 Accepted, no body.
| Status | Meaning |
|---|---|
200 | (blocking=true) Compaction completed; body reports the number of volumes compacted. |
202 | Compaction started in the background. |
400 | The vid / volume-id value could not be resolved to a volume. |
401 | Missing or invalid bearer token. |
409 | (async only) A conflicting compaction is already in progress. |
500 | (blocking=true) Compaction failed. |
POST /scrubAuthorization: Bearer $META_TOKENRetires leaked past-EOF block keys for one or all volumes.
| Parameter | Type | Default | Description |
|---|---|---|---|
vid / volume-id | string | A single volume UUID or name. Omit to scrub all open volumes. | |
blocking | bool | false | Wait for the scrub and return a summary. See the maintenance note above. |
Response: with blocking=true, 200 OK and body retired N leaked block key(s): M inode(s) affected, K volume(s) skipped. Otherwise 202 Accepted, no body.
| Status | Meaning |
|---|---|
200 | (blocking=true) Scrub completed; body reports the counts. |
202 | Scrub started in the background. |
400 | The vid / volume-id value could not be resolved to a volume. |
401 | Missing or invalid bearer token. |
409 | (async only) A conflicting scrub is already in progress. |
500 | (blocking=true) Scrub failed. |
Reconcile
Section titled “Reconcile”POST /reconcileAuthorization: Bearer $META_TOKENChecks that every object in the block store is accounted for in the metadata store and removes any that are not.
| Parameter | Type | Default | Description |
|---|---|---|---|
vid / volume-id | string | A single volume UUID or name. Omit to reconcile all open volumes. When set, objects belonging to other volumes sharing the same block store are left untouched. | |
blocking | bool | false | Wait for the reconciliation and return a summary. See the maintenance note above. |
Response: with blocking=true, 200 OK and body reconciled N object(s): M deleted, K marked for deletion. Otherwise 202 Accepted, no body.
| Status | Meaning |
|---|---|
200 | (blocking=true) Reconciliation completed; body reports the counts. |
202 | Reconciliation started in the background. |
400 | The vid / volume-id value could not be resolved to a volume. |
401 | Missing or invalid bearer token. |
409 | (async only) A conflicting reconciliation is already in progress. |
Delete Locks
Section titled “Delete Locks”DELETE /locksAuthorization: Bearer $META_TOKENDeletes held file locks for a volume, optionally scoped to a single inode — the DELETE verb on the /locks resource that GET lists.
| Parameter | Type | Default | Description |
|---|---|---|---|
vid / volume-id | string | Volume UUID or name (required) | |
ino | uint64 | 0 | Inode to scope the deletion to. 0 or omitted deletes all locks in the volume. |
Response: 200 OK with a plain-text body deleted N lock(s).
| Status | Meaning |
|---|---|
200 | Locks deleted; body reports the count. |
400 | Missing/unresolvable volume, or an invalid ino. |
401 | Missing or invalid bearer token. |
500 | Deletion failed. |