# Reading Files

**Page:** api/files/reading

[Download Raw Markdown](./api/files/reading.md)

---

{/* AUTO-GENERATED — Do not edit manually. Regenerate with: npm run docs:api:generate */}



## Overview

The Reading Files endpoints let you browse, download, and inspect files via HTTP `GET` requests. Use them to enumerate directory contents, download file payloads, retrieve hashes, run content searches (`grep`) and filename searches (`glob`), extract specific line ranges, and read historical revisions from the file journal. Two endpoint variants are available: a basic form at `/{path}` and a richer v1 form at `/api/v1/files/{path}` that exposes the full search and journal surface.

## `GET /{path}`

Returns a directory listing in HTML or JSON format, or downloads a file. For file paths, append `?download` (or `?download=true`) to force a `Content-Disposition: attachment` response. Use `?json` for a machine-readable listing, `?hash` for a SHA-256 digest, and `?base64` for base64-encoded content.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `path` | path | string | Yes | File or directory path |
| `json` | query | string | No | Return JSON format instead of HTML |
| `simple` | query | string | No | Return simple text listing |
| `sort` | query | string | No | Sort by field. Accepted values: `name`, `mtime`, `size` |
| `order` | query | string | No | Sort order. Accepted values: `asc`, `desc` |
| `hash` | query | string | No | Get SHA256 hash of file (returns plain text hash) |
| `sha256` | query | string | No | Get SHA256 hash of file (alias for `hash`) |
| `base64` | query | string | No | Get file content as base64 encoded string |
| `edit` | query | string | No | Open file in Web UI editor (requires `allow-upload` permission) |
| `view` | query | string | No | View file in Web UI (read-only mode) |
| `download` | query | string | No | For file paths only: force browser download (`Content-Disposition: attachment`). Accepted values: empty (`?download`), `1`, or `true`. For directory paths, triggers the URL download-manager operation. |
| `content-type` | query | string | No | Override `Content-Type` header for file downloads |
| `history` | query | string | No | List all revisions of a file. Returns JSON with revisions array, pagination via after_id. Mutually exclusive with at/revision/diff. |
| `at` | query | string | No | Read file content at a point in time. Accepts RFC3339 timestamp or Unix milliseconds. Mutually exclusive with history/revision/diff. Composable with ?lines, ?hash, ?base64. |
| `revision` | query | integer | No | Read file content by stable per-path sequence number. Mutually exclusive with history/at/diff. Composable with ?lines, ?hash, ?base64. |
| `diff` | query | string | No | Compute unified diff between two versions. Requires from_seq or from_ts. Optional to_seq or to_ts (defaults to current file). Mutually exclusive with history/at/revision. |
| `from_seq` | query | integer | No | Source revision seq number for ?diff. Mutually exclusive with from_ts. |
| `from_ts` | query | string | No | Source timestamp for ?diff (RFC3339 or Unix ms). Mutually exclusive with from_seq. |
| `to_seq` | query | integer | No | Target revision seq number for ?diff. Mutually exclusive with to_ts. Default: current file on disk. |
| `to_ts` | query | string | No | Target timestamp for ?diff (RFC3339 or Unix ms). Mutually exclusive with to_seq. |
| `after_id` | query | integer | No | Cursor for ?history pagination. Returns entries with id &gt; after_id. |
| `limit` | query | integer | No | Max entries to return for ?history. |

### Example request



```bash
curl "https://api.hoody.com/workspace/projects?json&sort=name&order=asc"
```


```javascript
const listing = await client.files.listDirectory({
  path: "workspace/projects",
  json: "",
  sort: "name",
  order: "asc"
});
```



### Response



Directory listings return JSON matching the `DirectoryListing` schema. File downloads return `application/octet-stream` with the raw binary content.

```json
{
  "allow_archive": true,
  "allow_delete": false,
  "allow_search": true,
  "allow_upload": true,
  "auth": true,
  "dir_exists": true,
  "href": "/workspace/projects",
  "kind": "Index",
  "paths": [
    {
      "mtime": 1716400000000,
      "name": "README.md",
      "path_type": "File",
      "revisions": 12,
      "size": 4321
    },
    {
      "mtime": 1716390000000,
      "name": "src",
      "path_type": "Dir",
      "revisions": null,
      "size": 24
    },
    {
      "mtime": 1716300000000,
      "name": "package.json",
      "path_type": "File",
      "revisions": 5,
      "size": 1208
    }
  ],
  "uri_prefix": "/api/v1/files",
  "user": "alice"
}
```


```json
{
  "error": "Access to /workspace/secret is forbidden",
  "success": false
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `ACCESS_FORBIDDEN` | Access forbidden | User does not have permission to access this path | Contact administrator for read permissions or authenticate with different account |


```json
{
  "error": "File or directory not found: /workspace/missing.txt",
  "success": false
}
```



## `GET /api/v1/files/{path}`

Get a directory listing in JSON format, download a file, run `grep`/`glob` searches, extract a line range, or read historical revisions from the journal. The optional `backend` query parameter routes the request to a remote backend.

### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `path` | path | string | Yes | File or directory path |
| `backend` | query | string | No | Backend ID for remote file access |
| `hash` | query | string | No | Get SHA256 hash of file |
| `sha256` | query | string | No | Get SHA256 hash of file (alias for `hash`) |
| `base64` | query | string | No | Get file content as base64 |
| `preview` | query | string | No | Preview archive contents (for zip/tar files). Alias: `?contents` |
| `contents` | query | string | No | Alias for `?preview` — list archive contents |
| `stat` | query | string | No | Get file/directory metadata (stat) without downloading content |
| `thumbnail` | query | string | No | Generate thumbnail (not yet implemented in API v1, returns 501) |
| `grep` | query | string | No | Search file/directory contents for regex pattern (or literal if `fixed_string=true`). Requires `--allow-grep`. |
| `ignore_case` | query | boolean | No | Case-insensitive grep matching. Default: `false` |
| `fixed_string` | query | boolean | No | Treat grep pattern as literal string, not regex. Default: `false` |
| `glob` | query | string | No | Find files matching glob pattern (e.g. `**/*.rs`, `src/**/*.{ts,tsx}`). Requires `--allow-search`. Directory paths only. |
| `context` | query | integer | No | Number of context lines before/after each grep match. Default: `0` |
| `max_count` | query | integer | No | Max matches per file for grep. Default: `50` |
| `max_matches` | query | integer | No | Total max matches across all files for grep. Default: `500` |
| `max_depth` | query | integer | No | Directory recursion depth for grep. Default: `50` |
| `max_filesize` | query | integer | No | Skip files larger than this (bytes) during grep. Default: `10485760` |
| `timeout` | query | integer | No | Grep timeout in seconds. Default: `30` |
| `no_ignore` | query | boolean | No | Bypass `.gitignore` filtering during grep. Default: `false` |
| `max_results` | query | integer | No | Max entries returned for glob search. Default: `1000` |
| `max_files_scanned` | query | integer | No | Max filesystem entries scanned during glob search. Default: `100000` |
| `sort` | query | string | No | Sort glob results by: `mtime` (default), `name`, or `size` |
| `order` | query | string | No | Sort order for glob results. Default: `desc` for mtime, `asc` for name/size. Accepted values: `asc`, `desc` |
| `lines` | query | string | No | Extract specific lines from a file. Formats: `10-50` (range, 1-indexed inclusive), `100` (single line), `-20` (last 20 lines / tail), `50-` (line 50 to end). Returns `text/plain` with `X-Line-Range` header. `X-Total-Lines` header included when naturally known (scan reached EOF). Max 100,000 lines or 64MB per request. |
| `history` | query | string | No | List all revisions of a file. Returns JSON with revisions array, pagination via `after_id`. Mutually exclusive with `at`/`revision`/`diff`. |
| `at` | query | string | No | Read file content at a point in time. Accepts RFC3339 timestamp or Unix milliseconds. Mutually exclusive with `history`/`revision`/`diff`. Composable with `?lines`, `?hash`, `?base64`. |
| `revision` | query | integer | No | Read file content by stable per-path sequence number. Mutually exclusive with `history`/`at`/`diff`. Composable with `?lines`, `?hash`, `?base64`. |
| `diff` | query | string | No | Compute unified diff between two versions. Requires `from_seq` or `from_ts`. Optional `to_seq` or `to_ts` (defaults to current file). Mutually exclusive with `history`/`at`/`revision`. |
| `from_seq` | query | integer | No | Source revision seq number for `?diff`. Mutually exclusive with `from_ts`. |
| `from_ts` | query | string | No | Source timestamp for `?diff` (RFC3339 or Unix ms). Mutually exclusive with `from_seq`. |
| `to_seq` | query | integer | No | Target revision seq number for `?diff`. Mutually exclusive with `to_ts`. Default: current file on disk. |
| `to_ts` | query | string | No | Target timestamp for `?diff` (RFC3339 or Unix ms). Mutually exclusive with `to_seq`. |
| `after_id` | query | integer | No | Cursor for `?history` pagination. Returns entries with id > `after_id`. |
| `limit` | query | integer | No | Max entries to return for `?history`. Default: `100` |
| `zip` | query | string | No | Download a directory as a streaming zip archive (bare flag, e.g. ?zip). Local directories only; requires --allow-archive. Same behavior as the WebDAV-style /&#123;directory&#125;?zip. |

### Example request



```bash
curl "https://api.hoody.com/api/v1/files/workspace/api-docs?grep=export+function&ignore_case=true&context=2&max_count=50"
```


```javascript
const results = await client.files.get({
  path: "workspace/api-docs",
  grep: "export function",
  ignore_case: true,
  context: 2,
  max_count: 50
});
```



### Response



Returns a directory listing, grep/glob results, line-range content, file revision history, historical content, or a unified diff depending on the query parameters used. File downloads return `application/octet-stream`.

Directory listing:

```json
{
  "allow_archive": true,
  "allow_delete": false,
  "allow_search": true,
  "allow_upload": true,
  "auth": true,
  "dir_exists": true,
  "href": "/workspace/api-docs",
  "kind": "Index",
  "paths": [
    {
      "mtime": 1716400000000,
      "name": "README.md",
      "path_type": "File",
      "revisions": 12,
      "size": 4321
    },
    {
      "mtime": 1716390000000,
      "name": "src",
      "path_type": "Dir",
      "revisions": null,
      "size": 24
    }
  ],
  "uri_prefix": "/api/v1/files",
  "user": "alice"
}
```

Grep results:

```json
{
  "duration_ms": 142,
  "matches": [
    {
      "column_byte": 6,
      "context_after": ["function foo() {"],
      "context_before": ["// utility module"],
      "line": "export function greet(name) {",
      "line_number": 12,
      "path": "/workspace/api-docs/src/utils.ts"
    }
  ],
  "path": "/workspace/api-docs",
  "pattern": "export function",
  "total_files_matched": 1,
  "total_files_searched": 42,
  "total_matches": 1,
  "truncated": false
}
```

Glob results:

```json
{
  "count": 2,
  "duration_ms": 18,
  "entries": [
    {
      "is_dir": false,
      "modified": 1716400000,
      "name": "/workspace/api-docs/src/index.ts",
      "size": 2104
    },
    {
      "is_dir": false,
      "modified": 1716350000,
      "name": "/workspace/api-docs/src/utils.ts",
      "size": 872
    }
  ],
  "path": "/workspace/api-docs",
  "pattern": "src/**/*.ts",
  "total_scanned": 87,
  "truncated": false
}
```


```json
{
  "error": "File /workspace/old-report.txt was deleted or moved at the requested point in time"
}
```


```json
{
  "error": "Content for revision 47 of /workspace/large.bin is not stored (file exceeded journal size limit)"
}
```


Too many concurrent journal queries are in flight. Retry after a short delay. The response has no body.




The v1 endpoint exposes the file journal. Use `?history` (with optional `after_id`/`limit`) to paginate revisions, `?at` or `?revision` to read historical content, and `?diff` with `from_seq`/`from_ts` (and optionally `to_seq`/`to_ts`) to compute unified diffs between two points in time. These three modes are mutually exclusive.