# Files and the workspace (/docs/concepts/files)



Every sandbox has a workspace: the working filesystem area at `/workspace`
inside the live sandbox. The file APIs let you read, write, list, move, and
delete files there while the sandbox is alive. The workspace disappears
when the sandbox is destroyed, so export anything durable as an
[artifact](/docs/concepts/artifacts).

## Workspace confinement [#workspace-confinement]

All file APIs are confined to `/workspace`. Every path you pass must
resolve inside it; paths that escape through `..` segments are rejected
with `path_outside_workspace`. Sandboxes never receive host or
provider credentials, and the file APIs can't reach anything outside the
workspace.

## Reading and writing files [#reading-and-writing-files]

Direct reads and writes work on file content up to 256 KB. To move larger
files out of the workspace, export them as
[artifacts](/docs/concepts/artifacts).

* `GET /v1/sandboxes/{id}/files/read` with query `path` returns
  `{ content, encoding }`. Files over 256 KB return `file_too_large` —
  export them as artifacts instead.
* `PUT /v1/sandboxes/{id}/files` with body `path` and `content` writes a
  file, up to 256 KB. Optional fields: `overwrite` (default `true`) and
  `createParents` (default `false`). With `createParents` false, writing
  into a missing directory returns `parent_directory_not_found`.
* `POST /v1/sandboxes/{id}/files/download-url` with body `{ path }` returns
  `{ url, method: "GET", authMode: "api_key" }` — a same-origin URL (still
  authenticated with your API key) that streams the file directly. The
  download is subject to the same 256 KB cap; export larger files as
  [artifacts](/docs/concepts/artifacts).

### Encodings [#encodings]

Reads and writes accept an `encoding` of `utf8` (default) or `base64`. Use
`base64` for binary content. An unsupported value returns
`invalid_file_encoding`.

## Listing and inspecting [#listing-and-inspecting]

Two read endpoints describe the workspace without transferring file
content.

* `GET /v1/sandboxes/{id}/files` lists a directory (query `path`, default
  `/workspace`) and returns `{ data: FileEntry[] }`.
* `GET /v1/sandboxes/{id}/files/stat` returns metadata for one path.

List entries have `path`, `name`, `type` (`file` or `directory`), and
`sizeBytes`, plus an optional `modifiedAt`. The `stat` response is the same
shape without `name`.

## Directory operations [#directory-operations]

The write endpoints cover directory creation, moves, and deletion.

* `POST /v1/sandboxes/{id}/files/mkdir` creates a directory (body `path`,
  optional `parents`, default `false`). Without `parents`, a missing parent
  returns `parent_directory_not_found`.
* `POST /v1/sandboxes/{id}/files/move` moves or renames (body `from`, `to`,
  optional `overwrite`, default `false`). With `overwrite` false, an
  existing destination returns `file_already_exists`.
* `DELETE /v1/sandboxes/{id}/files` with query `path` deletes a file or an
  empty directory and returns `{ deleted: true }`.

<Callout type="info" title="Note">
  There is no recursive delete. Deleting a non-empty directory returns
  `directory_not_empty`. Remove the contents first, or run a command such as `rm -rf`
  inside the sandbox.
</Callout>

## File error codes [#file-error-codes]

These error codes are specific to the file APIs:

| Code                         | Meaning                                             |
| ---------------------------- | --------------------------------------------------- |
| `path_outside_workspace`     | The path resolves outside `/workspace`.             |
| `path_is_directory`          | A file operation targeted a directory.              |
| `path_not_directory`         | A directory operation targeted a file.              |
| `file_not_found`             | The path doesn't exist.                             |
| `file_too_large`             | Content exceeds the 256 KB direct read/write limit. |
| `file_already_exists`        | The destination exists and `overwrite` is false.    |
| `parent_directory_not_found` | A parent directory is missing.                      |
| `directory_not_empty`        | Delete targeted a non-empty directory.              |
| `invalid_file_encoding`      | The `encoding` value isn't `utf8` or `base64`.      |

## Next steps [#next-steps]

* [Artifacts](/docs/concepts/artifacts) — keep files beyond the sandbox
  lifetime.
* [Commands](/docs/concepts/commands) — run processes that produce and
  consume workspace files.
* [SDK quickstart](/docs/quickstart/sdk)
* [Files API reference](/docs/api/files)
