Sandbox Files (Advanced) API

These advanced file operations extend the core Files API with IDE-oriented capabilities: recursive tree listing, atomic batch writes, and a live file-change event stream.

Base path: /api/v1/sandboxes/{id}/files, and /api/v1/sandboxes/{id}/fs for the upload route.


Endpoints

MethodPathDescription
GET/api/v1/sandboxes/{id}/files/treeRecursive file tree
POST/api/v1/sandboxes/{id}/files/write-manyBatch write multiple files
GET/api/v1/sandboxes/{id}/files/watchSSE stream of file-change events
POST/api/v1/sandboxes/{id}/fs/uploadUpload a file (multipart)

Upload a file

POST /api/v1/sandboxes/{id}/fs/upload

Send the bytes as multipart form data. This is the route the SDKs use, and the only upload route today.

FieldTypeRequiredDescription
filefileYesThe bytes to write. A missing part answers 400 MISSING_FILE.
pathstringNoDestination. Defaults to /home/user/. A trailing slash appends the uploaded filename; without one, path is the exact destination.
curl -X POST https://api.miosa.ai/api/v1/sandboxes/$SBX/fs/upload \
  -H "Authorization: Bearer msk_u_..." \
  -F "path=/workspace/assets/" \
  -F "file=@./logo.png"

Errors

StatusCodeCause
400MISSING_FILENo file part.
400INVALID_PATHpath contains a null byte.
413FILE_TOO_LARGEThe upload exceeds the size limit.

Write bytes, not text

/files/write stores content verbatim, so it is for text. For anything binary, send content_base64 instead; /files/write-many takes it per file.

# macOS uses `base64 -i`, GNU coreutils uses `base64 -w0`
B64=$(base64 -i ./logo.png | tr -d '\n')
curl -X POST https://api.miosa.ai/api/v1/sandboxes/$SBX/files/write \
  -H "Authorization: Bearer msk_u_..." \
  -H "Content-Type: application/json" \
  --data "$(jq -n --arg p /workspace/logo.png --arg b "$B64" '{path: $p, content_base64: $b}')"

File Tree

GET /api/v1/sandboxes/{id}/files/tree

Returns a recursive directory listing up to a configurable depth. Useful for populating an IDE file-explorer panel.

Auth

Authorization: Bearer msk_...

Query Parameters

ParameterTypeDefaultDescription
pathstring/workspaceRoot directory to list
depthinteger3Max traversal depth (1-10)
include_hiddenbooleanfalseInclude dot-files and dot-directories

Response - 200 OK

{
  "data": {
    "path": "/workspace",
    "type": "directory",
    "children": [
      {
        "name": "src",
        "path": "/workspace/src",
        "type": "directory",
        "children": [
          {
            "name": "index.ts",
            "path": "/workspace/src/index.ts",
            "type": "file",
            "size": 1842,
            "modified_at": "2026-05-26T09:12:01Z"
          }
        ]
      },
      {
        "name": "package.json",
        "path": "/workspace/package.json",
        "type": "file",
        "size": 512,
        "modified_at": "2026-05-25T18:00:00Z"
      }
    ]
  }
}

Batch Write

POST /api/v1/sandboxes/{id}/files/write-many

Writes multiple files in a single request. All writes are applied atomically from the guest’s perspective - either all succeed or an error is returned for the failing file.

Request Body

{
  "files": [
    {
      "path": "/workspace/src/index.ts",
      "content": "export const hello = () => 'world';\n",
      "encoding": "utf8"
    },
    {
      "path": "/workspace/src/utils.ts",
      "content": "ZXhwb3J0IGZ1bmN0aW9uIG5vb3AoKSB7fQo=",
      "encoding": "base64"
    }
  ]
}
FieldTypeRequiredDescription
files[].pathstringYesAbsolute path inside the sandbox
files[].contentstringYesFile content (UTF-8 text or base64-encoded binary)
files[].encodingstringNo"utf8" (default) or "base64"

Response - 200 OK

{
  "data": {
    "written": 2,
    "paths": [
      "/workspace/src/index.ts",
      "/workspace/src/utils.ts"
    ]
  }
}

Errors

StatusCodeCause
400INVALID_BODYfiles is missing or not an array
400TOO_MANY_FILESMore than 50 files in one request
400INVALID_PATHA path contains a null byte or traverses outside the sandbox

File Watch (SSE)

GET /api/v1/sandboxes/{id}/files/watch

Streams file-system change events as SSE. Useful for syncing editor state in real time.

Auth

Authorization: Bearer msk_...

(Browser EventSource cannot set this header - use a server-side client or a scoped session token.)

Query Parameters

ParameterTypeDefaultDescription
pathstring/workspaceDirectory to watch

Response - 200 OK (text/event-stream)

id: wev_001
event: file.changed
data: {"path":"/workspace/src/index.ts","event":"modified","ts":"2026-05-26T10:14:23Z"}

id: wev_002
event: file.changed
data: {"path":"/workspace/src/new-file.ts","event":"created","ts":"2026-05-26T10:14:24Z"}

: heartbeat

Event values for data.event:

ValueTrigger
createdNew file or directory
modifiedFile content changed
deletedFile or directory removed
renamedFile moved or renamed

Examples

Was this page helpful?