Directory Listing
Section titled “Directory Listing”Listing
The directory listing endpoints combine filesystem management with archive operations on the container files service. Use them to create directories, list and track archive extractions, extract full or selective entries from ZIP and TAR archives, preview archive contents or read individual files without extracting, and download directories as ZIP archives.
All endpoints on this page are served by the container-scoped files instance, addressed at:
https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com
The examples below substitute a concrete container id (67e89abc123def456789abcd-890abcdef12345678901cdef) and the node-us server; replace these with your own project, container, and server identifiers in production.
Archives
Section titled “Archives”Extraction history
Section titled “Extraction history”GET /?extraction_history
Returns the history of past archive extractions, including both completed and failed operations. Use this endpoint to audit extraction activity or diagnose failures.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
extraction_history | query | string | Yes | Presence flag (empty value) that selects the extraction-history response |
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-us.containers.hoody.com/?extraction_history" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.archives.getHistory({ extraction_history: '' });{ "history": [ { "id": "0d3a8e91-7b4c-4f12-9d6e-1a2b3c4d5e6f", "archive_path": "/data/uploads/release.zip", "dest_path": "/data/projects/release", "start_time": 1716302412, "end_time": 1716302428, "status": "completed", "selective": false, "selective_path": null, "total_bytes": 15728640, "extracted_bytes": 15728640, "total_files": 312, "extracted_files": 312, "error": null }, { "id": "1e4b9f02-8c5d-4a23-8e7f-2b3c4d5e6f70", "archive_path": "/data/uploads/snapshot.tar.gz", "dest_path": "/data/projects/snapshot", "start_time": 1716299000, "end_time": 1716299015, "status": "failed", "selective": true, "selective_path": "src/", "total_bytes": 52428800, "extracted_bytes": 12582912, "total_files": 1024, "extracted_files": 240, "error": "PATH_TRAVERSAL_BLOCKED" } ]}List active extractions
Section titled “List active extractions”GET /?extractions
Returns the progress of currently running archive extractions on the files service.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
extractions | query | string | Yes | Presence flag (empty value) that selects the active-extractions response |
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-us.containers.hoody.com/?extractions" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.archives.listActive({ extractions: '' });{ "extractions": [ { "id": "0d3a8e91-7b4c-4f12-9d6e-1a2b3c4d5e6f", "archive_path": "/data/uploads/dataset.tar.gz", "dest_path": "/data/projects/dataset", "start_time": 1716302412, "status": "running", "selective": false, "selective_path": null, "total_bytes": 1073741824, "extracted_bytes": 536870912, "total_files": 8421, "extracted_files": 4102, "percentage": 50.0 } ]}List active extractions (API)
Section titled “List active extractions (API)”GET /api/v1/extractions
Returns the progress of currently running archive extractions via the versioned API path. This endpoint takes no parameters.
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-us.containers.hoody.com/api/v1/extractions" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.archives.listGlobal();{ "extractions": [ { "id": "0d3a8e91-7b4c-4f12-9d6e-1a2b3c4d5e6f", "archive_path": "/data/uploads/dataset.tar.gz", "dest_path": "/data/projects/dataset", "start_time": 1716302412, "status": "running", "selective": false, "selective_path": null, "total_bytes": 1073741824, "extracted_bytes": 536870912, "total_files": 8421, "extracted_files": 4102, "percentage": 50.0 } ]}Extract archive
Section titled “Extract archive”GET /{archive}?extract
Extracts a ZIP, TAR, or compressed TAR archive to a destination directory. Pass ?extract (empty value) to extract the entire archive, or ?extract=src/ for a selective extraction that pulls only matching entries.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
archive | path | string | Yes | Path to the archive file to extract |
extract | query | string | Yes | Empty value for full extraction; a path (e.g. src/ or lib/) for selective extraction |
dest | query | string | No | Destination directory name (default: archive name) |
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-us.containers.hoody.com/uploads/release.zip?extract" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.archives.extract('/uploads/release.zip', { extract: '' });{ "success": true, "message": "Archive extracted successfully", "extraction_id": "0d3a8e91-7b4c-4f12-9d6e-1a2b3c4d5e6f", "destination": "/data/projects/release", "extracted_files": 312, "extracted_bytes": 15728640, "selective": false, "selective_path": null, "error": null}{ "success": false, "message": "Extraction failed: suspicious compression ratio", "extraction_id": "0d3a8e91-7b4c-4f12-9d6e-1a2b3c4d5e6f", "destination": "/data/projects/release", "extracted_files": 0, "extracted_bytes": 0, "selective": false, "selective_path": null, "error": "ZIP_BOMB_DETECTED"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_ARCHIVE_FORMAT | Invalid archive format | File is not a valid archive or format is unsupported | Verify file is a supported archive format (zip, tar, tar.gz, tar.bz2, tar.xz) |
ARCHIVE_TOO_LARGE | Archive exceeds size limit | Archive total size exceeds configured maximum extraction size | Contact administrator to increase extraction size limit or extract manually |
TOO_MANY_FILES | Too many files in archive | Archive contains more files than allowed maximum | Contact administrator to increase file count limit or extract in smaller batches |
ZIP_BOMB_DETECTED | Potential zip bomb detected | Archive has suspicious compression ratio indicating potential zip bomb | Verify archive source is trusted, contact administrator if legitimate |
PATH_TRAVERSAL_BLOCKED | Path traversal attempt blocked | Archive contains files attempting to escape extraction directory | Archive may be malicious, verify source and re-create archive without path traversal |
{ "success": false, "error": "Archive extraction is disabled on this server"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
EXTRACTION_FORBIDDEN | Extraction not allowed | Server is not configured to allow archive extraction | Contact administrator to enable --allow-extract flag |
Extract file from archive
Section titled “Extract file from archive”GET /{archive}?extract_file
Extracts a single file or directory from inside a ZIP, TAR, or compressed TAR archive to a destination directory. Only the specified entry (and its children if a directory) is extracted, leaving other archive contents untouched.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
archive | path | string | Yes | Path to archive file |
extract | query | string | Yes | Path of the file or directory inside the archive to extract (e.g. src/ or lib/) |
dest | query | string | No | Destination directory name (default: archive name) |
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-us.containers.hoody.com/uploads/release.zip?extract_file&extract=src/" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.archives.extractFile('/uploads/release.zip', { extract: 'src/' });{ "success": true, "message": "Selective extraction completed", "extraction_id": "1e4b9f02-8c5d-4a23-8e7f-2b3c4d5e6f70", "destination": "/data/projects/release", "extracted_files": 48, "extracted_bytes": 2097152, "selective": true, "selective_path": "src/", "error": null}{ "success": false, "message": "No entries matched the requested path", "extraction_id": null, "destination": null, "extracted_files": 0, "extracted_bytes": 0, "selective": true, "selective_path": "missing/", "error": "NO_MATCHING_ENTRIES"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_ARCHIVE_FORMAT | Invalid archive format | File is not a valid archive or format is unsupported | Verify file is a supported archive format (zip, tar, tar.gz, tar.bz2, tar.xz) |
INVALID_SELECTIVE_PATH | Invalid entry path | The entry path is invalid (empty, absolute, contains traversal, or null bytes) | Use a relative path without .. components (e.g. src/ or lib/) |
NO_MATCHING_ENTRIES | No matching entries | No entries in the archive matched the specified path | Use previewArchive to list archive contents and verify the entry path |
PATH_TRAVERSAL_BLOCKED | Path traversal attempt blocked | Archive contains files attempting to escape extraction directory | Archive may be malicious, verify source and re-create archive without path traversal |
{ "success": false, "error": "Archive extraction is disabled on this server"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
EXTRACTION_FORBIDDEN | Extraction not allowed | Server is not configured to allow archive extraction | Contact administrator to enable --allow-extract flag |
{ "success": false, "error": "Archive file not found"}Preview archive contents
Section titled “Preview archive contents”GET /{archive}?preview
Lists the contents of a ZIP, TAR, or compressed TAR archive without extracting it, or reads a specific file from the archive. Pass ?preview (empty value) to receive a JSON listing of all entries; pass ?preview=README.md to read the raw content of that file. The ?contents parameter is an alias for ?preview.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
archive | path | string | Yes | Path to archive file |
preview | query | string | No | Empty value lists archive contents; non-empty value reads a specific file from the archive (alias: ?contents) |
contents | query | string | No | Alias for ?preview |
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-us.containers.hoody.com/uploads/release.zip?preview" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.archives.preview('/uploads/release.zip', { preview: '' });{ "format": "zip", "total_files": 312, "total_size": 15728640, "total_compressed_size": 8388608, "entries": [ { "path": "src/index.js", "is_dir": false, "entry_type": "file", "size": 4096, "compressed_size": 1536, "modified_time": 1716200000, "permissions": 33188, "link_target": null }, { "path": "src/", "is_dir": true, "entry_type": "directory", "size": 0, "compressed_size": 0, "modified_time": 1716200000, "permissions": 16877, "link_target": null }, { "path": "link-to-readme", "is_dir": false, "entry_type": "symlink", "size": 12, "compressed_size": 12, "modified_time": 1716200000, "permissions": 41471, "link_target": "README.md" } ]}{ "success": false, "error": "Archive file is corrupted and cannot be read"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_ARCHIVE_FORMAT | Invalid archive format | File is not a valid ZIP, TAR, or compressed TAR archive | Verify file is a valid archive and format is supported (zip, tar, tar.gz, tar.bz2, tar.xz) |
CORRUPTED_ARCHIVE | Corrupted archive | Archive file is corrupted or incomplete | Re-download or re-upload the archive file |
{ "success": false, "error": "Archive entry is password-protected"}{ "success": false, "error": "Archive file or entry not found"}{ "success": false, "error": "File is too large for preview (max 100MB)"}View file from archive
Section titled “View file from archive”GET /{archive}?view_file
Reads and returns a single file from inside a ZIP, TAR, or compressed TAR archive without extracting the entire archive. The response body is the raw file content with an auto-detected MIME type, useful for inspecting individual files before deciding to extract the whole archive.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
archive | path | string | Yes | Path to archive file |
preview | query | string | Yes | Path of the file inside the archive to view (e.g. src/ or README.md) |
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-us.containers.hoody.com/uploads/release.zip?view_file&preview=README.md" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.archives.viewFile('/uploads/release.zip', { preview: 'README.md' });The response body is the raw file content streamed back as application/octet-stream (or the auto-detected MIME type). For a text file such as README.md, the body contains the file’s textual content; for binary files, the body contains the raw bytes.
{ "success": false, "error": "Invalid entry path: must be a relative path without .. components"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_ARCHIVE_FORMAT | Invalid archive format | File is not a valid ZIP, TAR, or compressed TAR archive | Verify file is a valid archive and format is supported (zip, tar, tar.gz, tar.bz2, tar.xz) |
INVALID_SELECTIVE_PATH | Invalid entry path | The entry path is invalid (empty, absolute, contains traversal, or null bytes) | Use a relative path without .. components (e.g. src/) |
{ "success": false, "error": "Archive entry is password-protected"}{ "success": false, "error": "Archive file or entry not found"}{ "success": false, "error": "File is too large for preview"}Download directory as ZIP
Section titled “Download directory as ZIP”GET /{directory}?zip
Creates a ZIP archive of the given directory and streams it back as the response body. The response is served as application/zip.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
directory | path | string | Yes | Path to the directory to package as a ZIP archive |
zip | query | string | Yes | Presence flag (empty value) that selects the ZIP download response |
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-us.containers.hoody.com/projects/release?zip" \ -H "Authorization: Bearer $HOODY_TOKEN" \ -o release.zipimport { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.archives.downloadAsZip('/projects/release', { zip: '' });The response body is the raw ZIP archive streamed as application/zip with the binary ZIP content. Save it directly to a file or pipe it through a ZIP reader.
{ "success": false, "error": "Archive download is disabled on this server"}Directories
Section titled “Directories”Create directory
Section titled “Create directory”MKCOL /{path}
Creates a new directory at the specified path. The container must have upload enabled (--allow-upload) and the calling user must hold write permissions for the parent path.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
path | path | string | Yes | Path of the directory to create |
curl -X MKCOL "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-us.containers.hoody.com/projects/new-release" \ -H "Authorization: Bearer $HOODY_TOKEN"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-files-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.directories.create('/projects/new-release');Directory created successfully. The response body is empty; the 201 status indicates success.
{ "success": false, "error": "Directory creation is disabled on this server"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
UPLOAD_FORBIDDEN | Directory creation not allowed | Server is not configured to allow directory creation | Contact administrator to enable --allow-upload flag |
INSUFFICIENT_PERMISSIONS | Insufficient permissions | User account does not have write permissions for this path | Contact administrator for write permissions |
{ "success": false, "error": "Directory already exists at /projects/new-release"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
DIRECTORY_EXISTS | Directory already exists | A directory with this name already exists at the specified path | Choose a different name or delete the existing directory first |