# Cloud Storage

**Page:** foundation/storage/cloud

[Download Raw Markdown](./foundation/storage/cloud.md)

---

# Cloud Storage

**Connect your container to Google Drive, Dropbox, S3, and 63 cloud providers through a single HTTP API.** This capability is powered by **hoody-kit's hoody-files service**—not a Foundation-level feature, but so essential we document it here.


**About this page:** Cloud storage is powered by [hoody-files](/kit/files/), part of the Hoody Kit, not the core Hoody API. This page covers **cloud mounting only**—a subset of hoody-files' capabilities.

For complete hoody-files documentation (cloud, protocols, encryption, advanced backends), see the [Hoody Files API Reference](/api/files/).


**The magic:** hoody-files makes ANY storage backend **both HTTP-accessible AND POSIX-mountable**. Access Google Drive via HTTP API or mount it like a local directory—your choice.

---

## API Endpoints Summary

**Complete hoody-files documentation:**

**Overview:**
- **[Hoody Files Overview →](/api/files/)** - Service capabilities and architecture

**Mounting Cloud Storage:**
- **[Cloud Storage →](/api/files/mount/cloud/)** - Google Drive, Dropbox, OneDrive, Box, pCloud, etc.
- **[Object Storage →](/api/files/mount/object/)** - S3, Azure Blob, Google Cloud Storage, Backblaze B2, Wasabi
- **[File Protocols →](/api/files/mount/protocols/)** - SFTP, FTP, WebDAV, SMB/CIFS

**File Operations:**
- **[Reading Files →](/api/files/reading/)** - Stream content via HTTP
- **[Downloading Files →](/api/files/downloading/)** - Download with verification
- **[File Metadata →](/api/files/metadata/)** - Get size, type, modified time
- **[File Hashing →](/api/files/hashing/)** - SHA256 integrity verification
- **[Directory Listing →](/api/files/directories/)** - Browse with sorting/filtering

**Backend Management:**
- **[Managing Backends →](/api/files/managing-backends/)** - Connect, test, disconnect
- **[Quick Start →](/api/files/quick-start/)** - Complete workflow example

---

## What is hoody-files Cloud Mounting?

**hoody-files transforms cloud storage APIs into HTTP endpoints AND mountable filesystems.**

**The transformation:**

```
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
   └─────────────────┘
```

**ANY backend becomes:**
- ✅ **HTTP-accessible** via REST API (language-agnostic)
- ✅ **POSIX-mountable** via FUSE (use ls, cp, cat, standard tools)
- ✅ **Unified interface** (same API for all 63 providers)

**The core idea:**

```bash
# Instead of learning 63 different APIs:
# - Google Drive API (OAuth, pagination, MIME types)
# - Dropbox API (cursors, batching, webhooks)
# - S3 API (buckets, keys, multipart uploads)
# ... 60 more APIs

# Use ONE unified HTTP API:
GET /api/v1/files/{path}?backend={backend_id}

# Works identically for Google Drive, S3, Dropbox, OneDrive, etc.
```

**One API to access 63 providers:**

See the [complete expandable list below](#63-supported-storage-backends) for all supported providers.

---

## How It Works

### 1. Connect Backend (One-Time Setup)

> **Prerequisite — OAuth credentials.** OAuth-backed providers (Google Drive, Dropbox, OneDrive, Box, …) need a `client_id` / `client_secret` from the provider console and an initial `token` from an OAuth consent flow. Either run `hoody files backends connect drive` (interactive — opens a browser, completes the flow, and captures the token for you), or paste pre-minted values as shown below. Key/secret backends (S3, B2, etc.) need the provider's access-key pair instead.

**Mount a storage provider:**


  
    ```bash
    curl -X POST "http://localhost:5000/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...\"}"
      }'
    
    # Response: {"id": "backend_drive_abc123"}
    ```
  
  
  
    ```bash
    curl -X POST "http://localhost:5000/api/v1/backends/dropbox" \
      -H "Content-Type: application/json" \
      -d '{
        "client_id": "your-client-id",
        "client_secret": "your-secret",
        "token": "{\"access_token\":\"sl.B...\"}"
      }'
    
    # Response: {"id": "backend_dropbox_xyz789"}
    ```
  
  
  
    ```bash
    curl -X POST "http://localhost:5000/api/v1/backends/s3" \
      -H "Content-Type: application/json" \
      -d '{
        "provider": "AWS",
        "access_key_id": "AKIAIOSFODNN7EXAMPLE",
        "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        "region": "us-east-1"
      }'
    
    # Response: {"id": "backend_s3_def456"}
    ```
  


**Backend connection is persistent.** Configure once, use forever.

### 2. Access Files via Unified API

**Now all backends use the same HTTP API:**


  
    ```bash
    # Read file from any connected backend
    hoody files get Documents/report.pdf --backend backend_drive_abc123

    # List directory on a backend (get lists directory paths too)
    hoody files get Documents/ --backend backend_s3_def456
    ```
  
  
    ```typescript
    const containerClient = await client.withContainer({
      id: CONTAINER_ID,
      project_id: PROJECT_ID,
      server: SERVER
    });

    // Read from Google Drive — same API for all 63 providers
    const driveFile = await containerClient.files.get(
      'Documents/report.pdf',
      { backend: 'backend_drive_abc123' }
    );

    // Read from S3 — just change the backend parameter
    const s3File = await containerClient.files.get(
      'Documents/report.pdf',
      { backend: 'backend_s3_def456' }
    );
    ```
  
  
    ```bash
    # Read from Google Drive
    curl "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.icu/api/v1/files/Documents/report.pdf?backend=backend_drive_abc123"

    # Read from Dropbox — same endpoint, different backend
    curl "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.icu/api/v1/files/Documents/report.pdf?backend=backend_dropbox_xyz789"

    # Read from S3 — same API, different backends
    curl "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.icu/api/v1/files/Documents/report.pdf?backend=backend_s3_def456"
    ```
  


**The abstraction is complete:** Whether it's Google Drive, S3, or SFTP—the HTTP API is identical.

---

## 63 Supported Storage Backends

<details>
<summary><strong>📋 Click to see all 63 supported providers</strong></summary>

**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 (7)**
- Google Photos - Photo/video management
- Cloudinary - Image/video CDN
- ImageKit.io - Image optimization
- Git - Read-only repositories (fetched via the `fetch-from-git` file operation, not a `backends/` mount)
- Proton Drive - Zero-knowledge encryption
- iCloud Drive - Apple ecosystem
- Zoho WorkDrive - Workspace integration

**Utility/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/Specialized (4)**
- Hadoop HDFS - Big data
- OpenDrive - Cloud storage
- Akamai NetStorage - CDN storage
- Ulož.to - Czech file sharing

**Total: 63 backend types**

For detailed configuration parameters, see:
- [Cloud Storage API](/api/files/mount/cloud/) - Google, Dropbox, OneDrive, Box
- [Object Storage API](/api/files/mount/object/) - S3, Azure, GCS, B2
- [File Protocols API](/api/files/mount/protocols/) - SFTP, FTP, WebDAV, SMB

</details>

---

## Why Use hoody-files for Cloud Storage?

### Problem: Each Provider Has Different APIs

**Traditional approach** requires learning and implementing each provider's unique API:

```javascript
// 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: Completely different paradigm (buckets, keys, regions)
const s3 = new AWS.S3();
const file = await s3.getObject({Bucket: 'my-bucket', Key: 'folder/file.pdf'}).promise();

// You need 63 different implementations
```

### Hoody Solution: One Unified API

**hoody-files abstracts everything to simple HTTP:**

```bash
# Same API for all 63 providers - just change backend parameter
curl "http://localhost:5000/api/v1/files/folder/file.pdf?backend={backend_id}"

# Works for Google Drive, Dropbox, S3, OneDrive, Box, SFTP, WebDAV, etc.
```

**Benefits:**
- ✅ **One API to learn** (not 63)
- ✅ **Backend-agnostic code** (switch providers without code changes)
- ✅ **Automatic protocol translation** (HTTP → provider's native protocol)
- ✅ **Unified error handling** (consistent across all backends)

---

## Core Capabilities

**What you can do with any connected backend:**



Stream file contents via HTTP:

```bash
GET /api/v1/files/{path}?backend={id}
```

Works for text, binary, any file type.



Download with SHA256 verification:

```bash
GET /api/v1/files/{path}?backend={id}&hash
```

Integrity checked automatically.



Browse directories with JSON/HTML output:

```bash
GET /api/v1/files/{path}/?backend={id}&json
```

Sortable, filterable directory listings.



Get size, type, modified time:

```bash
HEAD /api/v1/files/{path}?backend={id}
```

Lightweight metadata queries.



**See:** [Hoody Files API](/api/files/) for complete operations.

---

## Quick Start Example

**Connect Google Drive and access files:**


  
    ```bash
    # Connect Google Drive
    curl -X POST "http://localhost:5000/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,
      "data": {
        "id": "backend_drive_abc123",
        "type": "drive"
      }
    }
    ```
  
  
  
    ```bash
    # List root directory
    curl "http://localhost:5000/api/v1/files/?backend=backend_drive_abc123&json"
    
    # Response: JSON object with an entries array
    {
      "path": "/",
      "entries": [
        {"name": "Documents", "is_dir": true, "size": 0},
        {"name": "Photos", "is_dir": true, "size": 0},
        {"name": "report.pdf", "is_dir": false, "size": 1048576}
      ],
      "count": 3
    }
    ```
  
  
  
    ```bash
    # Read file content
    curl "http://localhost:5000/api/v1/files/Documents/report.pdf?backend=backend_drive_abc123" \
      > report.pdf
    
    # File downloaded from Google Drive via HTTP
    ```
  


**Total setup time:** 1 minute. Now you have HTTP access to all your Google Drive files.

---

## Use Cases

### Multi-Provider Data Aggregation

**Access files from multiple cloud providers in one application:**

```bash
# Mount 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
```

**Perfect for:** Backup verification, data migration, multi-cloud strategies.

### Backup to Cloud

**Automate backups from container to cloud storage:**

```bash
# Upload container backup to Google Drive
tar czf backup.tar.gz /hoody/storage/myapp/

curl -X PUT "http://localhost:5000/api/v1/files/Backups/backup.tar.gz?backend=backend_drive_abc" \
  --data-binary "@backup.tar.gz"

# Hoody Files handles OAuth, chunking, retries
```

### Process Cloud-Stored Data

**Read data from cloud, process in container, write results back:**

```bash
# Download dataset from S3
curl "http://localhost:5000/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 "http://localhost:5000/api/v1/files/Results/results.json?backend=backend_dropbox_xyz" \
  --data-binary "@results.json"

# Zero cloud SDK integration - pure HTTP
```

### Serve Files from Cloud

**Make cloud storage files accessible via HTTP:**

```bash
# Mount S3 bucket
POST /backends/s3 {"bucket": "my-public-files"}

# Now serve files via Hoody Proxy
GET https://{project}-{container}-files.../api/v1/files/images/logo.png?backend=backend_s3_abc

# Cloud storage becomes HTTP file server
```

---

## Backend Categories

### Cloud Storage (OAuth-based)

**Consumer-focused cloud services with OAuth authentication:**

- 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:** [Cloud Storage API](/api/files/mount/cloud/) for mounting instructions.

### Object Storage (S3-compatible)

**Developer-focused object storage with 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:** [Object Storage API](/api/files/mount/object/) for S3 configuration.

### File Protocols

**Connect to any server supporting standard 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:** [File Protocols API](/api/files/mount/protocols/) for protocol mounting.

---

## Key Features

### Unified API Across All Backends

**Same endpoints work for every provider:**


  
    ```bash
    # List directory — works for ALL backends
    hoody files get folder/ --backend $BACKEND_ID

    # Read file — works for ALL backends
    hoody files get folder/file.txt --backend $BACKEND_ID
    ```
  
  
    ```typescript
    // List directory — works for ALL backends
    // (files.get returns the JSON listing for a directory path)
    const listing = await containerClient.files.get(
      'folder/',
      { backend: BACKEND_ID }
    );

    // Read file — works for ALL backends
    const file = await containerClient.files.get(
      'folder/file.txt',
      { backend: BACKEND_ID }
    );
    ```
  
  
    ```bash
    # List directory — works for ALL backends
    curl "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.icu/api/v1/files/folder/?backend=$BACKEND_ID&json"

    # Read file — works for ALL backends
    curl "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.icu/api/v1/files/folder/file.txt?backend=$BACKEND_ID"

    # Get metadata — works for ALL backends
    curl -I "https://$PROJECT-$CONTAINER-files-1.$SERVER.containers.hoody.icu/api/v1/files/folder/file.txt?backend=$BACKEND_ID"
    ```
  


**Switch backends = change one parameter:**

```javascript
// 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}`);
```

### Multiple Backend Mounting

**Connect unlimited backends simultaneously:**

```bash
# 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
```

### Backend-Agnostic Applications

**Build apps that work with any storage:**

```javascript
// 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.
```

---

## Common Workflows

### Cloud-to-Cloud Transfer

**Transfer files between providers without downloading locally:**

```bash
# Read from Google Drive
curl "http://localhost:5000/api/v1/files/backup.zip?backend=backend_drive_abc" \
  > backup.zip

# Upload to S3
curl -X PUT "http://localhost:5000/api/v1/files/backup.zip?backend=backend_s3_xyz" \
  --data-binary "@backup.zip"

# Transfer happens in container (fast server bandwidth)
```

### Multi-Cloud Backup Strategy

**Store backups across multiple providers for redundancy:**

```bash
# 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 "http://localhost:5000/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)
```

### Process Cloud Data in Container

**Read from cloud, process, upload results:**

```bash
# 1. Download dataset from Dropbox
curl "http://localhost:5000/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 "http://localhost:5000/api/v1/files/Results/analysis-results.json?backend=backend_drive_xyz" \
  --data-binary "@analysis-results.json"

# Cloud → Container → Cloud (all via HTTP)
```

---

## Best Practices

### 1. Use Service Accounts for Automation

**Consumer OAuth requires user interaction.** For automated systems, use service accounts:

```bash
# 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"
}
```

**Credentials don't expire** with user sessions—perfect for scheduled tasks.

### 2. Configure Read-Only When Possible

**Minimize security risk:**

```bash
# Google Drive: Read-only scope
{
  "scope": "drive.readonly"
}

# Prevents accidental modifications
# Limits damage if credentials compromised
```

### 3. Mount Backend Once, Use Everywhere

**Backend connection persists across container restarts:**

```bash
# 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
```

### 4. Test Backends After Mounting

```bash
# 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](/api/files/managing-backends/) for testing and troubleshooting.

### 5. Use Encryption Layer for Sensitive Data

**Add zero-knowledge encryption to any backend:**

```bash
# Mount encrypted wrapper
POST /backends/crypt
{
  "remote": "backend_drive_abc:/Encrypted",
  "password": "your-encryption-password"
}

# Now files are encrypted before upload
```

See: [Encryption Layer](/api/files/mount/encryption/) for zero-knowledge encryption.

---

## Useful Questions

### Does hoody-files download entire files to container before serving?

No. hoody-files **streams** content:
- For small files: Buffered and served
- For large files: Streamed chunk-by-chunk
- Container never stores entire cloud file locally

### Can I use hoody-files without mounting cloud storage?

Yes! hoody-files also provides:
- **Local filesystem access** (container's own files)
- **SFTP/WebDAV server** for [local mounting](/foundation/storage/mount-locally/)
- Access to container's internal filesystem via HTTP

Cloud mounting is optional—hoody-files works for local and cloud storage.

### What happens if OAuth token expires?

Requests fail with 401 Unauthorized. **Fix:**

```bash
# 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 mount the same provider multiple times?

Yes! Example: Personal and work Google Drive accounts:

```bash
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
```

### Does hoody-files support file uploads?

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

### What's the performance like compared to native SDKs?

**Streaming:** Near-native performance over the provider's native transport. Some backends (notably Google Drive) disable HTTP/2 by default pending an upstream fix, and fall back to HTTP/1.1 — expect slightly more per-request overhead there; others keep HTTP/2 enabled.

**Batch operations:** Slightly slower (HTTP overhead per request)

**For high-throughput:** Use cloud provider's native SDK inside container. Use hoody-files for **convenience** and **abstraction**, not maximum throughput.

---

## Troubleshooting

### Backend Connection Fails

**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:**
   ```bash
   # Test from container
   curl https://www.googleapis.com  # Google Drive
   curl https://api.dropboxapi.com  # Dropbox
   
   # Should return response (not timeout)
   ```

### Files Not Showing in Directory Listing

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

**Check:**

1. **Path is correct:**
   ```bash
   # 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

### Rate Limiting Errors

**Problem:** 429 Too Many Requests from cloud provider

**Solutions:**

1. **Implement exponential backoff:**
   ```javascript
   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:**
   ```bash
   # Mount 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

---

## What's Next

**Storage ecosystem:**
- **[Container Storage →](./)** - Understanding container filesystem
- **[Mount Locally →](./mount-locally/)** - SFTP/WebDAV for local file managers
- **[SQLite Driver →](./sqlite-drive/)** - Concurrent-write databases  
- **[Shared Storage →](./sharing-files/)** - Share directories between containers
- **[/ramdisk →](./ramdisk/)** - Ultra-fast RAM storage

**Deep dive into hoody-files:**
- **[Hoody Files Overview →](/api/files/)** - Complete service documentation
- **[Cloud Storage Mounting →](/api/files/mount/cloud/)** - Google Drive, Dropbox, OneDrive, Box
- **[Object Storage Mounting →](/api/files/mount/object/)** - S3, Azure, GCS, B2
- **[File Protocols →](/api/files/mount/protocols/)** - SFTP, FTP, WebDAV, SMB
- **[Quick Start Guide →](/api/files/quick-start/)** - Complete workflow walkthrough

**Understanding gained:**
- ✅ Cloud storage powered by hoody-kit's hoody-files (not core Hoody API)
- ✅ Unified HTTP API for 63 storage providers
- ✅ ANY backend becomes HTTP-accessible AND POSIX-mountable
- ✅ Backend-agnostic code (switch providers without code changes)
- ✅ No cloud SDKs needed (pure HTTP or standard filesystem tools)
- ✅ This page covers cloud mounting only (subset of hoody-files capabilities)

---

> **63 cloud providers. One HTTP API. One POSIX interface.**
> **Any backend → HTTP-accessible AND locally mountable.**

**The abstraction layer that makes cloud storage feel local and local storage feel like APIs.**