Files
The shared /workspace disk: browser downloads, shell output, and reading and writing files through the API.
Every session has a disk at /workspace (the session’s workspacePath). The browser, the shell and the API all see the same files:
- browser downloads land in
/workspace/downloads, whichever client triggers them; - the shell starts in
/workspaceand can read and write it; - the files API lists, reads, writes and deletes files in it.
That is what lets an agent download a CSV in the browser, analyse it with Python and hand the result back, without the file ever leaving the machine.
Paths in the files API are relative to /workspace (downloads/report.csv), or absolute paths inside it (/workspace/downloads/report.csv). Paths outside the workspace are rejected with 403.
Read a file
GET/v1/sessions/:id/files?path=
Returns the file’s bytes.
curl -G https://api.staging.boxline.dev/v1/sessions/$SESSION_ID/files \
-H "x-api-key: $BOXLINE_API_KEY" \
--data-urlencode "path=summary.csv" \
-o summary.csvList a directory
GET/v1/sessions/:id/files?path=&list=1
curl -G https://api.staging.boxline.dev/v1/sessions/$SESSION_ID/files \
-H "x-api-key: $BOXLINE_API_KEY" \
--data-urlencode "path=downloads" \
--data-urlencode "list=1"{
"path": "/workspace/downloads",
"entries": [
{ "name": "report.csv", "type": "file", "size": 48213, "mtime": "2026-09-28T12:01:07.000Z" }
]
}type is "file", "dir" or "other".
Write a file
PUT/v1/sessions/:id/files?path=
The request body is the raw file contents. The response is { path, size }.
curl -X PUT "https://api.staging.boxline.dev/v1/sessions/$SESSION_ID/files?path=summarise.py" \
-H "x-api-key: $BOXLINE_API_KEY" \
--data-binary @summarise.pyDelete a file
DELETE/v1/sessions/:id/files?path= returns 204.
curl -X DELETE "https://api.staging.boxline.dev/v1/sessions/$SESSION_ID/files?path=summary.csv" \
-H "x-api-key: $BOXLINE_API_KEY"Wait for a file
GET/v1/sessions/:id/files/wait?pattern=&timeoutMs=
Downloads finish in their own time. Instead of polling, ask the session to respond once a file matching a glob exists and has finished writing. Chrome’s in-progress .crdownload files are ignored. The glob applies to the last path segment, relative to /workspace, for example downloads/*.csv.
curl -G https://api.staging.boxline.dev/v1/sessions/$SESSION_ID/files/wait \
-H "x-api-key: $BOXLINE_API_KEY" \
--data-urlencode "pattern=downloads/*.csv" \
--data-urlencode "timeoutMs=30000"The response is { path, size } for the newest match, with an absolute path such as /workspace/downloads/report.csv. If nothing matches in time, the request fails with 408.
With the SDK
| Method | Returns |
|---|---|
session.files.read(path) | Uint8Array |
session.files.readText(path) | string |
session.files.write(path, data) | { path, size }; data is a string, Uint8Array or Blob |
session.files.list(path = ".") | { path, entries } |
session.files.delete(path) | nothing |
session.files.waitFor(pattern, timeoutMs = 30000) | { path, size } |
// The browser clicked "Export"; wait for the download.
const csv = await session.files.waitFor("downloads/*.csv");
// Process it in the shell, on the same machine.
await session.exec(`python3 summarise.py ${csv.path} > summary.csv`);
// Bring the result home.
const summary = await session.files.readText("summary.csv");To hand a file back to a website, use the upload action with a path inside the sandbox.
These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.