Skip to main content

Files API

List Files

List files in a directory within the workspace.

curl 'https://api.nanoterm.dev/api/workspaces/ws_a1b2c3d4/files?path=/workspace' \
-H 'Authorization: Bearer nt_xxx'

Query Parameters:

ParamTypeDefaultDescription
pathstring/workspaceDirectory to list

Response: 200 OK

{
"files": [
{ "name": "src", "size": 4096, "isDirectory": true },
{ "name": "package.json", "size": 1234, "isDirectory": false },
{ "name": "README.md", "size": 567, "isDirectory": false }
]
}

Read File

Read the contents of a file from the workspace.

curl https://api.nanoterm.dev/api/workspaces/ws_a1b2c3d4/files/workspace/package.json \
-H 'Authorization: Bearer nt_xxx'

Response: 200 OK — raw file contents as binary

Write File

Write content to a file in the workspace.

curl -X PUT https://api.nanoterm.dev/api/workspaces/ws_a1b2c3d4/files/workspace/hello.txt \
-H 'Authorization: Bearer nt_xxx' \
-d 'Hello from NanoTerm!'

Request Body: raw file content

Response: 200 OK

{
"ok": true,
"bytes": 3712,
"mtime": "2026-05-06T08:01:23.000Z"
}

The server stats the file after writing and returns the actual byte count + mtime. Callers should verify bytes matches the upload size; the SDK's writeFile does this automatically and throws on mismatch.

Path constraints

All three endpoints (list, read, write) refuse paths that escape /workspace. Symbolic-traversal attempts (/workspace/../etc), sibling absolute paths (/etc/passwd, /proc/self/environ), and embedded NUL bytes return 400 INVALID_PATH. Inputs are POSIX- normalised first, so /workspace/./a/../b is canonicalised to /workspace/b and accepted.

500 FILE_WRITE_BYTE_MISMATCH

The bytes on disk don't match what was received over the wire — usually a streaming / proxy-buffer issue. Retry; if it persists, file a bug.

{
"error": {
"code": "FILE_WRITE_BYTE_MISMATCH",
"message": "Wrote 3700 bytes to /workspace/foo but received 3712 bytes from client.",
"retryable": true
}
}