Docs
BlogHomeStart building

Project Files

Read and edit your app's code file by file.


Work on the code directly instead of through prompts: list the tree, read a file, write it back. Every write is saved as a new version and deployed to the development preview; publish to put it live.

#Get Project Tree

GET/api/v1/vcaas/projects/:projectId/files/treeapi-keyFree

The project's files and folders, as a flat, sorted list. node_modules, .next, .git, dist and other build output are never included.

Path parameters

ParameterTypeDescription
projectIdstringThe project ID

Query parameters

FieldTypeRequiredDescription
pathstringNoLimit the tree to one subfolder, e.g. src/app. Default: the whole project
limitnumberNoPage size. Default 2000, max 5000
offsetnumberNoEntries to skip. Default 0

Response fields

FieldTypeDescription
data.entries[].pathstringPath relative to the project root, e.g. src/app/page.tsx
data.entries[].namestringFile or folder name
data.entries[].typestring"file" or "folder"
data.entries[].sizenumber | undefinedSize in bytes. Files only
data.entries[].depthnumber0 at the project root
data.totalEntriesnumberEntries matching the request before paging
data.offsetnumberThe offset used
data.limitnumberThe limit used
data.hasMorebooleantrue when more entries follow
data.commitShastring | nullGit commit the tree was read from
data.filesCountnumberFiles tracked in the project, before exclusions

Entries are sorted the way a file explorer shows them: folders before files, alphabetically, within each parent.

Example request

curl -H "api-key: tlm_sk_your_key" \
  "https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/files/tree?path=src/app&limit=100"
Success · 200 OK
json
{
  "errors": null,
  "data": {
    "entries": [
      { "path": "src/app", "name": "app", "type": "folder", "depth": 1 },
      { "path": "src/app/layout.tsx", "name": "layout.tsx", "type": "file", "size": 1284, "depth": 2 },
      { "path": "src/app/page.tsx", "name": "page.tsx", "type": "file", "size": 3902, "depth": 2 }
    ],
    "totalEntries": 3,
    "offset": 0,
    "limit": 100,
    "hasMore": false,
    "commitSha": "a1b2c3d",
    "filesCount": 47
  }
}

Error codes

CodeHTTPMeaning
INVALID_PATH400The path is absolute, contains .., or points inside an excluded folder
PROJECT_NOT_FOUND404Project does not exist or you don't own it
PROJECT_TOO_LARGE413The project archive is too large to browse through the API — download it instead

#Get File Content

GET/api/v1/vcaas/projects/:projectId/files/contentapi-keyFree

The complete content of one file. Files up to 1 MB.

Path parameters

ParameterTypeDescription
projectIdstringThe project ID

Query parameters

FieldTypeRequiredDescription
pathstringYesPath relative to the project root, e.g. src/app/page.tsx

Response fields

FieldTypeDescription
data.pathstringThe normalised path
data.namestringFile name
data.sizenumberSize of the stored file in bytes
data.encodingstring"utf8" for text, "base64" for binary
data.contentstringThe file content, in encoding
data.commitShastring | nullGit commit the file was read from

Binary files (anything with a NUL byte in the first 8 KB) come back base64-encoded, so they survive a round trip through PUT /files/content.

Example request

curl -H "api-key: tlm_sk_your_key" \
  "https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/files/content?path=src/app/page.tsx"
Success · 200 OK
json
{
  "errors": null,
  "data": {
    "path": "src/app/page.tsx",
    "name": "page.tsx",
    "size": 62,
    "encoding": "utf8",
    "content": "export default function Page() {\n  return <h1>Hello</h1>;\n}\n",
    "commitSha": "a1b2c3d"
  }
}
Error · 404
json
{
  "errors": {
    "errorCode": "FILE_NOT_FOUND",
    "errorMessage": "No file at \"src/app/missing.tsx\" in this project."
  },
  "data": null
}

Error codes

CodeHTTPMeaning
INVALID_PATH400The path is absolute, contains .., or points inside an excluded folder
PROJECT_NOT_FOUND404Project does not exist or you don't own it
FILE_NOT_FOUND404No file at that path
FILE_TOO_LARGE413The file is larger than 1 MB — download the source archive instead

#Write File Content

PUT/api/v1/vcaas/projects/:projectId/files/contentapi-keyFree

Create or replace one file (up to 512 KB). Missing folders are created. The write is saved as a version and the preview is rebuilt with it (a new file under public/ can make the preview answer 503 updating for a minute or two).

If the save is still in progress after about 45 seconds (the project's environment was asleep), the call answers 202 with saved: false: read the file again a minute later before relying on it, and do not send it again.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Body parameters

FieldTypeRequiredDescription
pathstringYesPath from the project root, e.g. src/app/page.tsx
contentstringYesThe complete new content ("" empties the file)
encodingstringNo"utf8" (default) or "base64" for binary files
baseSha256stringNoSHA-256 (hex) of the file as you read it: if it changed since (the agent, a restore), the write is refused with 409 FILE_CHANGED

Response fields

FieldTypeDescription
data.pathstringNormalised path
data.createdbooleantrue when the file is new
data.bytesWrittennumber | undefinedBytes written (saved writes only)
data.commitShastring | undefinedThe commit of the new version
data.filesCountnumber | undefinedFiles in the project after the write
data.rebuildRequiredbooleanAlways false: the write deploys itself
data.savedboolean | undefinedfalse on a 202 (still saving)
data.versionIdstring | undefinedOn a 202: the version being saved
data.messagestring | undefinedOn a 202: what to do

Example request

curl -X PUT \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"path":"src/app/hello/page.tsx","content":"export default function Hello() {\n  return <h1>Hello</h1>;\n}\n"}' \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/files/content
Success · 200 OK
json
{ "errors": null, "data": { "path": "src/app/hello/page.tsx", "bytesWritten": 58, "created": true, "commitSha": "d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3", "filesCount": 97, "rebuildRequired": false } }

Error codes

CodeHTTPMeaning
INVALID_PATH400Absolute, contains .., or inside an excluded folder
MISSING_CONTENT400content is missing or not a string
INVALID_ENCODING400Not utf8 or base64
FILE_TOO_LARGE413Over 512 KB
FILE_CHANGED409The file changed since your baseSha256
AGENT_RUNNING409A prompt is running
OPERATION_IN_PROGRESS409A publish, restore or import is running
RATE_LIMITED429More than 300 writes a minute
End of Write File ContentNext endpointPOSTRebuild Project

#Rebuild Project

POST/api/v1/vcaas/projects/:projectId/rebuildapi-key2 credits

Build the current version again and redeploy the preview — for example after the preview failed to build. Takes 1–4 minutes; poll Get Rebuild Status.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.projectIdstringProject id
data.statusstring"rebuilding"
data.startedAtstringISO 8601
data.messagestringNext step

Example request

curl -X POST -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/rebuild
Success · 200 OK
json
{ "errors": null, "data": { "projectId": "barber-bookings", "status": "rebuilding", "startedAt": "2026-10-08T12:20:00.000Z", "message": "Rebuild started. It usually takes 1-4 minutes. Poll GET /projects/barber-bookings/rebuild/status until status is \"success\" or \"error\"." } }

Error codes

CodeHTTPMeaning
REBUILD_RUNNING409A rebuild is already running
AGENT_RUNNING409A prompt is running
DEPLOYMENT_RUNNING409A publish is running
INSUFFICIENT_CREDITS402Not enough credits

#Get Rebuild Status

GET/api/v1/vcaas/projects/:projectId/rebuild/statusapi-keyFree

The newest rebuild. A failed rebuild is status: "error" in a 200 answer.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.projectIdstringProject id
data.statusstring"idle" (never rebuilt), "rebuilding", "success" or "error"
data.startedAtstring | nullISO 8601
data.finishedAtstring | nullISO 8601
data.elapsedSecondsnumber | nullDuration so far, or total
data.livePreviewUrlstring | undefinedThe preview, after a success
data.errorCodestring | undefinedOn "error"
data.errorMessagestring | undefinedOn "error"

Example request

curl -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/rebuild/status
Success · 200 OK
json
{ "errors": null, "data": { "projectId": "barber-bookings", "status": "success", "startedAt": "2026-10-08T12:20:00.000Z", "finishedAt": "2026-10-08T12:22:10.000Z", "elapsedSeconds": 130, "livePreviewUrl": "https://barber-bookings-dev-temporal-link-preview-k3y9x2ab.totalum-project.com" } }
End of Get Rebuild Status Back to top