Skip to main content

Volumes

Create, manage, and share code/data volumes: the durable storage your workspaces and jobs work in. A project's volume has two halves that mount together: a git-versioned code half and a per-file versioned data half. A volume created as shared holds the data half only (its code is absent); a project's volume keeps its code when it is shared, or kept after its project is deleted, read-only. Code is written only in a project's own volume, in its project's workspaces; wherever a project's volume is shared, its code is read-only, and a write to a shared volume's code is refused with 403. Every workspace and job run in a project mounts the project's volume at /volumes/local/<name>/{code,data}, and only the shared volumes chosen for it (sharedVolumeIds on the workspace or job) at /volumes/shared/<name>/{code,data}. When a volume's owner takes it away from a user (unshares it, or makes it private), it is dropped from that user's workspaces and jobs, and the user's reads and writes of it are refused at once. A workspace's data shows each file's latest version as of the workspace's start and its last Sync; new versions saved elsewhere appear at its next Sync or start. A job run or an app opens data at the latest version of each file.

A volume's scope is local (belongs to a project) or shared (usable across projects). A volume's name is unique among its owner's volumes of the same scope; a project's volume takes the project's name, which is unique among the organization's projects and volumes.

All endpoints require authentication via X-API-Key header and the appropriate scope.


Volume Object​

{
"_id": "vol_def001",
"name": "training-data",
"scope": "local",
"projectId": "proj_abc123",
"organizationId": "org_xyz",
"owner": "user_456",
"description": "Dataset and code for ML model training",
"code": {
"filesystemType": "github",
"repoUrl": "git@github.com:my-org/training.git",
"branch": "main",
"initialized": false
},
"data": {
"latestVersion": 0,
"lastVersionAt": "2025-02-01T14:22:00Z"
},
"isShared": false,
"sharedWith": [
{ "userId": "user_789" }
],
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-02-01T14:22:00Z"
}

A shared volume has no code. The code.filesystemType is either strongly (a platform-hosted git repository) or github (backed by an external GitHub repository, with repoUrl, optional branch, and an optional sshKeyId for a private repo). code.initialized is true once a strongly volume's repository has been created. projectId is set only on local volumes. sharedWith (read and write) and sharedReaders (read only) list the users the volume is shared with as { userId, role? } entries; they are absent until the volume is shared.

The data half is versioned per file, so there is no volume-wide data version number (data.latestVersion stays 0); data.lastVersionAt is when a file in it last changed. List its files with the data files endpoint to see each file's current version.


GET /api/v1/volumes​

List volumes accessible to the authenticated user.

Scope: volumes:read

Query Parameters

ParameterTypeRequiredDescription
scopestringNoFilter by scope: local or shared
projectIdstringNoFilter by project ID
limitintegerNoNumber of results to return (default: 50, max: 200)
cursorstringNometa.nextCursor of the previous page; omit for the first page

Response 200 OK

{
"data": [
{
"_id": "vol_def001",
"name": "training-data",
"scope": "local",
"projectId": "proj_abc123",
"organizationId": "org_xyz",
"owner": "user_456",
"description": "Dataset and code for ML model training",
"code": {
"filesystemType": "github",
"repoUrl": "git@github.com:my-org/training.git",
"branch": "main",
"initialized": false
},
"data": {
"latestVersion": 0,
"lastVersionAt": "2025-02-01T14:22:00Z"
},
"isShared": false,
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-02-01T14:22:00Z"
}
],
"meta": {
"total": 6,
"limit": 50,
"nextCursor": null,
"requestId": "req_abc123"
}
}

GET /api/v1/volumes/available-shared​

The shared volumes you may choose for a workspace or job, the ids you pass as its sharedVolumeIds: volumes created as shared, and other projects' volumes their owners shared, that you own, were granted (read & write or read only), or that are shared to all users (on a multi-tenant platform, all users of your organization). Paged, as the workspace's Volumes tab and the create forms list them.

Scope: volumes:read

Query parameterTypeDescription
projectIdstringThe project the workspace or job is in: its own volume is left out (it always mounts). An unknown project is 404
qstringName contains
sortstringname (default), createdAt or updatedAt
sortDirstringasc (default) or desc
pagenumberPage, from 1
pageSizenumber1 to 100 (default 10)
{
"total": 7,
"page": 1,
"pageSize": 10,
"items": [
{
"_id": "zxgy6r6nxmffc3kxs",
"name": "team-reference",
"mountPath": "/volumes/shared/team-reference",
"ownerName": "Strongly Demo",
"access": "read-only",
"isProjectVolume": false
}
]
}

access is owner, read-write or read-only. Choose volumes with sharedVolumeIds when you create or update a workspace (/api/v1/workspaces) or job (/api/v1/jobs).


POST /api/v1/volumes​

Create a new volume. The usual one to create is a shared volume, which holds data only: send no code (it is refused with 400). A project's own volume, with its code, is created with its project; a local volume needs code.

Scope: volumes:write

Request Body

{
"name": "training-data",
"scope": "shared",
"description": "Training dataset"
}
FieldTypeRequiredDescription
namestringYesVolume name, unique among your volumes of the same scope
scopestringNoshared for a data-only shared volume, or local (the default) for a project's volume
projectIdstringNoProject the volume belongs to (for local scope)
descriptionstringNoVolume description
codeobjectFor localA project volume's code half (see below); refused for shared

code object

FieldTypeRequiredDescription
filesystemTypestringYesstrongly (platform-hosted git repo) or github
repoUrlstringFor githubSSH URL of the GitHub repository
branchstringNoBranch to track (default main)
sshKeyIdstringNoReference to an SSH key for a private GitHub repo

Response 201 Created

{
"data": {
"_id": "vol_def001",
"name": "training-data",
"scope": "local"
},
"meta": {
"requestId": "req_abc123"
}
}

GET /api/v1/volumes/:id​

Get a single volume by ID.

Scope: volumes:read

Path Parameters

ParameterTypeRequiredDescription
idstringYesVolume ID

Response 200 OK

Returns the full Volume object.


GET /api/v1/volumes/:id/data/files​

List the files in the volume's data half. Each entry carries that file's current (head) version, so different files can be at different versions.

Scope: volumes:read

Path Parameters

ParameterTypeRequiredDescription
idstringYesVolume ID

Response 200 OK

{
"data": {
"volumeId": "vol_def001",
"files": [
{
"path": "raw/customers.csv",
"name": "customers.csv",
"size": 45000,
"version": 3,
"updatedAt": "2025-02-01T14:22:00Z",
"updatedBy": "user_456"
},
{
"path": "models/model.pkl",
"name": "model.pkl",
"size": 10485760,
"version": 1,
"updatedAt": "2025-01-20T09:10:00Z",
"updatedBy": "user_456"
}
]
},
"meta": {
"requestId": "req_abc123"
}
}
FieldTypeDescription
pathstringFile path within the data half
namestringFile name
sizeintegerFile size in bytes
versionintegerThat file's current (head) version
updatedAtstringWhen the file was last written
updatedBystringID of the user who last wrote the file

GET /api/v1/volumes/:id/data/files/versions​

List the version history of a single file in the volume's data half, newest first. Each write of that file created a version.

Scope: volumes:read

Path Parameters

ParameterTypeRequiredDescription
idstringYesVolume ID

Query Parameters

ParameterTypeRequiredDescription
pathstringYesFile path within the data half

Response 200 OK

{
"data": {
"path": "raw/customers.csv",
"versions": [
{
"version": 3,
"size": 45000,
"createdAt": "2025-02-01T14:22:00Z",
"createdBy": "user_456",
"createdByEmail": "ana@my-org.com",
"createdByName": "Ana Ruiz",
"message": "refreshed February export",
"deleted": false
},
{
"version": 2,
"size": 44200,
"createdAt": "2025-01-25T11:05:00Z",
"createdBy": "user_456",
"createdByEmail": "ana@my-org.com",
"createdByName": "Ana Ruiz",
"message": "",
"deleted": false
}
]
},
"meta": {
"requestId": "req_abc123"
}
}
FieldTypeDescription
pathstringFile path within the data half
versionintegerVersion number of this entry
sizeintegerFile size in bytes at this version
createdAtstringWhen this version was written
createdBystringID of the user who wrote this version
createdByEmailstringEmail of the user who wrote this version
createdByNamestringName of the user who wrote this version
messagestringOptional message recorded with the write
deletedbooleanWhether this version is a deletion (a tombstone)

GET /api/v1/volumes/:id/data/files/content​

Download the bytes of a single file in the volume's data half, base64-encoded. Returns the file's latest version by default, or a specific per-file version with version.

Scope: volumes:read

Path Parameters

ParameterTypeRequiredDescription
idstringYesVolume ID

Query Parameters

ParameterTypeRequiredDescription
pathstringYesFile path within the data half
versioninteger or stringNoVersion to read. Default latest

Response 200 OK

{
"data": {
"volumeId": "vol_def001",
"path": "raw/customers.csv",
"version": "latest",
"base64": "aWQsbmFtZQoxLEFuYQo=",
"sizeBytes": 14
},
"meta": {
"requestId": "req_abc123"
}
}
FieldTypeDescription
volumeIdstringVolume ID
pathstringFile path within the data half
versionstringThe version you asked for, as a string (latest when omitted)
base64stringThe file's bytes, base64-encoded
sizeBytesintegerFile size in bytes

POST /api/v1/volumes/:id/data/files​

Write a file to the volume's data half, creating a new version of that file. Send content for text or contentBase64 for binary bytes (exactly one).

Scope: volumes:write

Path Parameters

ParameterTypeRequiredDescription
idstringYesVolume ID

Request Body

{
"path": "raw/customers.csv",
"content": "id,name\n1,Ana\n",
"message": "refreshed February export"
}
FieldTypeRequiredDescription
pathstringYesFile path within the data half
contentstringOne ofText content to write
contentBase64stringOne ofBinary content to write, base64-encoded
messagestringNoOptional message recorded with the new version

Provide exactly one of content or contentBase64.

Response 200 OK

{
"data": {
"path": "raw/customers.csv",
"version": 4,
"changed": true,
"deleted": false
},
"meta": {
"requestId": "req_abc123"
}
}

Returns the file's new version number and whether its content actually changed. Re-writing the exact same bytes is a no-op, so changed is false and the version does not advance.


DELETE /api/v1/volumes/:id/data/files​

Delete a file from the volume's data half. The file is tombstoned, so its earlier versions stay in history.

Scope: volumes:write

Path Parameters

ParameterTypeRequiredDescription
idstringYesVolume ID

Query Parameters

ParameterTypeRequiredDescription
pathstringYesFile path within the data half
messagestringNoOptional message recorded with the deletion

Response 200 OK

{
"data": {
"path": "raw/customers.csv",
"version": 5,
"changed": true,
"deleted": true
},
"meta": {
"requestId": "req_abc123"
}
}

The deletion is recorded as a new version of the file, so it stays traceable in the file's history.


DELETE /api/v1/volumes/:id​

Delete a volume. It is refused while something uses it (a running workspace, a job run, an app built from it, or, for a project's own volume, its project). This action is irreversible.

Scope: volumes:write

Path Parameters

ParameterTypeRequiredDescription
idstringYesVolume ID

Response 204 No Content


GET /api/v1/volumes/:id/deletion-impact​

Before deleting: whether it can be deleted and, if not, what uses it, as the delete dialog says.

Response 200 OK

{
"data": {
"canDelete": false,
"reason": "in-use",
"message": "... is in use by ... Stop or delete those first.",
"dependents": [{ "kind": "app", "items": [{ "id": "app-abc", "name": "forecast-dashboard" }] }]
}
}

When it can be deleted, canDelete is true and dependents is empty.

Scope: volumes:read


Code half​

A project volume's code, as its Code tab shows it. These work on a volume whose code is on the Strongly filesystem: a GitHub volume's code is on GitHub, and a shared volume created on its own has no code (400). A shared volume's code is read-only, so writes to it are refused (403).

EndpointScopeWhat it does
GET /api/v1/volumes/:id/code/branchesvolumes:readIts branches and default branch
POST /api/v1/volumes/:id/code/branchesvolumes:writeCreate a branch. Body: name, optional from (a branch or commit; default the default branch)
GET /api/v1/volumes/:id/code/tree?ref=&path=volumes:readThe files and folders of one folder, on a branch (default the default branch)
GET /api/v1/volumes/:id/code/files/content?ref=&path=volumes:readOne file's content at a branch or commit
GET /api/v1/volumes/:id/code/log?ref=&path=&limit=volumes:readA branch's commits, newest first, optionally of one file or folder (default 50)
GET /api/v1/volumes/:id/code/diff?head=&base=&path=volumes:readWhat changed: a commit against its parent, or head against base, optionally for one file
PUT /api/v1/volumes/:id/code/files/contentvolumes:writeCreate or replace a file, committed as you. Body: path, content, optional branch and message
DELETE /api/v1/volumes/:id/code/files?path=&branch=&message=volumes:writeDelete a file, committed as you

Workspaces see a change made here when they pull (git pull in code/).