Skip to content

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.

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.

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.

Any JSON endpoint accepts pretty=true to indent the response (e.g. GET /v1/configure/volumes?pretty=true); the default is compact.

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

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

POST /v1/configure/{table}
Content-Type: application/json
{ "field": "value", ... }

Creates a new record.

Response: 200 OK with the created JSON object.

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

TablePrimary KeyDescription
accountsidUser accounts
block-apiscodeBlock store API types (read-only)
block-storesidBlock store configurations
meta-storesidMetadata store registrations
providerscodeCloud providers
proxy-groupsidProxy groups
regionsprovider_code, codeProvider regions (composite key)
volumesidVolumes
volume-proxy-groupsvolume_id, proxy_group_idVolume-to-proxy-group associations
volume-tokenstokenVolume access tokens
POST /v1/volumes
Authorization: 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 /v1/volumes/for-token/settings
Authorization: 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 /v1/volumes/{volumeID}/settings
Authorization: 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.

PATCH /v1/volumes/for-token/secret-id
Authorization: Bearer <volume-token>
Content-Type: application/json
{ "secret_id": "xxxxxxxx" }

Registers or updates the encryption secret ID for the volume.

GET /v1/volumes/for-name/{volumeName}/tokens
Authorization: Bearer <account-token>

Returns the list of volume tokens for the named volume.

PATCH /v1/volumes/for-name/{volumeName}/quota
Authorization: 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.

FieldTypeDescription
max_bytesint64Storage quota in bytes, rounded up to a whole block when recorded. 0 leaves the storage quota unchanged.
max_inodesint64Inode 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 /v1/volumes/for-name/{volumeName}
Authorization: Bearer <account-token>

Retires a volume by name.

DELETE /v1/volumes/{volumeID}
Authorization: Bearer <account-token|meta-token>

Retires or cleans a volume by ID.

GET /deploy/install-mount.sh

Returns a shell script that downloads and configures the mount client. No authentication required.

GET /deploy/{channel}/{version}/linux/{arch}/mount.flexfs

Serves the mount client binary. Channels are staging and production. No authentication required.

POST /v1/volumes/stats
Authorization: Bearer <meta-token>
Content-Type: application/json

Accepts volume statistics from metadata servers for billing and metering.

GET /v1/volumes/retired
Authorization: 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 /v1/rate-bins
Authorization: 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.

GET /status

Returns server health status. No authentication required, and no version slug.