Core conceptsBeta

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 /workspace and 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.

Shell
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.csv

List a directory

GET/v1/sessions/:id/files?path=&list=1

Shell
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"
Response
{
  "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 }.

Shell
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.py

Delete a file

DELETE/v1/sessions/:id/files?path= returns 204.

Shell
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.

Shell
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

MethodReturns
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 }
TypeScript
// 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.