Skip to content

Metadata REST API (v2)

Every endpoint except /status and /metrics requires a bearer token. See Authentication for which token each one takes.

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.

This page documents version 2, which is served only at /v2/.... A bare path (no version slug) means version 1, which is deprecated and served only when the metadata server is started with the deprecated v1 routes enabled, so pin /v2/... explicitly in scripts. The /status and /metrics endpoints carry no version slug and are always served. A metadata server that does not serve version 2 answers 404.

Each endpoint takes one of two tokens in an Authorization: Bearer header.

EndpointsToken
/find, /find-old, /analyze/files, /analyze/folders, /analyze/users, /duplicatesA volume token carrying the admin flag
/locks, /sessions, /size-bins, /verify, /missing-objects, and the maintenance endpointsThe metadata server token — the UUID configured with meta.flexfs init creds
/status, /metricsNone

The endpoints that list a volume’s contents return file and directory names together with their owners and permissions, so they are restricted to volume tokens granted the admin flag. Grant it with configure.flexfs:

Terminal window
configure.flexfs create volume-token --volumeID <volume-name> --flags admin --notes "reporting"

The flag is set on a volume token, not on a volume, and it has no effect when the same token is used to mount. See Volume token flags.

find.flexfs, analyze.flexfs and dedup.flexfs read this token from their own credentials files rather than taking it on the command line; see find.flexfs.

The token identifies the volume, so these endpoints do not take a vid / volume-id parameter; a request that supplies one is answered 400.

Where the token is scoped to a subdirectory with a mount path, that subdirectory is the query’s root: base-path resolves beneath it, results are reported relative to it, and the query cannot reach anything above it. Such a token reports on exactly the subtree it would mount.

Terminal window
curl -k -H "Authorization: Bearer <volume-token>" \
"https://<meta-addr>/v2/find?fields=path,size,perm"

The endpoints that report on the server rather than on a volume’s contents take the metadata server’s own token, as the maintenance endpoints do. These still name a volume with vid / volume-id.

Terminal window
curl -k -H "Authorization: Bearer <meta-token>" \
"https://<meta-addr>/v2/sessions"

These parameters are accepted by most endpoints:

ParameterTypeDescription
vid / volume-idstringVolume UUID or name, on the administrative and maintenance endpoints. The two spellings are equivalent, and either accepts a UUID or a volume name; a name is resolved to its UUID before the request runs, and either form is checked against the volumes this server has open — an identifier matching none of them, including a well-formed UUID, is rejected with 400. Required by /locks; optional on the others, where omitting it covers every open volume. Not accepted on the reporting queries, whose volume comes from the token.
base-pathstringBase32-encoded path to scope the query to, relative to the token’s mount path
mount-pathstringThe client’s mount point (plain text, e.g. /mnt/flexfs). Used to interpret symbolic links whose targets are absolute paths — see below.
at-timeuint64Point-in-time in nanoseconds since epoch (for time-travel mounts)
prettyboolOn JSON endpoints, pretty=true indents the response (default is compact). No effect on text endpoints.

A failed request carries its reason as a plain-text body, so a client can show it rather than just a status line:

  • 400 — the caller’s request is at fault: an unparsable, out-of-range, or unrecognized query parameter, a base-path that does not resolve, or a volume identifier matching no open volume. The body names the cause, e.g. validation error: invalid limit parameter: must be between 1 and 1000 or validation error: no such volume: "archive".
  • 401 — the request carried no bearer token, or one the server does not accept: an unknown or revoked volume token, or a value that is not the metadata server’s token. The body says which.
  • 403 — the volume token is valid but does not carry the admin flag, or an API access rule refused the caller’s source address before any handler ran. Access rules apply only on a server whose --accessFile exists; a server with no access file, which is the default, admits every address. Rules name an endpoint by its path template with the version slug removed — /locks for /v2/locks. See API Access Control.
  • 500 — the server failed. The body is empty and the reason is written to the metadata server’s log, since it is not something the caller can act on.
  • 502 — the admin server was reached but refused this metadata server’s own request to validate the volume token — for example an access rule blocking this server’s address, or a route it does not serve — so the token’s validity was never determined. The token is not at fault; the fix is on the admin server (check its access rules and version), not the caller’s credential. The body says so.
  • 503 — the admin server could not be reached to validate a volume token, so whether it is valid is unknown. Retry.

Endpoints that accept base-path (/find, /duplicates, and the three /analyze/* endpoints) follow symbolic links found among its components, including the final one, as long as the link target stays within the volume. Links with relative targets (such as ../data) resolve on their own. Links with absolute targets (such as /mnt/flexfs/data) are written in the client’s namespace, so the server needs the mount-path parameter to translate them; without it, or when the target falls outside the mount, the request fails with 400 Bad Request and a message naming the link. The CLI utilities supply mount-path automatically when run from inside a mount.

GET /v2/analyze/files
Authorization: Bearer <volume-token>

Returns the top files by size, size_bin, or cost within a volume or subtree.

ParameterTypeDefaultDescription
base-pathstringBase32-encoded path prefix
mount-pathstringClient mount point, for resolving absolute symbolic-link targets
at-timeuint64Point-in-time (nanoseconds since epoch)
headerboolfalseInclude column headers
limituint32100Maximum results (1-1000)
order-bystringsizeSort field: size, size_bin, or cost

Response: 200 OK with tab-separated text, one file per line.

GET /v2/analyze/folders
Authorization: Bearer <volume-token>

Returns per-directory recursive size and cost.

ParameterTypeDefaultDescription
base-pathstringBase32-encoded path prefix
mount-pathstringClient mount point, for resolving absolute symbolic-link targets
at-timeuint64Point-in-time (nanoseconds since epoch)
headerboolfalseInclude column headers
max-depthuint320Maximum depth (0 = unlimited)

Response: 200 OK with tab-separated text.

GET /v2/analyze/users
Authorization: Bearer <volume-token>

Returns per-user size and cost.

ParameterTypeDefaultDescription
base-pathstringBase32-encoded path prefix
mount-pathstringClient mount point, for resolving absolute symbolic-link targets
at-timeuint64Point-in-time (nanoseconds since epoch)
headerboolfalseInclude column headers
limituint32100Maximum results (1-1000)
order-bystringcostSort field: size or cost

Response: 200 OK with tab-separated text (UID, size, cost).

GET /v2/find
Authorization: Bearer <volume-token>

Searches the filesystem with filters on inode attributes.

ParameterTypeDescription
base-pathstringBase32-encoded path prefix
mount-pathstringClient mount point, for resolving absolute symbolic-link targets
fieldsstringComma-separated output fields
headerboolInclude column headers
namestringDentry name filter (supports glob)
typestringInode type: b, c, d, f, l, p, s
uiduint32UID filter
giduint32GID filter
inouint64Inode number filter
limituint64Maximum number of results (0 or omit for unlimited)
emptyboolEmpty file/directory filter
sparseboolSparse file filter
permstringRequired permission bits (octal, with or without a leading 0755 and 0755 mean the same thing; max 07777). Matches when (mode & perm-mask) == perm.
perm-maskstringBits of the file mode to test (octal, with or without a leading 0; default 0777, max 07777, must be non-zero)
min-size, max-sizeuint64Byte size range
min-blocks, max-blocksuint64Block count range
min-cost, max-costfloat64Monthly cost range
min-nlink, max-nlinkuint32Hard link count range
min-depth, max-depthuint32Depth range
min-atime, max-atimeuint64Access time range (seconds since epoch)
min-btime, max-btimeuint64Birth time range (seconds since epoch)
min-ctime, max-ctimeuint64Change time range (seconds since epoch)
min-mtime, max-mtimeuint64Modification time range (seconds since epoch)
min-size-bin, max-size-binuint32Size bin range (0-74)

Response: 200 OK with tab-separated text.

GET /v2/find-old
Authorization: Bearer <volume-token>

Lists 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.

ParameterTypeDefaultDescription
coint642 years agoCutoff access time, in seconds since epoch. Files with atime older than this are returned.
limuint64100000Maximum 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.

GET /v2/duplicates
Authorization: Bearer <volume-token>

Returns groups of files that share the same size and block count, which are candidates for deduplication.

ParameterTypeDescription
base-pathstringBase32-encoded path prefix
mount-pathstringClient mount point, for resolving absolute symbolic-link targets
at-timeuint64Point-in-time (nanoseconds since epoch)
limituint64Maximum number of duplicate groups (0 or omit for unlimited). When set, the largest groups by file size are retained.
min-size, max-sizeuint64Byte size range
min-blocks, max-blocksuint64Block 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 /v2/locks
Authorization: Bearer <meta-token>

Lists the volume’s currently held file locks.

ParameterTypeDescription
vid / volume-idstringVolume UUID or name (required)

Response: 200 OK with a JSON array of active lock objects (empty array if the volume holds no locks).

GET /v2/sessions
Authorization: Bearer <meta-token>

Returns the client sessions currently connected to the server.

ParameterTypeDescription
vid / volume-idstringVolume 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:

FieldTypeDescription
idstringSession UUID
remote_addrstringClient remote address
local_addrstringServer-side local address
build_versionstringClient build version
proto_versionstringNegotiated protocol version
commandstringClient command line
kernelstringClient kernel version
cpusuint32Client CPU count
ramuint64Client RAM in bytes
uiduint32Client user ID
giduint32Client group ID
startedstringSession start time
blocks_readuint64Blocks read this reporting period
blocks_writtenuint64Blocks written this reporting period
bytes_readuint64Bytes read this reporting period
bytes_writtenuint64Bytes written this reporting period

Fields with zero or empty values are omitted. The read/write counters reflect the current reporting period and reset periodically.

GET /v2/size-bins
Authorization: Bearer <meta-token>

Returns the volume’s billed storage distributed across activity-based size bins. Each bin is a 30-day age tier reflecting how recently the files’ data was accessed: bin 0 holds data active within the last 30 days, bin 1 data 30–60 days old, and so on up to bin 74.

ParameterTypeDescription
vid / volume-idstringVolume 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 (074) to the total billed size, in bytes, of the files whose data falls in that tier (sparse files counted at their allocated size). A specified volume yields just that one; omitting it yields all open volumes.

GET /v2/missing-objects
Authorization: Bearer <meta-token>

Scans 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.

ParameterTypeDefaultDescription
vid / volume-idstringVolume UUID or name. Omit to scan every open volume.
live-onlyboolfalseRestrict the scan to live block keys
retired-onlyboolfalseRestrict the scan to retired block keys (mutually exclusive with live-only)
concurrencyint16Number of parallel HEAD requests. The default matches the metadata server’s block-store concurrency ceiling; higher values queue on that limit rather than adding parallelism.

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.

StatusMeaning
200Scan ran; results returned keyed by volume ID.
400An invalid parameter: unresolvable volume, live-only and retired-only both set, or a malformed concurrency/boolean value.
401Missing or invalid bearer token.
409A single-volume scan was requested and one is already in progress for it.
500A single-volume scan failed.
GET /v2/verify
Authorization: Bearer <meta-token>

Runs 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.

ParameterTypeDescription
vid / volume-idstringVolume 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.

GET /metrics

Returns Prometheus-format metrics for the metadata server.

GET /status

Returns server health status. Unversioned: it is served whichever API versions this server serves, and there is no /v2/status.

POST /v2/backup
Authorization: Bearer <meta-token>

Writes 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).

ParameterTypeDefaultDescription
deststring<dbFolder>/.backupStaging 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-idstring""A single volume UUID or name. Omit to checkpoint all open volumes.
blockingboolfalseWait 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.

StatusMeaning
200(blocking=true) Checkpoint completed; body reports the number of volumes written.
202Checkpoint started in the background.
400The vid / volume-id value could not be resolved to a volume.
401Missing or invalid bearer token.
409(async only) A conflicting checkpoint is already in progress.
500Checkpoint 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):

Terminal window
curl -fk -X POST \
-H "Authorization: Bearer <meta-token>" \
"https://<meta-addr>/v2/backup?blocking=true"
POST /v2/compact
Authorization: Bearer <meta-token>

Triggers a manual compaction of the metadata database for one or all volumes.

ParameterTypeDefaultDescription
vid / volume-idstringA single volume UUID or name. Omit to compact all open volumes.
blockingboolfalseWait 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.

StatusMeaning
200(blocking=true) Compaction completed; body reports the number of volumes compacted.
202Compaction started in the background.
400The vid / volume-id value could not be resolved to a volume.
401Missing or invalid bearer token.
409(async only) A conflicting compaction is already in progress.
500(blocking=true) Compaction failed.
POST /v2/scrub
Authorization: Bearer <meta-token>

Retires leaked past-EOF block keys for one or all volumes.

ParameterTypeDefaultDescription
vid / volume-idstringA single volume UUID or name. Omit to scrub all open volumes.
blockingboolfalseWait 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.

StatusMeaning
200(blocking=true) Scrub completed; body reports the counts.
202Scrub started in the background.
400The vid / volume-id value could not be resolved to a volume.
401Missing or invalid bearer token.
409(async only) A conflicting scrub is already in progress.
500(blocking=true) Scrub failed.
POST /v2/reconcile
Authorization: Bearer <meta-token>

Checks that every object in the block store is accounted for in the metadata store and removes any that are not.

ParameterTypeDefaultDescription
vid / volume-idstringA 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.
blockingboolfalseWait 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.

StatusMeaning
200(blocking=true) Reconciliation completed; body reports the counts.
202Reconciliation started in the background.
400The vid / volume-id value could not be resolved to a volume.
401Missing or invalid bearer token.
409(async only) A conflicting reconciliation is already in progress.
DELETE /v2/locks
Authorization: Bearer <meta-token>

Deletes held file locks for a volume, optionally scoped to a single inode — the DELETE verb on the /v2/locks resource that GET lists.

ParameterTypeDefaultDescription
vid / volume-idstringVolume UUID or name (required)
inouint640Inode 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).

StatusMeaning
200Locks deleted; body reports the count.
400Missing/unresolvable volume, or an invalid ino.
401Missing or invalid bearer token.
500Deletion failed.