Skip to content
Hoody.com

hoody-files connects a container to Google Drive, Dropbox, S3, and 62 cloud providers through a single HTTP API. It is a hoody-kit service rather than a Foundation feature, but cloud mounting is documented here with the rest of container storage.

Every storage backend hoody-files supports is both HTTP-accessible and POSIX-mountable. You can read Google Drive through the HTTP API, or mount it and treat it as a local directory.


Complete hoody-files documentation:

Overview:

Mounting cloud storage:

File operations:

Backend management:


hoody-files turns a cloud storage API into HTTP endpoints and into a mountable filesystem.

Google Drive API (OAuth, MIME types, pagination complexity)
hoody-files abstraction
┌─────────────────┐
│ HTTP API │ ← curl, fetch, any HTTP client
│ POSIX Mount │ ← ls, cp, cat, any filesystem tool
└─────────────────┘

Every backend is reachable two ways:

  • HTTP-accessible through a REST API, from any language.
  • POSIX-mountable through FUSE, so ls, cp, cat, and other standard tools work on it.

The interface is the same for all 62 providers.

Terminal window
# Instead of learning 62 different APIs:
# - Google Drive API (OAuth, pagination, MIME types)
# - Dropbox API (cursors, batching, webhooks)
# - S3 API (buckets, keys, multipart uploads)
# ... 60 more APIs
# One unified HTTP API:
GET /api/v1/files/{path}?backend={backend_id}
# Works identically for Google Drive, S3, Dropbox, OneDrive, etc.

The full provider list is further down this page.


Prerequisite: OAuth credentials. OAuth-backed providers (Google Drive, Dropbox, OneDrive, Box, and so on) accept a client_id / client_secret from the provider console plus a token JSON blob from an OAuth consent flow. None of them are required: omit both credentials and an internal shared OAuth client is used instead (low performance; bringing your own client is recommended for full quota). The CLI is not interactive; pass the values as flags. For your own OAuth client, run hoody files backends connect drive -c <container-id> --client-id <id> --client-secret <secret>. To supply a pre-obtained provider token, use the HTTP request below; the current CLI incorrectly captures the subcommand’s --token as Hoody API authentication. The CLI prints only a success message and does not return the backend id, so run hoody files backends list -c <container-id> -o json afterwards to read it. Key/secret backends (S3, B2, etc.) need the provider’s access-key pair instead.

Connect a storage provider. The connection persists, so you configure a provider once and reuse it:

Terminal window
curl -X POST "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.com/api/v1/backends/drive" \
-H "Content-Type: application/json" \
-d '{
"client_id": "your-app.apps.googleusercontent.com",
"client_secret": "your-secret",
"token": "{\"access_token\":\"ya29...\"}"
}'
# 201 Response: {"success": true, "data": {"id": "9b4d3e2f5a6c7890", "backend_type": "drive", "type": "cloud", "mount_paths": []}}

Step 2: Access files through the unified API

Section titled “Step 2: Access files through the unified API”

Every connected backend answers the same requests, whether it is Google Drive, S3, or SFTP:

Terminal window
# Read file from any connected backend
hoody files get "Documents/report.pdf" --backend 9b4d3e2f5a6c7890 -c <container-id>
# List directory on a backend (get lists directory paths too)
hoody files get "Documents/" --backend 1a2b3c4d5e6f7080 -c <container-id>

All 62 supported providers

Major cloud storage (9)

  • Google Drive - OAuth, service accounts, team drives
  • Dropbox - OAuth, batch operations, business accounts
  • Microsoft OneDrive - Personal, Business, SharePoint
  • Box - OAuth, JWT service accounts
  • pCloud - EU/US data centers
  • MEGA - Username/password, encryption
  • Yandex Disk - OAuth, hard delete
  • Mail.ru Cloud - App passwords, speedup feature
  • Jottacloud - OAuth, version control

Object storage (12)

  • Amazon S3 / S3-compatible - AWS native plus MinIO, DigitalOcean Spaces, Cloudflare R2, Wasabi, Alibaba Cloud OSS (single s3 backend, provider selects the flavor)
  • Azure Blob Storage - Hot/cool/archive tiers
  • Azure Files - SMB in cloud
  • Google Cloud Storage - Standard/nearline/coldline/archive
  • Backblaze B2 - Cost-effective, CDN integration
  • Oracle Object Storage - OCI integration
  • OpenStack Swift - OpenStack deployments
  • QingStor - Asian provider
  • Storj - Decentralized storage
  • Tardigrade - Decentralized storage (Storj legacy endpoint)
  • Internet Archive - archive.org S3-compatible
  • Sia - Decentralized blockchain storage

File protocols (5)

  • SFTP/SSH - Secure file transfer
  • FTP/FTPS - Classic (with TLS option)
  • WebDAV - Nextcloud/ownCloud compatible
  • SMB/CIFS - Windows shares, NAS
  • HTTP/HTTPS - Read-only web servers

File sharing services (9)

  • 1Fichier - French file sharing
  • Gofile - Anonymous & authenticated
  • Pixeldrain - Direct file sharing
  • Put.io - Download completion
  • Linkbox - linkbox.to integration
  • Uptobox - Premium downloads
  • premiumize.me - Premium links
  • SugarSync - Cloud sync
  • PikPak - Cloud download manager

Enterprise services (7)

  • Citrix ShareFile - Enterprise sharing
  • Files.com - Managed file transfer
  • Enterprise File Fabric - Multi-cloud
  • Koofr - European (Digi Storage)
  • HiDrive - German cloud
  • Seafile - Open-source enterprise
  • Quatrix - Enterprise collaboration

Specialty services (6)

  • Google Photos - Photo/video management
  • Cloudinary - Image/video CDN
  • ImageKit.io - Image optimization
  • Proton Drive - Zero-knowledge encryption
  • iCloud Drive - Apple ecosystem
  • Zoho WorkDrive - Workspace integration

Utility and virtual backends (10)

  • Local - Container filesystem
  • Crypt - Zero-knowledge encryption
  • Compress - GZIP compression
  • Cache - Local caching layer
  • Chunker - Split large files
  • Hasher - Better checksums
  • Alias - Create shortcuts
  • Union - Merge with policies
  • Combine - Unified namespace
  • Memory - In-memory temporary

Legacy and specialized (4)

  • Hadoop HDFS - Big data
  • OpenDrive - Cloud storage
  • Akamai NetStorage - CDN storage
  • Ulož.to - Czech file sharing

Total: 62 backend types

Git repositories are also accessible read-only, but through the fetch-from-git file operation (?type=git) rather than a backends/ mount, so Git is not counted among the 62 backend types.

For detailed configuration parameters, see:


Without an abstraction layer, an application implements each provider’s own API:

// Google Drive: OAuth, MIME types, fileId abstraction
const drive = google.drive({version: 'v3', auth});
const file = await drive.files.get({fileId: 'abc123', alt: 'media'});
// Dropbox: different auth, different structure
const dbx = new Dropbox({accessToken: TOKEN});
const file = await dbx.filesDownload({path: '/folder/file.pdf'});
// S3: buckets, keys, and regions instead of paths
const s3 = new AWS.S3();
const file = await s3.getObject({Bucket: 'my-bucket', Key: 'folder/file.pdf'}).promise();
// You need 62 different implementations

hoody-files collapses those into one request shape:

Terminal window
# Same API for all 62 providers - just change backend parameter
curl "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.com/api/v1/files/folder/file.pdf?backend={backend_id}"
# Works for Google Drive, Dropbox, S3, OneDrive, Box, SFTP, WebDAV, etc.

You learn one API instead of 62. Application code names a backend id rather than a provider SDK, so moving from S3 to Dropbox changes a parameter and nothing else. hoody-files translates each HTTP call into the provider’s own protocol and reports errors in one format across every backend.


Every connected backend supports the same operations.

Read files

Stream file contents over HTTP:

Terminal window
GET /api/v1/files/{path}?backend={id}

This works for text, binary, and any other file type.

Verify a file hash

Get a file’s SHA256 hash, returned as plain text:

Terminal window
GET /api/v1/files/{path}?backend={id}&hash

Compare it against your local copy to check integrity.

List directories

Browse directories as JSON:

Terminal window
GET /api/v1/files/{path}/?backend={id}

Listings can be sorted and filtered.

Read file metadata

Get size, type, and modified time:

Terminal window
GET /api/v1/files/{path}?backend={id}&stat

These queries are lightweight.

See the Hoody Files API for the complete set of operations.


The three requests below connect the backend, list the root directory, and read a file. After that, every file in the account is reachable over HTTP.

Terminal window
# Connect Google Drive
curl -X POST "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.com/api/v1/backends/drive" \
-H "Content-Type: application/json" \
-d '{
"client_id": "your-app.apps.googleusercontent.com",
"client_secret": "your-client-secret",
"token": "{\"access_token\":\"ya29.a0...\"}"
}'
# Response includes backend ID
{
"success": true,
"message": "Google Drive backend connected successfully",
"data": {
"id": "9b4d3e2f5a6c7890",
"backend_type": "drive",
"type": "cloud",
"mount_paths": []
}
}

One application can read from several providers at once. This pattern covers backup verification, data migration, and multi-cloud setups:

Terminal window
# Connect all your storage
POST /backends/drive backend_drive_abc
POST /backends/dropbox backend_dropbox_xyz
POST /backends/s3 backend_s3_def
# Now access any file from any backend
GET /files/project-data.json?backend=backend_drive_abc
GET /files/project-data.json?backend=backend_dropbox_xyz
GET /files/project-data.json?backend=backend_s3_def
# Same API, different storage providers

A container can push its own backups to a cloud provider:

Terminal window
# Upload container backup to Google Drive
tar czf backup.tar.gz /hoody/storage/myapp/
curl -X PUT "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.com/api/v1/files/Backups/backup.tar.gz?backend=backend_drive_abc" \
--data-binary "@backup.tar.gz"
# Hoody Files handles OAuth, chunking, retries

Read from the cloud, process in the container, write the results back:

Terminal window
# Download dataset from S3
curl "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.com/api/v1/files/datasets/data.csv?backend=backend_s3_abc" > data.csv
# Process locally
python process.py data.csv > results.json
# Upload results to Dropbox
curl -X PUT "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.com/api/v1/files/Results/results.json?backend=backend_dropbox_xyz" \
--data-binary "@results.json"
# No cloud SDK involved; the transfers are plain HTTP

Cloud storage files can be exposed through a container URL:

Terminal window
# Connect S3 (the bucket is addressed in the path, e.g. my-public-files/images/logo.png)
POST /backends/s3 {"provider": "AWS", "access_key_id": "AKIA...", "secret_access_key": "...", "region": "us-east-1", "endpoint": "s3.us-east-1.amazonaws.com"}
# Now serve files via Hoody Proxy
GET https://{project}-{container}-files.../api/v1/files/images/logo.png?backend=backend_s3_abc
# S3 objects are now served over HTTP

Consumer cloud services that authenticate with OAuth:

  • Google Drive (team drives, service accounts)
  • Dropbox (batch operations, business accounts)
  • OneDrive (personal, business, SharePoint)
  • Box (JWT service accounts)
  • pCloud (EU/US data centers)

See the Cloud Storage API for mounting instructions.

Object stores that speak the S3 API:

  • AWS S3 (original)
  • Wasabi (cheaper than S3)
  • Backblaze B2 (affordable, fast)
  • DigitalOcean Spaces
  • Cloudflare R2 (zero egress fees)
  • Azure Blob Storage
  • Google Cloud Storage
  • Alibaba Cloud OSS

See the Object Storage API for S3 configuration.

Servers reachable over standard file protocols:

  • SFTP (secure file transfer over SSH)
  • FTP/FTPS (legacy file transfer)
  • WebDAV (Nextcloud, ownCloud, HTTP-based)
  • SMB/CIFS (Windows network shares, NAS devices)
  • HTTP/HTTPS (web servers, static file hosting)

See the File Protocols API for protocol mounting.


The path and query string do not change between providers. Only the backend id does.

Terminal window
# List a directory (identical for every backend)
hoody files get "folder/" --backend $BACKEND_ID -c <container-id>
# Read a file (identical for every backend)
hoody files get "folder/file.txt" --backend $BACKEND_ID -c <container-id>

Switching provider is a change to one variable:

// Change from S3 to Dropbox
const backend = 'backend_s3_abc'; // S3
const backend = 'backend_dropbox_xyz'; // Dropbox
// Rest of code unchanged
const file = await fetch(`/api/v1/files/data.json?backend=${backend}`);

There is no fixed limit on how many backends a container connects at the same time:

Terminal window
# Personal Google Drive
backend_drive_personal
# Work Google Drive
backend_drive_work
# AWS S3 production
backend_s3_prod
# AWS S3 backups
backend_s3_backup
# Dropbox archive
backend_dropbox_archive
# All accessible from one container via hoody-files

The backend can be a runtime choice rather than a build-time one:

// User chooses storage provider
const backend = userPreference; // 'backend_drive_abc' or 'backend_s3_xyz'
// App code doesn't care which provider
async function saveFile(path, content, backend) {
return fetch(`/api/v1/files/${path}?backend=${backend}`, {
method: 'PUT',
body: content
});
}
// Works with Google Drive, S3, Dropbox, OneDrive, etc.

Move a file between two providers without pulling it to your own machine:

Terminal window
# Read from Google Drive
curl "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.com/api/v1/files/backup.zip?backend=backend_drive_abc" \
> backup.zip
# Upload to S3
curl -X PUT "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.com/api/v1/files/backup.zip?backend=backend_s3_xyz" \
--data-binary "@backup.zip"
# The transfer runs in the container, on the server's bandwidth

Write the same backup to several providers for redundancy:

Terminal window
# Create backup
tar czf critical-data.tar.gz /hoody/storage/production/
# Upload to 3 different cloud providers
for backend in backend_s3_primary backend_gcs_backup backend_backblaze_archive; do
curl -X PUT "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.com/api/v1/files/Backups/critical-data.tar.gz?backend=$backend" \
--data-binary "@critical-data.tar.gz"
done
# Same data in 3 locations (AWS, Google, Backblaze)

The same three stages written out step by step:

Terminal window
# 1. Download dataset from Dropbox
curl "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.com/api/v1/files/datasets/raw-data.csv?backend=backend_dropbox_abc" \
> raw-data.csv
# 2. Process in container
python analyze.py raw-data.csv > analysis-results.json
# 3. Upload results to Google Drive
curl -X PUT "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.com/api/v1/files/Results/analysis-results.json?backend=backend_drive_xyz" \
--data-binary "@analysis-results.json"
# Cloud → Container → Cloud (all via HTTP)

Consumer OAuth requires a person to complete the consent flow. Service account credentials do not expire with a user session, so scheduled tasks keep working:

Terminal window
# Google Drive: Service Account (no user interaction)
{
"service_account_file": "/keys/service-account.json",
"team_drive": "0ABC123xyz"
}
# Box: JWT Authentication
{
"box_config_file": "/keys/box-config.json",
"box_sub_type": "enterprise"
}

A read-only scope removes write access from the credential:

Terminal window
# Google Drive: Read-only scope
{
"scope": "drive.readonly"
}
# Prevents accidental modifications
# Limits damage if credentials compromised

A backend connection survives container restarts:

Terminal window
# Connect backend once
POST /backends/drive backend_drive_abc
# Use in all future requests
GET /files/data.json?backend=backend_drive_abc
# Connection remains active until explicitly disconnected
Terminal window
# Verify connection works
GET /api/v1/files/?backend=backend_drive_abc
# Should return directory listing
# If error: OAuth expired, credentials wrong, or network issue

See Managing Backends for testing and troubleshooting.

Add an encryption layer for sensitive data

Section titled “Add an encryption layer for sensitive data”

The crypt backend wraps another backend with zero-knowledge encryption:

Terminal window
# Connect the encrypted wrapper
POST /backends/crypt
{
"remote": "backend_drive_abc:/Encrypted",
"password": "your-encryption-password"
}
# Now files are encrypted before upload

See Encryption Layer for zero-knowledge encryption.


Does hoody-files download a whole file first?

Section titled “Does hoody-files download a whole file first?”

No. hoody-files streams content: it buffers small files and sends large ones chunk by chunk. The container never stores a complete copy of the cloud file.

Can I use hoody-files without mounting cloud storage?

Section titled “Can I use hoody-files without mounting cloud storage?”

Yes. hoody-files also provides:

  • Local filesystem access to the container’s own files, over the same HTTP API.
  • WebDAV server for local mounting. SFTP mounting is provided separately, by the Hoody API’s SSH proxy.

Cloud mounting is optional. hoody-files works the same way for local storage.

Requests fail with 401 Unauthorized. Disconnect the backend and reconnect it with a fresh token:

Terminal window
# Disconnect expired backend
DELETE /api/v1/backends/backend_drive_abc
# Reconnect with fresh OAuth token
POST /api/v1/backends/drive
{"client_id": "...", "client_secret": "...", "token": "{\"access_token\":\"NEW_TOKEN\"}"}

Can I connect the same provider more than once?

Section titled “Can I connect the same provider more than once?”

Yes. Personal and work Google Drive accounts can both be connected:

Terminal window
POST /backends/drive {"token": "PERSONAL_TOKEN"} backend_drive_personal
POST /backends/drive {"token": "WORK_TOKEN"} backend_drive_work
# Access both simultaneously
GET /files/data.json?backend=backend_drive_personal
GET /files/data.json?backend=backend_drive_work

Yes, with HTTP PUT. Send the file body to PUT /api/v1/files/{path}?backend={id} (or at the root /{path}). See Hoody Files API for upload endpoints.

What’s the performance like compared to native SDKs?

Section titled “What’s the performance like compared to native SDKs?”

Streaming: close to native speed, over the provider’s own transport. Some backends (notably Google Drive) disable HTTP/2 by default pending an upstream fix and fall back to HTTP/1.1, which adds a little per-request overhead. Other backends keep HTTP/2 enabled.

Batch operations: slightly slower, because each request carries HTTP overhead.

High throughput: run the cloud provider’s own SDK inside the container. hoody-files trades maximum throughput for a single interface.


Problem: POST /backends/{provider} returns error

Solutions:

  1. OAuth token issues:

    • Verify token is valid and not expired
    • Check OAuth scopes include required permissions
    • Regenerate token if necessary
  2. Credential errors:

    • S3: Verify access_key_id and secret_access_key
    • SFTP: Check SSH key or password
    • Test credentials with provider’s native tools first
  3. Network connectivity:

    Terminal window
    # Test from container
    curl https://www.googleapis.com # Google Drive
    curl https://api.dropboxapi.com # Dropbox
    # Should return response (not timeout)

Problem: GET /files/?backend={id} returns empty or incomplete

Check:

  1. Path is correct:

    Terminal window
    # Root directory
    GET /files/?backend={id}
    # Specific folder
    GET /files/Documents/?backend={id}
  2. Backend has data:

    • Log into cloud provider’s web interface
    • Verify files exist in expected location
  3. Permissions:

    • OAuth scopes allow listing
    • Service account has access to folder/bucket

Problem: 429 Too Many Requests from cloud provider

Solutions:

  1. Implement exponential backoff:

    async function fetchWithRetry(url, retries = 3) {
    for (let i = 0; i < retries; i++) {
    const response = await fetch(url);
    if (response.status !== 429) return response;
    await sleep(Math.pow(2, i) * 1000); // 1s, 2s, 4s
    }
    }
  2. Use caching:

    Terminal window
    # Connect a cache layer
    POST /backends/cache
    {"remote": "backend_drive_abc:", "chunk_size": "10M"}
    # Repeated requests served from cache
  3. Reduce request frequency:

    • Batch operations where possible
    • Cache directory listings
    • Use webhooks instead of polling

Storage pages:

hoody-files reference: