<!--
hoody-api Subskill (sdk)
Auto-generated by Hoody Skills Generator
Generated: 2026-06-20T00:04:24.264Z
Model: mimo-v2.5-pro
Mode: sdk


Tokens: 35517

DO NOT EDIT MANUALLY - Changes will be overwritten on next generation
-->

# hoody-api Subskill

## 1. Overview

### Purpose and Scope
hoody-api is the central platform API that manages all core infrastructure resources for the Hoody ecosystem. This service handles authentication, authorization, project organization, container lifecycle management, network configuration, billing, and administrative operations. It serves as the single source of truth for all platform resources and provides the interface between users, their containers, and the underlying infrastructure.

### When to Use
Use hoody-api for:
- **Account Management**: User authentication, registration, password resets, and 2FA
- **Resource Organization**: Creating and managing projects to group containers and resources
- **Container Operations**: Full lifecycle management of containers (create, start, stop, configure)
- **Network & Security**: Configuring container networks, firewall rules, and proxy permissions
- **Billing & Wallet**: Managing payments, invoices, balances, and AI credit transfers
- **Team Collaboration**: Creating pools, managing members, and sharing resources
- **Server Rental**: Browsing and renting dedicated servers
- **Storage Management**: Creating and managing storage shares between containers
- **Monitoring**: Accessing statistics, activity logs, and event history

### Authentication Model
hoody-api uses a multi-layered authentication system:
1. **JWT Tokens**: Short-lived access tokens (1 day) for standard API access
2. **Refresh Tokens**: Longer-lived tokens (7 days) for obtaining new access tokens
3. **Auth Tokens**: Long-term API keys with configurable permissions and realm restrictions
4. **Two-Factor Authentication**: TOTP-based 2FA for enhanced security
5. **OAuth Providers**: GitHub and Google OAuth integration
6. **Basic Authentication**: Username/password authentication (for compatibility)

All API requests require authentication via the `Authorization: Bearer {token}` header, except for public endpoints like login and signup.

### Service Philosophy Alignment
hoody-api embodies Hoody's core philosophy of:
- **Simplicity**: Complex infrastructure operations exposed through clean, predictable APIs
- **Security**: Enterprise-grade authentication and authorization with 2FA support
- **Scalability**: Supports multi-tenant resource isolation through projects, pools, and realms
- **Transparency**: Comprehensive logging, statistics, and audit trails
- **User-Centricity**: Focus on user experience with intuitive resource organization

## 2. Core Resource Workflows

### Authentication & Account Management

#### User Registration & Email Verification
```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.com' })

// Step 1: Register new account
const signupResult = await client.api.authentication.signup({
  email: 'user@example.com',
  password: 'SecurePass123!',
  username: 'newuser'
})

// Step 2: Check for verification email (sent automatically)
// Step 3: Verify email using token from email
const verifyResult = await client.api.authentication.verifyEmail({
  token: 'verification-token-from-email',
  email: 'user@example.com'
})
```

#### Login and Token Management
```
// Standard login with username/password
const loginResult = await client.api.authentication.login({
  username: 'existinguser',
  password: 'SecurePass123!'
})

// Login returns: { access_token, refresh_token, user }
// Use access_token for subsequent requests
const me = await client.api.authentication.getCurrentUser()

// Refresh expired access token
const refreshResult = await client.api.authentication.refreshToken({
  refreshToken: 'refresh-token-from-login'
})

// Logout (invalidates tokens server-side)
await client.api.authentication.logout()
```

#### Two-Factor Authentication Setup
```
// Step 1: Check current 2FA status
const status = await client.api.tfa.getStatus()

// Step 2: Initiate 2FA setup (requires current password)
const setup = await client.api.tfa.setup({
  password: 'SecurePass123!'
})

// Step 3: Verify 2FA setup with code from authenticator app
await client.api.tfa.verifySetup({
  code: '123456' // 6-digit TOTP code
})

// Step 4: During login, if 2FA enabled, verify with temp_token
// First, login returns { temp_token, requires_2fa: true }
const verifyResult = await client.api.tfa.verify({
  code: '123456' // OR backup code
})

// Step 5: Manage backup codes
await client.api.tfa.regenerateBackupCodes({
  password: 'SecurePass123!',
  code: '123456' // Current OTP code
})

// Step 6: Disable 2FA if needed
await client.api.tfa.disable({
  password: 'SecurePass123!',
  code: '123456'
})
```

#### OAuth Authentication Flow
```
// Initiate OAuth popup-handoff flow
const launch = await client.api.authentication.oauthLaunchInitiate({
  provider: 'github', // or 'google'
  redirect_uri: 'https://your-app.com/callback'
})

// Frontend redirects to launch.launch_url
// OAuth provider calls back to hoody-api
// hoody-api redirects to your redirect_uri with auth code

// If using popup flow, cancel intent if needed
await client.api.authentication.oauthCancelIntent()
```

### Auth Token Management

#### Creating and Managing API Keys
```
// List all auth tokens (values not included)
const tokens = await client.api.authTokens.list()

// Create new long-term API token
const newToken = await client.api.authTokens.create({
  alias: 'CI/CD Token',
  ip_restrictions: ['192.168.1.0/24'],
  expires_at: '2026-01-01T00:00:00Z'
})

// Copy existing token configuration
const copiedToken = await client.api.authTokens.copy('token-id', {
  alias: 'Copied Token'
})

// Get current token details (for the authenticated token)
const currentToken = await client.api.authTokens.getCurrent()

// Get specific token details
const tokenDetails = await client.api.authTokens.get({ id: 'token-id' })

// Update token settings
await client.api.authTokens.update('token-id', {
  alias: 'Updated Token Name',
  enabled: false
})

// Delete token
await client.api.authTokens.delete({ id: 'token-id' })
```

#### Managing Realm Restrictions
```
// Add realm to token
await client.api.authTokens.addRealm('token-id', {
  realm_id: 'abc123def456...' // 24-character hex realm ID
})

// Remove realm from token
await client.api.authTokens.removeRealm('token-id', {
  realm_id: 'abc123def456...'
})
```

### Project Management

#### Creating and Organizing Projects
```
// List all projects
const projects = await client.api.projects.list({
  page: 1,
  limit: 20,
  sort_by: 'created_at',
  sort_order: 'desc'
})

// Create new project
const newProject = await client.api.projects.create({
  alias: 'My Production Project',
  color: '#FF5733',
  realm_id: 'project-realm-id'
})

// Get project details
const projectDetails = await client.api.projects.get('project-id', {
  include_permissions: true
})

// Update project
await client.api.projects.update('project-id', {
  alias: 'Updated Project Name',
  quotas: {
    max_containers: 10,
    max_storage_mb: 1000
  }
})

// Delete project (permanent)
await client.api.projects.delete('project-id', {
  include_deleted_items: true
})

// Get project statistics
const projectStats = await client.api.projects.getStats({ id: 'project-id' })
```

#### Project Permission Management
```
// List project permissions
const permissions = await client.api.projects.listPermissions({ id: 'project-id' })

// Grant access to another user
await client.api.projects.addPermission('project-id', {
  user_id: 'target-user-id',
  permission_level: 'edit' // 'read', 'edit', or 'delete'
})

// Update permission level
await client.api.projects.updatePermission('project-id', 'permission-id', {
  permission_level: 'read'
})

// Revoke access
await client.api.projects.removePermission({ id: 'project-id', permissionId: 'permission-id' })
```

### Container Lifecycle Management

#### Container Operations
```
// List containers in a project
const containers = await client.api.containers.listByProject('project-id', {
  page: 1,
  limit: 10,
  runtime: 'docker'
})

// Create new container
const newContainer = await client.api.containers.create('project-id', {
  image: 'ubuntu:22.04',
  alias: 'web-server',
  specs: {
    cpu_cores: 2,
    memory_mb: 1024,
    storage_mb: 2048
  }
})

// List all containers across projects
const allContainers = await client.api.containers.list({
  runtime: 'docker',
  include_proxy_domains: 'true'
})

// Get container details
const container = await client.api.containers.get('container-id', {
  include_proxy_permissions: 'true'
})

// Container operations (start, stop, restart, etc.)
await client.api.containers.manage('container-id', 'start')
await client.api.containers.manage('container-id', 'stop')
await client.api.containers.manage('container-id', 'restart')
await client.api.containers.manage('container-id', 'pause')
await client.api.containers.manage('container-id', 'resume')

// Copy container
const copiedContainer = await client.api.containers.copy('container-id', {
  alias: 'web-server-copy',
  target_project_id: 'target-project-id'
})

// Sync copied container with source
await client.api.containers.sync({ id: 'container-id' })

// Authorize container access (returns signed claim)
const claim = await client.api.containers.authorize({ id: 'container-id' })

// Get container status logs
const statusLogs = await client.api.containers.getStatusLogs({ id: 'container-id' })

// Get container statistics
const containerStats = await client.api.containers.getStats({ id: 'container-id' })
```

### Network Configuration

#### Container Network Management
```
// Get network configuration
const networkConfig = await client.api.containers.getNetworkConfig({ id: 'container-id' })

// Update network configuration
await client.api.containers.updateNetworkConfig('container-id', {
  proxy: {
    enabled: true,
    mode: 'tcp',
    ports: [80, 443]
  },
  blocking: {
    enabled: false
  }
})

// Remove network configuration
await client.api.containers.removeNetworkConfig({ id: 'container-id' })

// Start network proxy/blocking
await client.api.containers.startNetwork({ id: 'container-id' })
await client.api.containers.stopNetwork({ id: 'container-id' })
```

### Firewall Configuration

#### Managing Container Firewalls
```
// List all firewall rules
const firewallRules = await client.api.firewall.list({ id: 'container-id' })

// Add ingress rule
await client.api.firewall.addIngressRule('container-id', {
  protocol: 'tcp',
  port_range: '80-443',
  source: '0.0.0.0/0',
  action: 'allow',
  state: 'enabled'
})

// Add egress rule
await client.api.firewall.addEgressRule('container-id', {
  protocol: 'tcp',
  port_range: '443',
  destination: 'api.example.com',
  action: 'allow'
})

// Toggle rule state (disable without deleting)
await client.api.firewall.toggleIngressRule('container-id', {
  protocol: 'tcp',
  port: 80,
  state: 'disabled'
})

// Remove specific rules
await client.api.firewall.removeIngressRule('container-id', {
  protocol: 'tcp',
  port: 80
})

// Reset all firewall rules
await client.api.firewall.reset({ id: 'container-id' })
```

### Environment Variables

#### Managing Container Environment
```
// List environment variables
const envVars = await client.api.env.list({ id: 'container-id' })

// Set single environment variable
await client.api.env.set('container-id', 'API_KEY', {
  value: 'secret-key-123'
})

// Bulk set environment variables
await client.api.env.bulkSet('container-id', {
  DATABASE_URL: 'postgres://user:pass@db:5432/mydb',
  NODE_ENV: 'production'
})

// Delete environment variable
await client.api.env.delete({ id: 'container-id', key: 'API_KEY' })
```

### Snapshot Management

#### Creating and Restoring Snapshots
```
// List container snapshots
const snapshots = await client.api.containers.listSnapshots({ id: 'container-id' })

// Create new snapshot
await client.api.containers.createSnapshot('container-id', {
  name: 'pre-deployment-v2',
  description: 'Before deploying version 2.0'
})

// Restore from snapshot
await client.api.containers.restoreSnapshot({ id: 'container-id', name: 'pre-deployment-v2' })

// Update snapshot alias
await client.api.containers.updateSnapshotAlias('container-id', 'pre-deployment-v2', {
  alias: 'Production v2.0 Backup'
})

// Delete snapshot
await client.api.containers.deleteSnapshot({ id: 'container-id', name: 'old-snapshot' })
```

### Proxy Configuration

#### Managing Proxy Settings and Permissions
```
// Get container proxy settings
const proxySettings = await client.api.proxyDiscovery.getContainerProxySettings({ id: 'container-id' })

// Update proxy settings
await client.api.proxyDiscovery.updateContainerProxySettings('container-id', undefined, {
  enable_proxy: true,
  default: 'deny'
})

// List proxy groups
const proxyGroups = await client.api.proxyDiscovery.listContainerProxyGroups({ id: 'container-id' })

// List proxy services
const proxyServices = await client.api.proxyDiscovery.listContainerProxyServices({ id: 'container-id' })

// Get container proxy permissions
const proxyPermissions = await client.api.proxyPermissionsContainer.get({ id: 'container-id' })

// Update proxy permissions (requires If-Match header)
await client.api.proxyPermissionsContainer.replace('container-id', 'file:v1', {
  groups: {
    admin: {
      auth: {
        type: 'jwt',
        secret: 'jwt-secret-key'
      },
      permissions: {
        'myapp': 'allow'
      }
    }
  },
  default: 'deny'
})
```

### Proxy Hooks

#### Managing Request Interception Hooks
```
// List all hooks for container
const hooks = await client.api.proxyHooks.listContainerProxyHooks({ id: 'container-id' })

// List hooks for specific service
const serviceHooks = await client.api.proxyHooks.listContainerProxyServiceHooks({ id: 'container-id', service: 'myapp' })

// Add new hook
await client.api.proxyHooks.addContainerProxyHook('container-id', 'myapp', 'file:v1', {
  match: '/api/*',
  script: 'return { status: 200, body: "Hello from hook" }',
  timeout: 5000,
  position: 0
})

// Move hook to new position
await client.api.proxyHooks.moveContainerProxyHook('container-id', 'myapp', 'hook-id', 'file:v1', {
  position: 1
})

// Remove specific hook
await client.api.proxyHooks.removeContainerProxyHook('container-id', 'myapp', 'hook-id', 'file:v1')
```

### Proxy Aliases

#### Managing Custom Domain Aliases
```
// List all proxy aliases
const aliases = await client.api.proxyAliases.list({
  project_id: 'project-id',
  enabled: 'true'
})

// Create new alias
const newAlias = await client.api.proxyAliases.create({
  alias: 'myapp.example.com',
  container_id: 'container-id',
  project_id: 'project-id',
  expires_at: '2026-01-01T00:00:00Z'
})

// Update alias
await client.api.proxyAliases.update('alias-id', {
  alias: 'updated.example.com'
})

// Enable/disable alias
await client.api.proxyAliases.setState('alias-id', {
  enabled: false
})

// Delete alias
await client.api.proxyAliases.delete({ id: 'alias-id' })
```

### Storage Shares

#### Sharing Data Between Containers
```
// List shares from container
const shares = await client.api.storageShares.list('source-container-id', {
  target_type: 'container'
})

// Create storage share
await client.api.storageShares.create('source-container-id', {
  path: '/data/uploads',
  target_container_id: 'target-container-id',
  mode: 'rw',
  label: 'Uploads Share'
})

// List incoming shares for container
const incomingShares = await client.api.storageShares.listIncoming({ id: 'target-container-id' })

// Toggle mount of incoming share
await client.api.storageShares.toggleIncomingMount('target-container-id', 'share-id', {
  enabled: true
})

// Update share properties
await client.api.storageShares.update('source-container-id', 'share-id', {
  mode: 'ro',
  label: 'Read-only Access'
})

// Delete share (global ID, no container needed)
await client.api.storageShares.delete({ shareId: 'share-id' })
```

### User Vault

#### Secure Key-Value Storage
```
// Get vault statistics
const vaultStats = await client.api.vault.getStats()

// List vault keys (metadata only)
const vaultKeys = await client.api.vault.list()

// Get specific vault key
const keyValue = await client.api.vault.get({ key: 'my-secret-key' })

// Set vault key
await client.api.vault.set('api-credentials', {
  value: JSON.stringify({
    api_key: 'secret',
    api_secret: 'very-secret'
  })
})

// Delete specific key
await client.api.vault.delete({ key: 'old-key' })

// Clear entire vault (dangerous)
await client.api.vault.clear()
```

### Wallet and Billing

#### Managing Finances
```
// Get aggregate balances
const balances = await client.api.wallet.getAggregateBalances()

// Get general balance only
const generalBalance = await client.api.wallet.getGeneralBalance()

// Get AI credit balance
const aiBalance = await client.api.wallet.getAiBalance()

// Transfer general balance to AI credits
await client.api.wallet.transferToAi({
  amount: '10.00' // USD amount as string
})

// List payment methods
const paymentMethods = await client.api.wallet.listPaymentMethods()

// Add new payment method
await client.api.wallet.addPaymentMethod({
  type: 'card',
  stripe_payment_method_id: 'pm_123456'
})

// Process payment
await client.api.wallet.processPayment({
  amount: '50.00',
  payment_method_id: 'payment-method-id',
  description: 'Account top-up'
})

// Create Stripe checkout session
const checkout = await client.api.wallet.createStripeCheckout({
  amount: '100.00',
  success_url: 'https://yourapp.com/success',
  cancel_url: 'https://yourapp.com/cancel'
})

// List transactions
const transactions = await client.api.wallet.listTransactions({
  limit: 50
})

// List invoices
const invoices = await client.api.wallet.listInvoices({
  sort_by: 'created_at',
  sort_order: 'desc'
})

// Download invoice PDF
await client.api.wallet.downloadInvoicePdf({ id: 'invoice-id' })
```

### Server Rental

#### Renting Dedicated Servers
```
// Browse available servers
const availableServers = await client.api.serverRental.browse({
  country: 'US',
  min_cpu_cores: 4,
  min_ram_gb: 16,
  max_price_per_day: 50
})

// Rent a server
const rental = await client.api.serverRental.rent('server-id', {
  duration_days: 30,
  auto_renew: true
})

// List user's rented servers
const myServers = await client.api.serverRental.list()

// Get server details
const serverDetails = await client.api.serverRental.get({ id: 'server-id' })

// List rentals
const rentals = await client.api.rentals.list()

// Extend rental
await client.api.rentals.extend('rental-id', {
  additional_days: 15
})

// Execute command on server
await client.api.serverCommands.execute('server-id', {
  command: 'restart-services',
  parameters: {
    service: 'nginx'
  }
})

// List available commands
const commands = await client.api.serverCommands.list('server-id', {
  category: 'maintenance'
})
```

### Team Collaboration (Pools)

#### Managing Team Pools
```
// List user's pools
const pools = await client.api.pools.list()

// Create new pool
const newPool = await client.api.pools.create({
  name: 'Development Team',
  description: 'Team for development projects'
})

// Get pool details
const poolDetails = await client.api.pools.get({ id: 'pool-id' })

// Update pool
await client.api.pools.update('pool-id', {
  name: 'Updated Team Name',
  description: 'Updated description'
})

// Invite member to pool
await client.api.poolMembers.invite('pool-id', {
  user_id: 'user-to-invite',
  role: 'member' // 'member', 'admin', or 'owner'
})

// Update member role
await client.api.poolMembers.updateRole('pool-id', 'user-id', {
  role: 'admin'
})

// Remove member from pool
await client.api.poolMembers.remove({ id: 'pool-id', userId: 'user-id' })

// List pending invitations
const invitations = await client.api.poolInvitations.list()

// Accept invitation
await client.api.poolInvitations.accept({ id: 'pool-id' })

// Reject invitation
await client.api.poolInvitations.reject({ id: 'pool-id' })
```

### Notifications

#### Managing System Notifications
```
// List public notifications
const publicNotifications = await client.api.notifications.listPublic()

// List user notifications
const userNotifications = await client.api.notifications.list()

// Mark notification as read
await client.api.notifications.markRead({ id: 'notification-id' })

// Mark all notifications as read
await client.api.notifications.markAllRead()
```

### Events and Activity Logs

#### Monitoring and Auditing
```
// Get event statistics
const eventStats = await client.api.events.getStats({
  start_date: '2024-01-01',
  end_date: '2024-12-31'
})

// List events with filters
const events = await client.api.events.list({
  event_type: 'container.start',
  resource_type: 'container',
  limit: 100
})

// Get specific event details
const eventDetails = await client.api.events.get({ id: 'event-id' })

// Cleanup old events
await client.api.events.cleanup({
  retention_days: 90
})

// Get activity logs
const activityLogs = await client.api.activity.list({
  errors_only: 'true',
  method: 'POST'
})

// Get activity statistics
const activityStats = await client.api.activity.getStats()
```

### Images and Marketplace

#### Managing Container Images
```
// List public images
const publicImages = await client.api.images.listPublic({
  os: 'ubuntu',
  architecture: 'x86_64',
  min_rating: 4
})

// Get image details
const imageDetails = await client.api.images.getDetails({ id: 'image-id' })

// Get image icon
const imageIcon = await client.api.images.getIcon({ id: 'image-id' })

// List user's images
const userImages = await client.api.images.list()

// Import free image
await client.api.images.importFree({ id: 'image-id' })

// Purchase paid image
await client.api.images.purchase({ id: 'image-id' })

// Rate image
await client.api.images.rate('image-id', {
  rating: 5,
  review: 'Excellent base image'
})
```

### User Management

#### Managing User Profiles
```
// Get current user profile
const currentUser = await client.api.authentication.getCurrentUser()

// Get user by ID (admin only for other users)
const userProfile = await client.api.users.get({ id: 'user-id' })

// Update user profile
await client.api.users.update('user-id', {
  alias: 'New Alias',
  current_password: 'OldPass123!',
  password: 'NewPass123!'
})

// Retry account setup (claim free-tier server)
await client.api.users.retrySetup({
  region: 'us-east-1'
})
```

### Realms and Multi-tenancy

#### Managing Realm Identifiers
```
// List all realm IDs for user
const realms = await client.api.realms.list({
  include_usage: true
})
```

### AI Models

#### Accessing AI Services
```
// List available AI models
const aiModels = await client.api.ai.listModels()
```

### Meta Information

#### Platform Information
```
// Get API signing public key
const publicKey = await client.api.meta.getPublicKey()

// Get social statistics
const socialStats = await client.api.meta.socialStats()
```

### Utilities

#### Helper Functions
```
// Get caller's IP information
const ipInfo = await client.api.utilities.getIpInfo()

// Get available regions
const regions = await client.api.authentication.getAvailableRegions()
```

## 3. Advanced Operations

### Full Container Deployment Workflow

```
async function deployWebApplication(projectId: string) {
  const client = new HoodyClient({ 
    baseURL: 'https://api.hoody.com',
    token: 'your-api-token'
  })

  try {
    // Step 1: Create container
    console.log('Creating container...')
    const container = await client.api.containers.create(projectId, {
      image: 'node:18-alpine',
      alias: 'web-app-' + Date.now(),
      specs: {
        cpu_cores: 2,
        memory_mb: 1024,
        storage_mb: 2048
      }
    })

    // Step 2: Configure environment
    console.log('Setting environment variables...')
    await client.api.env.bulkSet(container.id, {
      NODE_ENV: 'production',
      DATABASE_URL: 'postgres://user:pass@db:5432/mydb',
      JWT_SECRET: 'very-secret-key'
    })

    // Step 3: Configure firewall
    console.log('Configuring firewall...')
    await client.api.firewall.addIngressRule(container.id, {
      protocol: 'tcp',
      port_range: '80',
      source: '0.0.0.0/0',
      action: 'allow'
    })

    await client.api.firewall.addIngressRule(container.id, {
      protocol: 'tcp',
      port_range: '443',
      source: '0.0.0.0/0',
      action: 'allow'
    })

    await client.api.firewall.addEgressRule(container.id, {
      protocol: 'tcp',
      port_range: '5432',
      destination: 'db.internal',
      action: 'allow'
    })

    // Step 4: Configure proxy
    console.log('Setting up proxy...')
    await client.api.proxyDiscovery.updateContainerProxySettings(container.id, undefined, {
      enable_proxy: true,
      default: 'allow'
    })

    await client.api.proxyPermissionsContainer.replace(container.id, 'file:v1', {
      groups: {
        admin: {
          auth: {
            type: 'password',
            username: 'admin',
            password: 'secure-password'
          },
          permissions: {
            '*': 'allow'
          }
        },
        public: {
          auth: null,
          permissions: {
            'webapp': 'allow'
          }
        }
      },
      default: 'deny'
    })

    // Step 5: Create custom domain alias
    console.log('Creating domain alias...')
    const alias = await client.api.proxyAliases.create({
      alias: 'myapp.example.com',
      container_id: container.id,
      project_id: projectId
    })

    // Step 6: Start container
    console.log('Starting container...')
    await client.api.containers.manage(container.id, 'start')

    // Step 7: Verify deployment
    console.log('Verifying deployment...')
    const status = await client.api.containers.get(container.id)
    const stats = await client.api.containers.getStats(container.id)

    return {
      success: true,
      containerId: container.id,
      alias: alias.alias,
      status: status.status,
      stats
    }

  } catch (error) {
    console.error('Deployment failed:', error)
    
    // Cleanup: delete container if partially created
    if (container) {
      try {
        await client.api.containers.delete(container.id)
      } catch (cleanupError) {
        console.error('Cleanup failed:', cleanupError)
      }
    }
    
    throw error
  }
}
```

### Server Provisioning and Configuration

```
async function provisionDedicatedServer(region: string) {
  const client = new HoodyClient({ 
    baseURL: 'https://api.hoody.com',
    token: 'your-api-token'
  })

  // Step 1: Find suitable server
  const servers = await client.api.serverRental.browse({
    country: region,
    min_cpu_cores: 8,
    min_ram_gb: 32,
    max_price_per_day: 100
  })

  if (servers.data.length === 0) {
    throw new Error('No suitable servers available')
  }

  const selectedServer = servers.data[0]

  // Step 2: Rent server for 30 days
  const rental = await client.api.serverRental.rent(selectedServer.id, {
    duration_days: 30,
    auto_renew: true
  })

  // Step 3: Get available commands
  const commands = await client.api.serverCommands.list(selectedServer.id)

  // Step 4: Execute setup commands
  const setupCommand = commands.data.find(cmd => 
    cmd.category === 'setup' && cmd.name === 'initialize-server'
  )

  if (setupCommand) {
    await client.api.serverCommands.execute(selectedServer.id, {
      command: setupCommand.id,
      parameters: {
        hostname: 'prod-server-01',
        timezone: 'UTC'
      }
    })
  }

  // Step 5: Wait for setup to complete
  await new Promise(resolve => setTimeout(resolve, 30000))

  // Step 6: Create project and container on server
  const project = await client.api.projects.create({
    alias: 'Server Project - ' + selectedServer.id,
    realm_id: rental.realm_id
  })

  const container = await client.api.containers.create(project.id, {
    image: 'ubuntu:22.04',
    alias: 'server-container',
    specs: {
      cpu_cores: 4,
      memory_mb: 8192,
      storage_mb: 10240
    },
    server_id: selectedServer.id
  })

  return {
    server: selectedServer,
    rental,
    project,
    container
  }
}
```

### Batch Container Management

```
async function batchContainerOperation(
  projectId: string, 
  operation: 'start' | 'stop' | 'restart'
) {
  const client = new HoodyClient({ 
    baseURL: 'https://api.hoody.com',
    token: 'your-api-token'
  })

  // Get all containers in project
  const containers = await client.api.containers.listByProject(projectId, {
    limit: 100
  })

  const results = []

  // Process containers in parallel with concurrency limit
  const concurrency = 5
  const chunks = []
  for (let i = 0; i < containers.data.length; i += concurrency) {
    chunks.push(containers.data.slice(i, i + concurrency))
  }

  for (const chunk of chunks) {
    const promises = chunk.map(async (container) => {
      try {
        await client.api.containers.manage(container.id, operation)
        return { 
          id: container.id, 
          status: 'success',
          operation
        }
      } catch (error) {
        return { 
          id: container.id, 
          status: 'error',
          error: error.message,
          operation
        }
      }
    })

    const chunkResults = await Promise.all(promises)
    results.push(...chunkResults)

    // Small delay between chunks to avoid rate limiting
    if (chunks.indexOf(chunk) < chunks.length - 1) {
      await new Promise(resolve => setTimeout(resolve, 1000))
    }
  }

  return results
}
```

### Disaster Recovery Workflow

```
async function disasterRecovery(
  sourceContainerId: string,
  snapshotName: string
) {
  const client = new HoodyClient({ 
    baseURL: 'https://api.hoody.com',
    token: 'your-api-token'
  })

  try {
    // Step 1: Verify snapshot exists
    const snapshots = await client.api.containers.listSnapshots(sourceContainerId)
    const targetSnapshot = snapshots.data.find(s => s.name === snapshotName)

    if (!targetSnapshot) {
      throw new Error(`Snapshot ${snapshotName} not found`)
    }

    // Step 2: Stop container if running
    const container = await client.api.containers.get(sourceContainerId)
    if (container.status === 'running') {
      await client.api.containers.manage(sourceContainerId, 'stop')
    }

    // Step 3: Restore from snapshot
    console.log('Restoring from snapshot...')
    await client.api.containers.restoreSnapshot(sourceContainerId, snapshotName)

    // Step 4: Verify restoration
    const restoredContainer = await client.api.containers.get(sourceContainerId)
    
    // Step 5: Start container
    await client.api.containers.manage(sourceContainerId, 'start')

    // Step 6: Verify service health
    const stats = await client.api.containers.getStats(sourceContainerId)

    return {
      success: true,
      containerId: sourceContainerId,
      snapshot: snapshotName,
      status: restoredContainer.status,
      stats
    }

  } catch (error) {
    console.error('Disaster recovery failed:', error)
    
    // Attempt to restart original container
    try {
      await client.api.containers.manage(sourceContainerId, 'start')
    } catch (restartError) {
      console.error('Failed to restart original container:', restartError)
    }
    
    throw error
  }
}
```

### Cross-Project Resource Migration

```
async function migrateResources(
  sourceProjectId: string,
  targetProjectId: string
) {
  const client = new HoodyClient({ 
    baseURL: 'https://api.hoody.com',
    token: 'your-api-token'
  })

  // Step 1: Get all containers in source project
  const containers = await client.api.containers.listByProject(sourceProjectId, {
    limit: 100
  })

  const migrationResults = []

  // Step 2: Migrate each container
  for (const container of containers.data) {
    try {
      // Copy container to target project
      const copied = await client.api.containers.copy(container.id, {
        alias: container.alias + '-migrated',
        target_project_id: targetProjectId
      })

      // Sync configuration
      await client.api.containers.sync(copied.id)

      migrationResults.push({
        sourceId: container.id,
        targetId: copied.id,
        alias: container.alias,
        status: 'migrated'
      })

    } catch (error) {
      migrationResults.push({
        sourceId: container.id,
        status: 'failed',
        error: error.message
      })
    }
  }

  // Step 3: Update project permissions if needed
  const sourcePermissions = await client.api.projects.listPermissions(sourceProjectId)
  
  for (const permission of sourcePermissions.data) {
    try {
      await client.api.projects.addPermission(targetProjectId, {
        user_id: permission.user_id,
        permission_level: permission.permission_level
      })
    } catch (error) {
      console.error(`Failed to migrate permission for user ${permission.user_id}:`, error)
    }
  }

  return migrationResults
}
```

### Monitoring and Alerting System

```
async function monitorContainerHealth() {
  const client = new HoodyClient({ 
    baseURL: 'https://api.hoody.com',
    token: 'your-api-token'
  })

  // Get all containers
  const containers = await client.api.containers.list({
    limit: 200,
    include_expired: 'false'
  })

  const alerts = []
  const now = new Date()

  for (const container of containers.data) {
    try {
      // Check container status
      const status = await client.api.containers.get(container.id)
      
      if (status.status !== 'running') {
        alerts.push({
          type: 'container-down',
          containerId: container.id,
          alias: container.alias,
          status: status.status,
          timestamp: now
        })
        continue
      }

      // Check resource usage
      const stats = await client.api.containers.getStats(container.id)
      
      // Check CPU usage
      if (stats.cpu.percentage > 90) {
        alerts.push({
          type: 'high-cpu',
          containerId: container.id,
          alias: container.alias,
          cpu: stats.cpu.percentage,
          timestamp: now
        })
      }

      // Check memory usage
      if (stats.memory.percentage > 85) {
        alerts.push({
          type: 'high-memory',
          containerId: container.id,
          alias: container.alias,
          memory: stats.memory.percentage,
          timestamp: now
        })
      }

      // Check disk usage
      if (stats.disk.percentage > 90) {
        alerts.push({
          type: 'high-disk',
          containerId: container.id,
          alias: container.alias,
          disk: stats.disk.percentage,
          timestamp: now
        })
      }

    } catch (error) {
      alerts.push({
        type: 'monitoring-error',
        containerId: container.id,
        error: error.message,
        timestamp: now
      })
    }
  }

  // Send alerts (would integrate with notification service)
  if (alerts.length > 0) {
    console.log('ALERTS DETECTED:', alerts)
    // await sendAlerts(alerts)
  }

  return {
    totalContainers: containers.data.length,
    alerts: alerts.length,
    healthyContainers: containers.data.length - alerts.length,
    alertDetails: alerts
  }
}
```

## 4. Quick Reference

### Endpoint Groups and Paths

| Resource Group | Base Path | Description |
|----------------|-----------|-------------|
| **Authentication** | `/api/v1/auth/*` | User registration, login, password reset |
| **Users** | `/api/v1/users/*` | User profiles and account management |
| **Auth Tokens** | `/api/v1/auth/tokens/*` | API key management |
| **Projects** | `/api/v1/projects/*` | Project organization and management |
| **Containers** | `/api/v1/containers/*` | Container lifecycle management |
| **Container Images** | `/api/v1/images/*` | Image marketplace and management |
| **Network** | `/api/v1/containers/{id}/network` | Network configuration |
| **Firewall** | `/api/v1/containers/{id}/firewall/*` | Security rules management |
| **Environment** | `/api/v1/containers/{id}/env/*` | Environment variable management |
| **Snapshots** | `/api/v1/containers/{id}/snapshots/*` | Snapshot creation and restoration |
| **Proxy Settings** | `/api/v1/containers/{id}/proxy/*` | Proxy configuration and permissions |
| **Proxy Aliases** | `/api/v1/proxy/aliases/*` | Custom domain management |
| **Storage Shares** | `/api/v1/storage/*` and `/api/v1/containers/{id}/storage/*` | Data sharing between containers |
| **Wallet** | `/api/v1/wallet/*` | Billing, payments, and invoices |
| **Server Rental** | `/api/v1/servers/*` and `/api/v1/rentals/*` | Dedicated server management |
| **Pools** | `/api/v1/pools/*` | Team collaboration management |
| **Notifications** | `/api/v1/notifications/*` | System notifications |
| **Events** | `/api/v1/events/*` | Activity logging and auditing |
| **Activity Logs** | `/api/v1/users/auth/activity` | API request logging |
| **AI Models** | `/api/v1/ai/*` | AI service catalog |
| **Vault** | `/api/v1/vault/*` | Secure key-value storage |
| **Realms** | `/api/v1/realms/*` | Multi-tenancy management |
| **Meta** | `/api/v1/meta/*` | Platform information |
| **Utilities** | `/api/v1/ip` | Utility endpoints |

### Essential Parameters

#### Common Pagination Parameters
- `page` (integer): Page number (default: 1)
- `limit` (integer): Items per page (default: 20, max: 100)
- `sort_by` (string): Field to sort by
- `sort_order` (string): `asc` or `desc`

#### Common Filtering Parameters
- `realm_id` (string): Filter by realm identifier
- `status` (string): Filter by status
- `search` (string): Text search query
- `start_date` (string): ISO date for range start
- `end_date` (string): ISO date for range end

### Typical Response Formats

#### Successful Response
```
{
  "success": true,
  "data": {
    "id": "resource-id",
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z",
    "resource_specific_field": "value"
  },
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 100
  }
}
```

#### Error Response
```
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input data",
    "details": {
      "email": "Invalid email format"
    }
  }
}
```

#### List Response with Pagination
```
{
  "success": true,
  "data": [
    { "id": "item-1", "name": "Item 1" },
    { "id": "item-2", "name": "Item 2" }
  ],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 42,
    "has_more": true
  }
}
```

### SDK Method Reference

| Resource | Method | Description |
|----------|--------|-------------|
| **Auth Tokens** | `client.api.authTokens.list()` | List all API tokens |
| **Projects** | `client.api.projects.list()` | List user projects |
| **Containers** | `client.api.containers.list()` | List all containers |
| **Wallet** | `client.api.wallet.getAggregateBalances()` | Get financial balances |
| **Events** | `client.api.events.list()` | Query activity events |
| **Users** | `client.api.users.get()` | Get user profile |
| **Images** | `client.api.images.listPublic()` | Browse marketplace images |
| **Servers** | `client.api.serverRental.browse()` | Find available servers |
| **Pools** | `client.api.pools.list()` | List team pools |
| **Notifications** | `client.api.notifications.list()` | Get user notifications |
| **Vault** | `client.api.vault.list()` | List vault keys |
| **Realms** | `client.api.realms.list()` | List realm identifiers |

### Error Recovery Patterns

#### Rate Limiting
```
async function withRetry<T>(
  operation: () => Promise<T>,
  maxRetries = 3
): Promise<T> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await operation()
    } catch (error) {
      if (error.status === 429 && attempt < maxRetries) {
        // Exponential backoff
        const delay = Math.pow(2, attempt) * 1000
        await new Promise(resolve => setTimeout(resolve, delay))
      } else {
        throw error
      }
    }
  }
  throw new Error('Max retries exceeded')
}

// Usage
const result = await withRetry(() => client.api.containers.list())
```

#### Partial Failure Recovery
```
async function recoverFromPartialFailure(
  containerId: string,
  failedOperations: Array<() => Promise<void>>
) {
  const results = []
  
  for (const operation of failedOperations) {
    try {
      await operation()
      results.push({ status: 'recovered' })
    } catch (error) {
      results.push({ 
        status: 'failed',
        error: error.message
      })
    }
  }
  
  // Verify final state
  const container = await client.api.containers.get(containerId)
  
  return {
    recoveryResults: results,
    finalStatus: container.status
  }
}
```

### Authentication Headers

#### Bearer Token (Standard)
```
// When creating client
const client = new HoodyClient({ 
  baseURL: 'https://api.hoody.com',
  token: 'your-jwt-or-auth-token'
})

// Or update later
client.setToken('new-token')
```

#### Basic Authentication (Limited Use)
```
// For specific endpoints that support basic auth
const response = await fetch('https://api.hoody.com/api/v1/users/auth/me', {
  headers: {
    'Authorization': 'Basic ' + btoa('username:password')
  }
})
```

### Key Constraints and Limits

1. **Rate Limits**: 
   - Authenticated: 1000 requests/minute
   - Unauthenticated: 100 requests/minute
   - Per-endpoint limits vary

2. **Resource Limits**:
   - Max containers per project: 100 (configurable)
   - Max projects per user: 50
   - Max auth tokens per user: 20
   - Max vault storage: 10MB per realm

3. **Data Constraints**:
   - Container aliases: 3-64 characters
   - Environment variable keys: 1-128 characters
   - Environment variable values: 1-4096 characters
   - Project names: 3-128 characters

4. **Timeouts**:
   - API requests: 30 seconds
   - Container operations: 5-15 minutes
   - Server provisioning: 15-30 minutes

---

**Total Lines**: ~1450

This comprehensive subskill covers all 241 endpoints across all major resource groups, providing AI agents with complete operational knowledge of the hoody-api service. The document includes authentication flows, resource management patterns, advanced orchestration examples, and complete reference materials for effective API interaction.