Skip to content
Hoody.com

Read files, list directories, search contents, and download archives over HTTP. This page covers the three read endpoints exposed by the Files service. The first (/{path}) returns HTML by default for browser browsing, JSON when requested. The second (/api/v1/files/{path}) returns JSON, binary, or zip and exposes the full search and archive surface (?grep, ?glob, ?stat, ?zip, ?lines, ?thumbnail, ?history, ?at, ?revision, ?diff). The third (/files/) lists the root directory and can be embedded in another page as a framed file browser.

All three endpoints are reached on the Files service hostname: https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com.

Browse a directory or download a single file in its raw form. By default the response is HTML rendered for browser navigation; pass ?json to receive a structured listing.

This endpoint accepts no request body.

NameInTypeRequiredDescription
pathpathstringYesFile or directory path
jsonquerystringNoReturn JSON format instead of HTML
simplequerystringNoReturn simple text listing
sortquerystringNoSort by field. Allowed values: name, mtime, size.
orderquerystringNoSort order. Allowed values: asc, desc.
hashquerystringNoGet SHA256 hash of file (returns plain text hash)
sha256querystringNoGet SHA256 hash of file (alias for hash)
base64querystringNoGet file content as base64 encoded string
editquerystringNoOpen file in Web UI editor (requires allow-upload permission)
viewquerystringNoOpen file in a read-only Web UI page: the text is shown with no Save, rename, move or delete.
downloadquerystringNoFor file paths only: force browser download (Content-Disposition: attachment). Accepted values: empty, 1, or true. For directory paths, ?download is the URL download-manager operation.
content-typequerystringNoOverride Content-Type header for file downloads
historyquerystringNoList all revisions of a file. Returns JSON with a revisions array; paginate via after_id. Mutually exclusive with at / revision / diff.
atquerystringNoRead file content at a point in time. Accepts RFC3339 timestamp or Unix milliseconds. Mutually exclusive with history / revision / diff. Composable with ?lines, ?hash, ?base64.
revisionqueryintegerNoRead file content by stable per-path sequence number. Mutually exclusive with history / at / diff. Composable with ?lines, ?hash, ?base64.
diffquerystringNoCompute 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_seqqueryintegerNoSource revision seq number for ?diff. Mutually exclusive with from_ts.
from_tsquerystringNoSource timestamp for ?diff (RFC3339 or Unix ms). Mutually exclusive with from_seq.
to_seqqueryintegerNoTarget revision seq number for ?diff. Mutually exclusive with to_ts. Default: current file on disk.
to_tsquerystringNoTarget timestamp for ?diff (RFC3339 or Unix ms). Mutually exclusive with to_seq.
after_idqueryintegerNoCursor for ?history pagination. Returns entries with id > after_id.
limitqueryintegerNoMax entries to return for ?history. Default: 100.
themequerystringNoHTML page only: colour theme of the page. Default oc-1. Allowed values: oc-1, aura, ayu, carbonfox, catppuccin, dracula, gruvbox, monokai, nightowl, nord, onedarkpro, shadesofpurple, solarized, tokyonight, vesper.
colorSchemequerystringNoHTML page only: light or dark colour scheme. Without it the page follows the system setting. Allowed values: light, dark.
fontquerystringNoHTML page only: monospace font of the editor and listing. Allowed values: ibm-plex-mono, cascadia-code, fira-code, hack, inconsolata, intel-one-mono, iosevka, jetbrains-mono, meslo-lgs, roboto-mono, source-code-pro, ubuntu-mono.
fontSizequeryintegerNoHTML page only: editor font size in pixels. Default 14.
embedderOriginquerystringNoHTML page only: origin of the page that embeds this one, such as https://app.example.com. The page then accepts theme and layout messages from that origin and tells it when it is ready. Only https origins are accepted.
chromelessquerybooleanNoHTML page only: hide the header, sidebar, preview, footer and borders at once. Each can be turned back on with its own parameter set to false.
borderlessquerybooleanNoHTML page only: hide the page borders.
hideHeaderquerybooleanNoHTML page only: hide the header bar.
hideSidebarquerybooleanNoHTML page only: hide the sidebar.
hidePreviewquerybooleanNoHTML page only: hide the preview pane.
hideFooterquerybooleanNoHTML page only: hide the footer.
embedBgquerystringNoHTML page only: transparent lets the background of the embedding page show through.

A directory listing, the raw file bytes (with Content-Disposition: attachment when ?download is set), revision history (with ?history), historical content (with ?at or ?revision), or a unified diff (with ?diff). The body shape depends on the negotiated content type and the query flags. application/octet-stream is the raw file body; text/html is the browser-rendered file manager page.

Directory listing in JSON:

{
"href": "/",
"kind": "Index",
"user": null,
"auth": false,
"dir_exists": true,
"uri_prefix": "/",
"allow_delete": false,
"allow_upload": false,
"allow_archive": false,
"allow_search": true,
"paths": [
{
"name": "README.md",
"path_type": "File",
"size": 2048,
"mtime": 1717000000000,
"revisions": null
},
{
"name": "src",
"path_type": "Dir",
"size": 12,
"mtime": 1717000123000,
"revisions": null
}
]
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
// Directory listing as JSON, sorted by mtime desc
await client.files.ui.getPage('/', { json: '', sort: 'mtime', order: 'desc' });
// Download a single file
await client.files.ui.getPage('/README.md', { download: 'true' });
// Read file content as base64
await client.files.ui.getPage('/data/config.json', { base64: '' });

Programmatic equivalent of the browser-friendly endpoint. Returns JSON by default, with the full search and archive surface exposed via query parameters: ?grep for content search, ?glob for path search, ?stat for metadata, ?zip for a streaming archive download, ?lines for ranged reads, ?thumbnail for processed images, and ?history / ?at / ?revision / ?diff for the journal modes.

This endpoint accepts no request body.

NameInTypeRequiredDescription
pathpathstringYesFile or directory path
backendquerystringNoBackend ID for remote file access
hashquerystringNoGet SHA256 hash of file
sha256querystringNoGet SHA256 hash of file (alias for hash)
base64querystringNoGet file content as base64
previewquerystringNoPreview archive contents (for zip/tar files). Alias: ?contents.
contentsquerystringNoAlias for ?preview; list archive contents
statquerystringNoGet file or directory metadata (stat) without downloading content
thumbnailquerystringNoReturn a processed image (resize, format convert, blur, grayscale), shaped by format, size, width, height, resize, quality, blur, grayscale and bg: the same image as the WebDAV-style /{image}?thumbnail. Only where the deployment enabled thumbnail processing; returns 403 when disabled.
formatquerystringNoWith thumbnail: output image format. Allowed values: jpeg, png, webp, gif, bmp. Default: jpeg.
sizequerystringNoWith thumbnail: target size as WIDTHxHEIGHT
widthqueryintegerNoWith thumbnail: target width in pixels
heightqueryintegerNoWith thumbnail: target height in pixels
resizequerystringNoWith thumbnail: how the image fits the target size. Allowed values: fit, fill, cover, exact. Default: fit.
qualityquerystringNoWith thumbnail: output quality. Allowed values: low, medium, high. Default: medium.
blurquerynumberNoWith thumbnail: Gaussian blur radius
grayscalequerystringNoWith thumbnail: convert to grayscale
bgquerystringNoWith thumbnail: background color for transparent areas
grepquerystringNoSearch file or directory contents for a regex pattern (or literal if fixed_string=true). Only where the deployment enabled content search.
ignore_casequerybooleanNoCase-insensitive grep matching. Default: false.
fixed_stringquerybooleanNoTreat grep pattern as literal string, not regex. Default: false.
globquerystringNoWithout grep, finds files and folders matching this glob (e.g. **/*.rs, src/**/*.{ts,tsx}); directory paths only, where the deployment enabled search. With grep, the content-search file filter.
contextqueryintegerNoNumber of context lines before/after each grep match. Default: 0.
max_countqueryintegerNoMax matches per file for grep. Default: 50.
max_matchesqueryintegerNoTotal max matches across all files for grep. Default: 500.
max_depthqueryintegerNoDirectory recursion depth for grep. Default: 50.
max_filesizequeryintegerNoSkip files larger than this (bytes) during grep. Default: 10485760.
timeoutqueryintegerNoGrep timeout in seconds. Default: 30.
no_ignorequerybooleanNoAlso search files excluded by .gitignore (inside a git repository), .ignore, .git/info/exclude and the global git excludes. Default: false.
hiddenquerybooleanNoAlso search names starting with ., which are otherwise skipped unless an ignore file whitelists them. .git folders found inside the searched folder are still skipped, and the server’s configured hidden paths still apply. Refused with 403 for an account that may only list this path. Default: false.
max_resultsqueryintegerNoMax entries returned for glob search. Default: 1000.
max_files_scannedqueryintegerNoMax filesystem entries scanned during glob search. Default: 100000.
sortquerystringNoSort glob results by mtime (default), name, or size. Allowed values: mtime, name, size.
orderquerystringNoSort order for glob results. Default: desc for mtime, asc for name / size. Allowed values: asc, desc.
linesquerystringNoExtract 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.
historyquerystringNoList all revisions of a file. Returns JSON with a revisions array; paginate via after_id. Mutually exclusive with at / revision / diff.
atquerystringNoRead file content at a point in time. Accepts RFC3339 timestamp or Unix milliseconds. Mutually exclusive with history / revision / diff. Composable with ?lines, ?hash, ?base64.
revisionqueryintegerNoRead file content by stable per-path sequence number. Mutually exclusive with history / at / diff. Composable with ?lines, ?hash, ?base64.
diffquerystringNoCompute 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_seqqueryintegerNoSource revision seq number for ?diff. Mutually exclusive with from_ts.
from_tsquerystringNoSource timestamp for ?diff (RFC3339 or Unix ms). Mutually exclusive with from_seq.
to_seqqueryintegerNoTarget revision seq number for ?diff. Mutually exclusive with to_ts. Default: current file on disk.
to_tsquerystringNoTarget timestamp for ?diff (RFC3339 or Unix ms). Mutually exclusive with to_seq.
after_idqueryintegerNoCursor for ?history pagination. Returns entries with id > after_id.
limitqueryintegerNoMax entries to return for ?history. Default: 100.
zipquerystringNoDownload a directory as a streaming zip archive (bare flag, e.g. ?zip). Local directories only, and only where the deployment enabled archive downloads (403 otherwise). Same behavior as the WebDAV-style /{directory}?zip.
qquerystringNoTwo roles. On a directory (without thumbnail): search the names and paths below it for this text, case-insensitive; at most 512 bytes of UTF-8, measured before and after lowercasing (longer is refused with 400, not truncated); only where the deployment enabled search (403 otherwise). With thumbnail: JPEG quality, 1-100 (default 85); only JPEG output uses it.
RangeheaderstringNoFile download only: ask for part of the file, as ‘bytes=first-last’, ‘bytes=first-’ or ‘bytes=-suffix_length’. A last position past the end is clamped to the last byte, and a suffix longer than the file selects all of it. One satisfiable range answers 206 with Content-Range; several answer 206 as multipart/byteranges for a local file, while a remote file (with backend) answers 200 with the whole file. Ranges that cannot be satisfied are dropped from a list, and 416 comes only when none is left. A malformed header, another unit or more than 100 ranges is ignored (200, whole file). HEAD ignores Range.
If-RangeheaderstringNoFile download only: honour Range only if the file still has this ETag, exactly; otherwise answer 200 with the whole file. A date never matches, since two versions saved within the same second share it. A remote file’s (with backend) ETag is weak, so with If-Range a remote file is always sent whole.

The body is one of:

  • a files_FileListing JSON object for a folder (or for ?q),
  • a files_FileStatResponse JSON object for ?stat,
  • a files_FileHashResponse JSON object for ?hash,
  • a files_FileBase64Response JSON object for ?base64,
  • a files_ArchiveContents JSON object for ?preview / ?contents,
  • a files_GrepResults JSON object for ?grep,
  • a files_GlobResults JSON object for ?glob,
  • the raw file body as application/octet-stream,
  • a streaming zip archive as application/zip (when ?zip is set on a directory),
  • revision history (with ?history), historical content (with ?at or ?revision), or a unified diff (with ?diff).

File content comes as text/plain for ?lines and with the file’s own Content-Type otherwise.

Directory listing:

{
"path": "/api/v1/files/",
"count": 2,
"entries": [
{
"name": "src",
"is_dir": true,
"size": 8,
"modified": 1717000123
},
{
"name": "index.ts",
"is_dir": false,
"size": 4096,
"modified": 1717000456,
"revisions": 14
}
]
}

Grep results:

{
"path": "/api/v1/files/src",
"pattern": "TODO",
"matches": [
{
"path": "/api/v1/files/src/index.ts",
"line_number": 42,
"column_byte": 4,
"line": "// TODO: refactor parser",
"context_before": [],
"context_after": []
}
],
"total_matches": 1,
"total_files_matched": 1,
"total_files_searched": 8,
"truncated": false,
"duration_ms": 17
}

Glob results:

{
"path": "/api/v1/files/src",
"pattern": "**/*.ts",
"entries": [
{
"name": "/api/v1/files/src/index.ts",
"is_dir": false,
"size": 4096,
"modified": 1717000456
}
],
"count": 1,
"total_scanned": 12,
"truncated": false,
"duration_ms": 4
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
// Directory listing
await client.files.get('/');
// Stat a file
await client.files.get('/README.md', { stat: '' });
// Grep for TODO across src
await client.files.get('/src', { grep: 'TODO', ignore_case: true, max_count: 50 });
// Glob for TypeScript files
await client.files.get('/src', { glob: '**/*.ts', sort: 'mtime', order: 'desc' });
// Read lines 10-50
await client.files.get('/README.md', { lines: '10-50' });
// Point-in-time read
await client.files.get('/README.md', { at: '2024-05-30T12:00:00Z' });
// Unified diff between two revisions
await client.files.get('/README.md', { diff: '', from_seq: 12, to_seq: 17 });

List the contents of the root directory the Files service is serving. The response is the file manager page (text/html) by default, the same listing as GET /{path} for the root folder, or, with ?json, a structured JSON document. With ?download the browser is forced to save the response rather than render it.

This endpoint is also the embed view: pass the page in an <iframe> and it will lay itself out as a framed file browser. Set embedderOrigin to the embedding page’s origin so the page can communicate its theme and layout back to the parent. For details on framing and the postMessage protocol the page uses, see the embed URLs guide.

This endpoint accepts no request body.

NameInTypeRequiredDescription
jsonquerystringNoReturn JSON format instead of HTML
simplequerystringNoReturn simple text listing
sortquerystringNoSort by field. Allowed values: name, mtime, size.
orderquerystringNoSort order. Allowed values: asc, desc.
hashquerystringNoGet SHA256 hash of file (returns plain text hash)
sha256querystringNoGet SHA256 hash of file (alias for hash)
base64querystringNoGet file content as base64 encoded string
editquerystringNoOpen file in Web UI editor (requires allow-upload permission)
viewquerystringNoOpen file in a read-only Web UI page: the text is shown with no Save, rename, move or delete.
downloadquerystringNoFor file paths only: force browser download (Content-Disposition: attachment). Accepted values: empty, 1, or true. For directory paths, ?download is the URL download-manager operation.
content-typequerystringNoOverride Content-Type header for file downloads
historyquerystringNoList all revisions of a file. Returns JSON with a revisions array; paginate via after_id. Mutually exclusive with at / revision / diff.
atquerystringNoRead file content at a point in time. Accepts RFC3339 timestamp or Unix milliseconds. Mutually exclusive with history / revision / diff. Composable with ?lines, ?hash, ?base64.
revisionqueryintegerNoRead file content by stable per-path sequence number. Mutually exclusive with history / at / diff. Composable with ?lines, ?hash, ?base64.
diffquerystringNoCompute 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_seqqueryintegerNoSource revision seq number for ?diff. Mutually exclusive with from_ts.
from_tsquerystringNoSource timestamp for ?diff (RFC3339 or Unix ms). Mutually exclusive with from_seq.
to_seqqueryintegerNoTarget revision seq number for ?diff. Mutually exclusive with to_ts. Default: current file on disk.
to_tsquerystringNoTarget timestamp for ?diff (RFC3339 or Unix ms). Mutually exclusive with to_seq.
after_idqueryintegerNoCursor for ?history pagination. Returns entries with id > after_id.
limitqueryintegerNoMax entries to return for ?history. Default: 100.
themequerystringNoHTML page only: colour theme of the page. Default oc-1. Allowed values: oc-1, aura, ayu, carbonfox, catppuccin, dracula, gruvbox, monokai, nightowl, nord, onedarkpro, shadesofpurple, solarized, tokyonight, vesper.
colorSchemequerystringNoHTML page only: light or dark colour scheme. Without it the page follows the system setting. Allowed values: light, dark.
fontquerystringNoHTML page only: monospace font of the editor and listing. Allowed values: ibm-plex-mono, cascadia-code, fira-code, hack, inconsolata, intel-one-mono, iosevka, jetbrains-mono, meslo-lgs, roboto-mono, source-code-pro, ubuntu-mono.
fontSizequeryintegerNoHTML page only: editor font size in pixels. Default 14.
embedderOriginquerystringNoHTML page only: origin of the page that embeds this one, such as https://app.example.com. The page then accepts theme and layout messages from that origin and tells it when it is ready. Only https origins are accepted.
chromelessquerybooleanNoHTML page only: hide the header, sidebar, preview, footer and borders at once. Each can be turned back on with its own parameter set to false.
borderlessquerybooleanNoHTML page only: hide the page borders.
hideHeaderquerybooleanNoHTML page only: hide the header bar.
hideSidebarquerybooleanNoHTML page only: hide the sidebar.
hidePreviewquerybooleanNoHTML page only: hide the preview pane.
hideFooterquerybooleanNoHTML page only: hide the footer.
embedBgquerystringNoHTML page only: transparent lets the background of the embedding page show through.

A directory listing, the raw bytes of the response (with Content-Disposition: attachment when ?download is set), or the browser-rendered file manager page (text/html).

Directory listing in JSON:

{
"href": "/files/",
"kind": "Index",
"user": null,
"auth": false,
"dir_exists": true,
"uri_prefix": "/files/",
"allow_delete": false,
"allow_upload": false,
"allow_archive": false,
"allow_search": true,
"paths": [
{
"name": "README.md",
"path_type": "File",
"size": 2048,
"mtime": 1717000000000,
"revisions": null
},
{
"name": "src",
"path_type": "Dir",
"size": 12,
"mtime": 1717000123000,
"revisions": null
}
]
}
Terminal window
curl "https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com/files/?json"
Terminal window
curl "https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com/files/?json&sort=mtime&order=desc"
Terminal window
curl "https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com/files/?chromeless=true&colorScheme=dark&embedBg=transparent"