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.
| Field | Type | Description |
|---|---|---|
name | String | Server name. Pass it as storageClassName when you create a volume. |
type | String | nfs or volobj (object storage). |
region | String | Region of the server. Volumes on it can only be used in this region. |
ownership | String | platform for a server Quave ONE runs (shared NFS, or the region's platform object storage point), account for a bucket your account connected. |
bucket | String | Account object storage servers only: the bucket. |
basePrefix | String | Account object storage servers only: the key prefix the volumes land under. |
lockOnWrite | Boolean | Account object storage servers only: whether a second writer of the same path gets EBUSY. |
hubUrl | String | Account object storage servers only, when you gave one: your own event hub URL. |
uid | Integer | Account object storage servers only, when you set one: the user id new volumes report as the owner of every file. |
gid | Integer | Account 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
| Field | Type | Description |
|---|---|---|
name | String | Volume (claim) name. |
namespace | String | Account namespace the claim lives in. |
storageClassName | String | Storage Server the volume is on. |
region | String | Region of the volume. |
size | String | Requested size, as a Kubernetes quantity. Nominal on object storage: the volume grows with what you write. |
state | String | active, or pending-purge for an object storage volume removed with a purge delay. |
deletedAt | String | ISO 8601 timestamp of the removal, when pending purge. |
purgeAt | String | ISO 8601 timestamp after which the data is deleted, when pending purge. |
origin | Object | Where 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 parameter | Type | Description |
|---|---|---|
accountId | String | Account ID. Required. |
region | String | Optional 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®ion=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.
| Field | Type | Required | Description |
|---|---|---|---|
accountId | String | Yes | Account ID. |
region | String | Yes | Region to open the server in. |
endpoint | String | Yes | S3-compatible endpoint host, without a scheme (HTTPS is assumed), for example s3.us-east-1.amazonaws.com. |
bucket | String | Yes | Bucket name. |
accessKey | String | Yes | Access key ID with read/write on the bucket. Write-only. |
secretKey | String | Yes | Secret access key. Write-only. |
s3Region | String | No | Signing region of the bucket, when the endpoint needs one (for example OCI outside the tenancy's home region). |
basePrefix | String | No | Key prefix for the volumes inside the bucket. Default: volobj. |
lockOnWrite | Boolean | No | Write exclusion across mounts. Default: true. |
hubUrl | String | No | Your own event hub, wss:// or ws://, with no credentials in it. Omit to use the Quave ONE event hub. |
hubToken | String | No | Token of your own event hub; only with hubUrl. Write-only. |
masterKey | String | No | Your 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. |
uid | Integer | No | User id every file of the server's volumes reports as its owner, 0 to 65535. Default: 1000. |
gid | Integer | No | Group 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.
| Field | Type | Required | Description |
|---|---|---|---|
accountId | String | Yes | Account ID. |
name | String | Yes | Server name, as List Storage Servers returns it. |
region | String | No | Region of the server. The name already identifies it. |
hubToken | String | No | New 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. |
hubUrl | String | No | New URL of your own event hub, wss:// or ws://, with no credentials in it. |
uid | Integer | No | User id new volumes report as the owner of every file, 0 to 65535. |
gid | Integer | No | Group 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.
| Field | Type | Required | Description |
|---|---|---|---|
accountId | String | Yes | Account ID. |
region | String | Yes | Region of the Storage Server. |
name | String | Yes | Volume name: lowercase letters, digits and dashes, starting and ending with a letter or digit, at most 63 characters. |
size | String | Yes | Requested size with a unit: Mi, Gi, Ti, M, G or T (for example 10Gi or 10000M). |
storageClassName | String | Yes | Name 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 parameter | Type | Description |
|---|---|---|
accountId | String | Account ID. Required. |
region | String | Optional 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.
| Field | Type | Required | Description |
|---|---|---|---|
accountId | String | Yes | Account ID. |
name | String | Yes | Volume name. |
region | String | No | Region of the volume. Required only for a volume Quave ONE does not know yet. |
purgeAfterDays | Integer | No | Days 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.
| Field | Type | Required | Description |
|---|---|---|---|
accountId | String | Yes | Account ID. |
name | String | Yes | Volume name. |
region | String | No | Region 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
| Operation | MCP tool | Scope |
|---|---|---|
| List Storage Servers | list-storage-servers | quave:read |
| Connect your own bucket | create-object-storage-server | quave:write:config |
| Update your own bucket | update-object-storage-server | quave:write:config |
| Create a shared volume | create-shared-volume | quave:write:config |
| List shared volumes | list-shared-volumes | quave:read |
| Remove a shared volume | remove-shared-volume | quave:write:dangerous |
| Restore a shared volume | restore-shared-volume | quave:write:config |