Admin REST API
The admin server exposes a REST API over HTTPS (port 443 by default). All endpoints that modify state require a Bearer token in the Authorization header.
Versioning
Section titled “Versioning”Every endpoint below is served at both its versioned path (/v1/volumes) and its bare path (/volumes); a bare path always resolves to v1. Pin the versioned path in scripts and new integrations. The /deploy/ tree and the /status health check are exempt and are only ever served unversioned.
Authentication
Section titled “Authentication”All /v1/configure/ endpoints require an account token, as do POST /v1/volumes and the /v1/volumes/for-name/ endpoints. Volume-scoped endpoints (/v1/volumes/for-token/) accept a volume token. Meta-server endpoints (/v1/volumes/stats, /v1/volumes/retired, /v1/rate-bins, and /v1/volumes/{volumeID}/settings) accept a meta store token. DELETE /v1/volumes/{volumeID} accepts either an account token or a meta store token.
Authorization: Bearer <token>Tokens decide who a caller is. Where an access file is in use, a whitelist also decides where it may call from, and a request from an address no rule admits is answered 403 before the token is looked at. Rules name an endpoint by its path template with the /v1 slug removed — /volumes/stats for /v1/volumes/stats. See API Access Control.
Pretty-printing
Section titled “Pretty-printing”Any JSON endpoint accepts pretty=true to indent the response (e.g. GET /v1/configure/volumes?pretty=true); the default is compact.
Configuration CRUD Endpoints
Section titled “Configuration CRUD Endpoints”These endpoints provide generic CRUD operations on all admin resource tables. The {table} parameter corresponds to the API name of the resource (e.g., accounts, volumes, block-stores).
List Resources
Section titled “List Resources”GET /v1/configure/{table}?key=value&...Returns a JSON array of all records in the table. Query parameters are used as filters.
Response: 200 OK with JSON array.
Get Resource
Section titled “Get Resource”GET /v1/configure/{table}/{id}GET /v1/configure/{table}/{id1}/{id2}Returns a single record by primary key. Composite-key resources (e.g., regions) use the two-ID form.
Response: 200 OK with JSON object.
Create Resource
Section titled “Create Resource”POST /v1/configure/{table}Content-Type: application/json
{ "field": "value", ... }Creates a new record.
Response: 200 OK with the created JSON object.
Update Resource
Section titled “Update Resource”PUT /v1/configure/{table}/{id}PUT /v1/configure/{table}/{id1}/{id2}Content-Type: application/json
{ "field": "new_value", ... }Updates an existing record. Only provided fields are modified.
Response: 204 No Content.
Delete Resource
Section titled “Delete Resource”DELETE /v1/configure/{table}/{id}DELETE /v1/configure/{table}/{id1}/{id2}Deletes a record. For volumes, this sets the retired_at timestamp rather than removing the row.
Response: 204 No Content.
Available Tables
Section titled “Available Tables”| Table | Primary Key | Description |
|---|---|---|
accounts | id | User accounts |
block-apis | code | Block store API types (read-only) |
block-stores | id | Block store configurations |
meta-stores | id | Metadata store registrations |
providers | code | Cloud providers |
proxy-groups | id | Proxy groups |
regions | provider_code, code | Provider regions (composite key) |
volumes | id | Volumes |
volume-proxy-groups | volume_id, proxy_group_id | Volume-to-proxy-group associations |
volume-tokens | token | Volume access tokens |
Volume Endpoints
Section titled “Volume Endpoints”Create Volume
Section titled “Create Volume”POST /v1/volumesAuthorization: Bearer <account-token>Content-Type: application/json
{ "name": "<volume-name>", "provider": "aws", "region": "<region>", "block_api": "s3", "block_size": 4194304, "max_bytes": 3221225472}Creates a volume. Used by the CSI driver for dynamic provisioning.
The volume must be placed either by naming a provider, region and block API — in which case the server picks a matching block store and meta store — or by giving meta_store and block_store IDs directly. A request supplying neither is answered 400. block_api defaults to s3 when the provider is aws; for every other provider it must be given.
max_bytes and max_inodes set the initial quotas, 0 meaning unlimited. The byte figure is converted using the volume’s block size, so the quota in force is the rounded-up block count reported back in the response.
A repeated request for a name that already has a live volume returns that volume rather than creating a second one, which is what makes a retried provisioning call safe. A name still held by a retired volume is answered 409 instead, until that volume’s retention period has elapsed and it is cleaned up.
Get Volume Settings (by token)
Section titled “Get Volume Settings (by token)”GET /v1/volumes/for-token/settingsAuthorization: Bearer <volume-token>Returns the volume settings for the token’s associated volume, including block size, compression, encryption, retention, mount flags, and proxy group addresses.
Get Volume Settings (by ID)
Section titled “Get Volume Settings (by ID)”GET /v1/volumes/{volumeID}/settingsAuthorization: Bearer <meta-token>Returns the same volume settings as the by-token form above, addressed by volume ID instead of by volume token. This form requires the meta store token of the metadata server that owns the volume; it is used by metadata servers, which hold volume IDs rather than volume tokens. A token that is not the volume’s assigned meta store token is answered 401, and an unknown volume ID 404.
Update Secret ID (by token)
Section titled “Update Secret ID (by token)”PATCH /v1/volumes/for-token/secret-idAuthorization: Bearer <volume-token>Content-Type: application/json
{ "secret_id": "xxxxxxxx" }Registers or updates the encryption secret ID for the volume.
Get Volume Tokens (by name)
Section titled “Get Volume Tokens (by name)”GET /v1/volumes/for-name/{volumeName}/tokensAuthorization: Bearer <account-token>Returns the list of volume tokens for the named volume.
Update Volume Quota (by name)
Section titled “Update Volume Quota (by name)”PATCH /v1/volumes/for-name/{volumeName}/quotaAuthorization: Bearer <account-token>Content-Type: application/json
{ "max_bytes": 3221225472, "max_inodes": 0}Ensures a volume’s quotas are at least the given figures. Backs CSI volume expansion.
Volume creation (POST /v1/volumes) accepts the same two fields, where they set the initial quotas; 0 means unlimited there. In both cases the byte figure is converted using the volume’s block size, so the quota that ends up in force is the rounded-up block count reported back in the response.
| Field | Type | Description |
|---|---|---|
max_bytes | int64 | Storage quota in bytes, rounded up to a whole block when recorded. 0 leaves the storage quota unchanged. |
max_inodes | int64 | Inode quota. 0 leaves the inode quota unchanged. |
Quotas only grow through this endpoint: it ensures a volume allows at least the figures given. A value the volume already satisfies leaves the quota unchanged and responds 200 with the figure in force, so a caller that is behind on the volume’s real size does not fail. To reduce a quota, set it directly with configure.flexfs update volume --maxBlocks/--maxInodes.
A volume with no quota in a dimension is refused with 400 for that dimension: there is no limit to raise, and the unlimited sentinel is not a figure a caller can meaningfully record as a capacity.
Responds 200 with the volume identity and the quota now in force:
{ "id": "992467d9-1f45-439d-86e1-2bbb253711c6", "name": "pvc-76021e89-28ed-44d6-82be-34bc4e23a5bb", "max_blocks": 768, "max_bytes": 3221225472, "max_inodes": 0}Returns 404 for an unknown or retired volume name, and 401 for a token that is not an account token.
Delete Volume (by name)
Section titled “Delete Volume (by name)”DELETE /v1/volumes/for-name/{volumeName}Authorization: Bearer <account-token>Retires a volume by name.
Delete Volume (by ID)
Section titled “Delete Volume (by ID)”DELETE /v1/volumes/{volumeID}Authorization: Bearer <account-token|meta-token>Retires or cleans a volume by ID.
Deploy Endpoints
Section titled “Deploy Endpoints”Install Script
Section titled “Install Script”GET /deploy/install-mount.shReturns a shell script that downloads and configures the mount client. No authentication required.
Binary Files
Section titled “Binary Files”GET /deploy/{channel}/{version}/linux/{arch}/mount.flexfsServes the mount client binary. Channels are staging and production. No authentication required.
Meta-Server Endpoints
Section titled “Meta-Server Endpoints”Post Volume Stats
Section titled “Post Volume Stats”POST /v1/volumes/statsAuthorization: Bearer <meta-token>Content-Type: application/jsonAccepts volume statistics from metadata servers for billing and metering.
Get Retired Volumes
Section titled “Get Retired Volumes”GET /v1/volumes/retiredAuthorization: Bearer <meta-token>Returns the IDs of volumes that have been retired but not yet cleaned, for the authenticated metadata server. There is no time window — a volume appears here until its cleanup completes.
Response: 200 OK with a JSON array of volume-ID strings.
Get Rate Bins
Section titled “Get Rate Bins”GET /v1/rate-binsAuthorization: Bearer <meta-token>Proxies rate bin data from the stat server. Returns a JSON object mapping size bin numbers (0-127) to per-GiB monthly dollar rates ($/GiB/month). An admin server with no stat server credentials reports a single zero rate, so cost is reported as zero instead of failing. Used by metadata servers to compute the cost field in analyze.flexfs and find.flexfs. See Cost and Rate Bin in the glossary.
Status
Section titled “Status”GET /statusReturns server health status. No authentication required, and no version slug.