Skip to main content

Shared Volumes API

The Shared Volumes API lets you manage Shared Storage programmatically: list the Storage Servers your account can create volumes on, connect your own S3-compatible bucket as an object storage Storage Server and update it later (hub token, hub URL, file owner), and create, list, remove, and restore shared volumes. A shared volume can be mounted by app environments (see useNfsVolume in the App Env API or the MCP tool update-app-env-volume) and by Agent Sandboxes (volumeName).

Make sure to read the Get Started document to understand how the API works.

Note: These endpoints accept user tokens, and MCP or OAuth tokens carrying the scopes documented per operation. Environment tokens are not accepted: shared volumes belong to the account, not to an environment.

Every request must include accountId, and the account must have Shared Storage enabled (contact support to enable it); otherwise the API answers 403. Read operations require account membership; create, update, remove, and restore operations require an account Admin.

Storage Server object​

A Storage Server is the backend (a Kubernetes StorageClass) a shared volume lives on.

FieldTypeDescription
nameStringServer name. Pass it as storageClassName when you create a volume.
typeStringnfs or volobj (object storage).
regionStringRegion of the server. Volumes on it can only be used in this region.
ownershipStringplatform for a server Quave ONE runs (shared NFS, or the region's platform object storage point), account for a bucket your account connected.
bucketStringAccount object storage servers only: the bucket.
basePrefixStringAccount object storage servers only: the key prefix the volumes land under.
lockOnWriteBooleanAccount object storage servers only: whether a second writer of the same path gets EBUSY.
hubUrlStringAccount object storage servers only, when you gave one: your own event hub URL.
uidIntegerAccount object storage servers only, when you set one: the user id new volumes report as the owner of every file.
gidIntegerAccount object storage servers only, when you set one: the group id new volumes report as the owner of every file.

Credentials (access key, secret key, hub token, master key) are never returned, and the bucket of the Quave ONE platform point is never shown.

Shared volume object​

FieldTypeDescription
nameStringVolume (claim) name.
namespaceStringAccount namespace the claim lives in.
storageClassNameStringStorage Server the volume is on.
regionStringRegion of the volume.
sizeStringRequested size, as a Kubernetes quantity. Nominal on object storage: the volume grows with what you write.
stateStringactive, or pending-purge for an object storage volume removed with a purge delay.
deletedAtStringISO 8601 timestamp of the removal, when pending purge.
purgeAtStringISO 8601 timestamp after which the data is deleted, when pending purge.
originObjectWhere the volume came from. A sandbox volume has kind: "sandbox" and its sandboxId.

List Storage Servers​

Send a GET request to /api/public/v1/storage-servers. Requires the quave:read scope.

Query parameterTypeDescription
accountIdStringAccount ID. Required.
regionStringOptional region filter.

The list contains the account's own servers, the shared NFS servers of the account's regions and, when object storage volumes are enabled on the account, the Quave ONE platform object storage point of each of those regions that has one.

curl -X GET \
-H 'Authorization: YOUR_TOKEN' \
'https://api.quave.cloud/api/public/v1/storage-servers?accountId=ACCOUNT_ID&region=us-5'

Example response:

{
"accountId": "ACCOUNT_ID",
"servers": [
{
"name": "volobj-us-5",
"type": "volobj",
"region": "us-5",
"ownership": "platform"
},
{
"name": "volobj-us-5-ACCOUNT_ID",
"type": "volobj",
"region": "us-5",
"ownership": "account",
"bucket": "my-bucket",
"basePrefix": "volobj",
"lockOnWrite": true
}
]
}

Connect your own bucket​

Send a POST request to /api/public/v1/storage-server/object-storage/create. Requires the quave:write:config scope and an account Admin. The account needs object storage volumes enabled (contact support; otherwise 403), and the region must support object storage volumes (otherwise 400); nothing is created in either case.

FieldTypeRequiredDescription
accountIdStringYesAccount ID.
regionStringYesRegion to open the server in.
endpointStringYesS3-compatible endpoint host, without a scheme (HTTPS is assumed), for example s3.us-east-1.amazonaws.com.
bucketStringYesBucket name.
accessKeyStringYesAccess key ID with read/write on the bucket. Write-only.
secretKeyStringYesSecret access key. Write-only.
s3RegionStringNoSigning region of the bucket, when the endpoint needs one (for example OCI outside the tenancy's home region).
basePrefixStringNoKey prefix for the volumes inside the bucket. Default: volobj.
lockOnWriteBooleanNoWrite exclusion across mounts. Default: true.
hubUrlStringNoYour own event hub, wss:// or ws://, with no credentials in it. Omit to use the Quave ONE event hub.
hubTokenStringNoToken of your own event hub; only with hubUrl. Write-only.
masterKeyStringNoYour own master key, 64 hexadecimal characters (openssl rand -hex 32). Omit to have one generated; a member with the Secrets Access role can reveal it later on the Shared Storage page. Write-only.
uidIntegerNoUser id every file of the server's volumes reports as its owner, 0 to 65535. Default: 1000.
gidIntegerNoGroup id every file of the server's volumes reports as its owner, 0 to 65535. Default: 1000.

The credential goes to the region's cluster and is never shown again. The response is the new Storage Server, answered with 201. uid and gid are returned once set.

curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"accountId": "ACCOUNT_ID",
"region": "us-5",
"endpoint": "s3.us-east-1.amazonaws.com",
"bucket": "my-bucket",
"accessKey": "ACCESS_KEY",
"secretKey": "SECRET_KEY"
}' \
https://api.quave.cloud/api/public/v1/storage-server/object-storage/create

Example response:

{
"success": true,
"server": {
"name": "volobj-us-5-ACCOUNT_ID",
"type": "volobj",
"region": "us-5",
"ownership": "account",
"bucket": "my-bucket",
"basePrefix": "volobj",
"lockOnWrite": true
}
}

Update your own bucket​

Send a POST request to /api/public/v1/storage-server/object-storage/update. Requires the quave:write:config scope and an account Admin, and the account needs object storage volumes enabled (otherwise 403). Only an object storage server your account connected (ownership: "account") can be updated: the Quave ONE platform point answers 403, an NFS server 400, and a name your account does not own 404.

FieldTypeRequiredDescription
accountIdStringYesAccount ID.
nameStringYesServer name, as List Storage Servers returns it.
regionStringNoRegion of the server. The name already identifies it.
hubTokenStringNoNew token of your own event hub. Only for a server that uses its own hub: a hubUrl already stored or given in the same request (otherwise 400). Write-only.
hubUrlStringNoNew URL of your own event hub, wss:// or ws://, with no credentials in it.
uidIntegerNoUser id new volumes report as the owner of every file, 0 to 65535.
gidIntegerNoGroup id new volumes report as the owner of every file, 0 to 65535.

Send at least one of hubToken, hubUrl, uid or gid (otherwise 400). A field you leave out keeps its current value.

  • Hub token: always accepted. The new token replaces the old one in the region's cluster. A running mount keeps the token it read when it mounted, so re-publish each volume to pick up the new token: restart the pods of the app environment that mounts it, or pause and resume the sandbox.
  • Hub URL: refused with 409 (and the cluster's message) while your account has object storage volumes in that region, because every volume records the hub it was created with. Move or remove those volumes first.
  • uid/gid: apply to volumes created afterwards; existing volumes keep the owner they were created with.

The response is the updated Storage Server, answered with 200. The token is never returned.

curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"accountId": "ACCOUNT_ID",
"name": "volobj-us-5-ACCOUNT_ID",
"hubToken": "NEW_HUB_TOKEN",
"uid": 1001,
"gid": 1001
}' \
https://api.quave.cloud/api/public/v1/storage-server/object-storage/update

Example response:

{
"success": true,
"server": {
"name": "volobj-us-5-ACCOUNT_ID",
"type": "volobj",
"region": "us-5",
"ownership": "account",
"bucket": "my-bucket",
"basePrefix": "volobj",
"lockOnWrite": true,
"hubUrl": "wss://hub.example.com",
"uid": 1001,
"gid": 1001
}
}

A hub URL change while the account has volumes in the region:

{
"error": "Event hub URL in use",
"details": "MESSAGE_FROM_THE_CLUSTER"
}

Create a shared volume​

Send a POST request to /api/public/v1/shared-volume/create. Requires the quave:write:config scope and an account Admin.

FieldTypeRequiredDescription
accountIdStringYesAccount ID.
regionStringYesRegion of the Storage Server.
nameStringYesVolume name: lowercase letters, digits and dashes, starting and ending with a letter or digit, at most 63 characters.
sizeStringYesRequested size with a unit: Mi, Gi, Ti, M, G or T (for example 10Gi or 10000M).
storageClassNameStringYesName of a Storage Server the account can use in the region, as List Storage Servers returns it.

The response is the created volume, answered with 201. A storageClassName the account cannot use in that region answers 400, an object storage server while object storage volumes are off on the account answers 403, and an account without a cluster namespace yet answers 409.

curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"accountId": "ACCOUNT_ID",
"region": "us-5",
"name": "datasets",
"size": "10Gi",
"storageClassName": "volobj-us-5"
}' \
https://api.quave.cloud/api/public/v1/shared-volume/create

Example response:

{
"success": true,
"volume": {
"name": "datasets",
"namespace": "ACCOUNT_NAMESPACE",
"storageClassName": "volobj-us-5",
"region": "us-5",
"size": "10Gi",
"state": "active"
}
}

List shared volumes​

Send a GET request to /api/public/v1/shared-volumes. Requires the quave:read scope.

Query parameterTypeDescription
accountIdStringAccount ID. Required.
regionStringOptional region filter.

The list reflects the storage backends right now, including object storage volumes pending purge.

curl -X GET \
-H 'Authorization: YOUR_TOKEN' \
'https://api.quave.cloud/api/public/v1/shared-volumes?accountId=ACCOUNT_ID'

Remove a shared volume​

Send a POST request to /api/public/v1/shared-volume/remove. Requires the quave:write:dangerous scope and an account Admin.

FieldTypeRequiredDescription
accountIdStringYesAccount ID.
nameStringYesVolume name.
regionStringNoRegion of the volume. Required only for a volume Quave ONE does not know yet.
purgeAfterDaysIntegerNoDays to keep an object storage volume restorable (default 7, maximum 3650). 0 purges now and answers 409 while a container still mounts the volume. NFS volumes are deleted at once.
curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"accountId": "ACCOUNT_ID",
"name": "datasets",
"purgeAfterDays": 14
}' \
https://api.quave.cloud/api/public/v1/shared-volume/remove

Restore a shared volume​

Send a POST request to /api/public/v1/shared-volume/restore. Requires the quave:write:config scope and an account Admin.

FieldTypeRequiredDescription
accountIdStringYesAccount ID.
nameStringYesVolume name.
regionStringNoRegion of the volume.

The volume comes back with the same name and data, and the pending purge is dropped. After the purge deadline the API answers 410; while the old claim is still terminating it answers 409 (retry).

curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"accountId": "ACCOUNT_ID",
"name": "datasets"
}' \
https://api.quave.cloud/api/public/v1/shared-volume/restore

MCP tools​

OperationMCP toolScope
List Storage Serverslist-storage-serversquave:read
Connect your own bucketcreate-object-storage-serverquave:write:config
Update your own bucketupdate-object-storage-serverquave:write:config
Create a shared volumecreate-shared-volumequave:write:config
List shared volumeslist-shared-volumesquave:read
Remove a shared volumeremove-shared-volumequave:write:dangerous
Restore a shared volumerestore-shared-volumequave:write:config