# File browser API

> List a running machine's folders under /work, /root, or /home as a live tree, and download a folder as a .tar.gz archive.

- [List a folder tree](#list-a-folder-tree): `GET /v1/machines/{machine_id}/files/tree`
- [Download a folder](#download-a-folder): `GET /v1/machines/{machine_id}/files/archive`

## List a folder tree

`GET /v1/machines/{machine_id}/files/tree`

The machine must be running. `path` is `/work` (the default), `/root`, or a home under `/home`, or a folder inside one; `depth` is 1 to 4 (default 2). At most 5,000 entries, breadth first; `truncated` says the listing stopped early. See [Files](/docs/guides/files).

- **API key:** `Authorization: Bearer vmy_…` with preset `use_existing`, `create_and_use`, `full_access`.
- **Browser session:** the `vmyard_session` cookie.
- **Who:** Owner, Admin, or Operator.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `machine_id` | path | `string (uuid)` | Yes |  |
| `path` | query | `string` | No | Absolute directory: `/work` (default), `/root`, or a home under `/home`, or inside one of them; no `.`/`..` components. |
| `depth` | query | `integer` | No | Levels to list below `path`, 1-4 (default 2). |
| `X-Organization-ID` | header | `string (uuid)` | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| `200` | The live tree below `path`, breadth first; at most 5,000 entries | [`FileTreeDto`](/docs/api/schemas#filetreedto) |
| `401` | Not signed in, or the API key is malformed, expired, or revoked (`unauthenticated`, `invalid_api_key`). | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `403` | `forbidden` (Viewer or Billing) or `insufficient_scope` (a `read_only` key) | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `404` | Unknown machine, or `path_not_found` | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `409` | `machine_not_running`, `machine_not_created`, or `machine_deleted` | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `422` | Invalid `path` or `depth`, `path_not_allowed` (a symlink out of the roots), `not_a_directory`, or `listing_too_large` | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `502` | `guest_action_failed` | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `503` | `files_unavailable` (not configured) or `runtime_unavailable` | [`ProblemDetails`](/docs/api/schemas#problemdetails) |

```sh title="Request"
curl "$VMYARD_API_URL/v1/machines/$MACHINE_ID/files/tree" \
  -H "Authorization: Bearer $VMYARD_API_KEY"
```

```json title="Response 200"
{
  "entries": [
    {
      "children": [],
      "modified_at": "2026-10-12T05:51:01Z",
      "name": "dev",
      "path": "notes/todo.txt",
      "size_bytes": 0,
      "type": "file"
    }
  ],
  "file_count": 0,
  "path": "notes/todo.txt",
  "total_bytes": 0,
  "truncated": false
}
```

## Download a folder

`GET /v1/machines/{machine_id}/files/archive`

Streams the folder as a `.tar.gz`; folders over 512 MiB answer `413 archive_too_large`. A download that does not end cleanly is incomplete.

- **API key:** `Authorization: Bearer vmy_…` with preset `use_existing`, `create_and_use`, `full_access`.
- **Browser session:** the `vmyard_session` cookie.
- **Who:** Owner, Admin, or Operator.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `machine_id` | path | `string (uuid)` | Yes |  |
| `path` | query | `string` | Yes | The directory to download, as for the tree. |
| `X-Organization-ID` | header | `string (uuid)` | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| `200` | The folder as a streamed `tar.gz` (`Content-Disposition: attachment`, `<name>.tar.gz`). A failure after the headers aborts the body, so a download that does not end cleanly is incomplete. | `application/gzip` |
| `401` | Not signed in, or the API key is malformed, expired, or revoked (`unauthenticated`, `invalid_api_key`). | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `403` | `forbidden` (Viewer or Billing) or `insufficient_scope` (a `read_only` key) | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `404` | Unknown machine, or `path_not_found` | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `409` | `machine_not_running`, `machine_not_created`, or `machine_deleted` | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `413` | `archive_too_large`: the folder exceeds 512 MiB | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `422` | Invalid `path`, `path_not_allowed`, or `not_a_directory` | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `502` | `guest_action_failed` | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `503` | `files_unavailable` (not configured) or `runtime_unavailable` | [`ProblemDetails`](/docs/api/schemas#problemdetails) |

```sh title="Request"
curl "$VMYARD_API_URL/v1/machines/$MACHINE_ID/files/archive?path=notes/todo.txt" \
  -H "Authorization: Bearer $VMYARD_API_KEY"
```
