<!--
hoody-api Subskill (sdk)
Auto-generated by Hoody Skills Generator
Generated: 2026-05-06T20:06:30.884Z
Model: mimo-v2.5-pro
Mode: sdk


Tokens: 35793

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

# hoody-api Subskill

## Overview

### What This Service Does

hoody-api is the core platform API for the Hoody ecosystem. It manages the complete lifecycle of all platform resources: user accounts, authentication (including OAuth and 2FA), projects, containers, server rentals, networking, firewall rules, storage shares, proxy configuration, wallet/billing, notifications, events, and more. It exposes 238 endpoints across 31 files and serves as the single source of truth for all platform state.

### When to Use It

Use hoody-api whenever you need to:

- **Authenticate users** — login, signup, OAuth flows, 2FA, token management
- **Manage projects** — create, update, delete projects; manage project-level permissions
- **Manage containers** — create, configure, operate, snapshot, and monitor containers
- **Configure networking** — set up firewall rules, network proxy/blocking, proxy permissions, hooks, and aliases
- **Manage storage** — create and manage storage shares between containers
- **Handle billing** — manage wallets, payment methods, invoices, and transactions
- **Manage server rentals** — browse available servers, rent, extend, and execute commands
- **Manage pools** — team collaboration with pool creation, member management, and invitations
- **Access platform metadata** — AI models, public keys, social stats, realm discovery
- **Monitor activity** — events, activity logs, notifications

### Authentication Model

All endpoints require authentication unless explicitly marked as public. Authentication uses one of three methods:

1. **JWT Bearer Token** — obtained via `POST /api/v1/users/auth/login`, expires in 1 day. Refresh with `POST /api/v1/users/auth/refresh`.
2. **Auth Token** — long-lived tokens created via `POST /api/v1/auth/tokens`. Scoped to specific realms.
3. **Basic Auth** — username:password for programmatic access.

The SDK handles authentication automatically:

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

// Token-based authentication
const client = new HoodyClient({
  baseURL: 'https://api.hoody.icu',
  token: 'YOUR_TOKEN'
})

// Credential-based authentication (returns authenticated client)
const client = await HoodyClient.authenticate(
  'https://api.hoody.icu',
  { username: 'user@example.com', password: 'your-password' }
)
```

### How It Fits Into Hoody Philosophy

hoody-api embodies the Hoody philosophy of zero-configuration infrastructure. It provides:

- **Automatic routing** — containers get predictable URLs via the proxy system: `https://{projectId}-{containerId}-{serviceName}-{serviceId}.{node}.containers.hoody.icu`
- **Built-in security** — proxy permissions, firewall rules, and 2FA are first-class features
- **Multi-tenant isolation** — realms, projects, and pools provide logical separation
- **Portable credentials** — container authorization claims are ED25519-signed and verifiable

### Critical Path Rules

- **Base URL**: `https://api.hoody.icu`
- **All paths** MUST start with `/api/v1/` (never `/v1/`)
- **Bearer auth**: `Authorization: Bearer {token}`

---

## Core Resource Workflows

### 1. Authentication & Account Lifecycle

#### 1.1 Signup and Email Verification

```
// Step 1: Create account
const signupResult = await client.api.authentication.signup({
  email: 'user@example.com',
  password: 'SecurePass123!',
  alias: 'myusername'
})

// Step 2: Verify email (token from verification email)
const verifyResult = await client.api.authentication.verifyEmail({
  token: 'verification-token-from-email'
})

// Step 3: Login after verification
const loginResult = await client.api.authentication.login({
  email: 'user@example.com',
  password: 'SecurePass123!'
})
```

#### 1.2 Login and Token Refresh

```
// Login
const loginResult = await client.api.authentication.login({
  email: 'user@example.com',
  password: 'SecurePass123!'
})

// Refresh token (use refresh token in Authorization header)
const refreshResult = await client.api.authentication.refreshToken({
  refreshToken: 'your-refresh-token'
})

// Get current user profile
const me = await client.api.authentication.getCurrentUser()

// Logout
await client.api.authentication.logout()
```

#### 1.3 Password Reset Flow

```
// Step 1: Request password reset
await client.api.authentication.forgotPassword({
  email: 'user@example.com'
})

// Step 2: Reset password with token from email
await client.api.authentication.resetPassword({
  token: 'reset-token-from-email',
  password: 'NewSecurePass456!'
})
```

#### 1.4 OAuth Flows (GitHub / Google)

```
// GitHub OAuth — browser redirect
client.api.authentication.githubOAuthRedirect(
  'optional-intent',
  'https://your-app.com/callback',
  'pkce-code-challenge'
)

// GitHub OAuth callback (handled by browser)
client.api.authentication.githubOAuthCallback({ code: 'auth-code', state: 'state-value' })

// Google OAuth — browser redirect
client.api.authentication.googleOAuthRedirect(
  'https://your-app.com/callback',
  'pkce-code-challenge'
)

// Google OAuth callback (handled by browser)
client.api.authentication.googleOAuthCallback({ code: 'auth-code', state: 'state-value' })
```

#### 1.5 Available Regions

```
// Public endpoint — no auth required
const regions = await client.api.authentication.getAvailableRegions()
```

---

### 2. Two-Factor Authentication (2FA)

#### 2.1 Setup 2FA

```
// Step 1: Initialize setup (returns QR code and backup codes)
const setup = await client.api.tfa.setup({
  password: 'current-password'
})

// Step 2: Verify setup with first code from authenticator app
await client.api.tfa.verifySetup({
  code: '123456'
})

// Step 3: Check status
const status = await client.api.tfa.getStatus()
```

#### 2.2 Login with 2FA

```
// Step 1: Login returns temp_token when 2FA is required
const loginResult = await client.api.authentication.login({
  email: 'user@example.com',
  password: 'SecurePass123!'
})

// Step 2: Verify 2FA code
const verified = await client.api.tfa.verify({
  temp_token: loginResult.temp_token,
  code: '123456'
})
```

#### 2.3 Manage 2FA

```
// Check 2FA status
const status = await client.api.tfa.getStatus()

// Regenerate backup codes
const newCodes = await client.api.tfa.regenerateBackupCodes({
  password: 'current-password',
  code: '123456'
})

// Set token gate (require OTP for token mutations)
await client.api.tfa.setTokenGate({
  enabled: true
})

// Disable 2FA
await client.api.tfa.disable({
  password: 'current-password',
  code: '123456'
})
```

---

### 3. Auth Tokens

#### 3.1 List and Create Tokens

```
// List all auth tokens (token values not included)
const tokens = await client.api.authTokens.list()

// Create a new auth token
const newToken = await client.api.authTokens.create({
  alias: 'ci-deploy-token',
  ip_whitelist: ['192.168.1.0/24'],
  expires_at: '2026-01-01T00:00:00Z'
})
```

#### 3.2 Token Details and Updates

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

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

// Copy token configuration to new token
const copied = await client.api.authTokens.copy('token-id', {
  alias: 'copied-token'
})

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

#### 3.3 Current Token and Realm Management

```
// Get current token metadata
const current = await client.api.authTokens.getCurrent()

// Add realm to token
await client.api.authTokens.addRealm('token-id', {
  realm_id: 'abc123def456'
})

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

#### 3.4 Public Profiles

```
// Update current token's public profile
await client.api.authTokens.updatePublicProfile({
  public_key: 'ed25519-public-key-hex',
  public_storage: { bio: 'CI/CD automation token' }
})

// Resolve public profile by public key
const profile = await client.api.authTokens.getPublicProfile({ public_key: 'ed25519-public-key-hex' })
```

---

### 4. Users

#### 4.1 User Profile Management

```
// Get user by ID
const user = await client.api.users.get({ id: 'user-id' })

// Update own profile
await client.api.users.update('user-id', {
  alias: 'new-alias',
  current_password: 'current-password',
  password: 'new-password'
})

// Retry free-tier setup (idempotent)
await client.api.users.retrySetup({})
```

---

### 5. Projects

#### 5.1 Project CRUD

```
// List all projects
const projects = await client.api.projects.list()

// Create a project
const project = await client.api.projects.create({
  alias: 'my-project',
  color: '#3B82F6'
})

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

// Update project
await client.api.projects.update('project-id', {
  alias: 'renamed-project',
  color: '#EF4444'
})

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

#### 5.2 Project Permissions

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

// Grant access
await client.api.projects.addPermission('project-id', {
  user_id: 'target-user-id',
  permission: 'edit'
})

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

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

#### 5.3 Project Statistics

```
const stats = await client.api.projects.getStats({ id: 'project-id' })
```

---

### 6. Containers

#### 6.1 Container CRUD

```
// List containers for a project
const containers = await client.api.containers.listByProject({ id: 'project-id' })

// List all containers across all projects
const allContainers = await client.api.containers.list()

// Create a container
const container = await client.api.containers.create('project-id', {
  alias: 'my-container',
  image: 'ubuntu:22.04',
  runtime: 'lxc'
})

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

// Update container
await client.api.containers.update('container-id', {
  alias: 'renamed-container'
})

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

#### 6.2 Container Operations

```
// Start container
await client.api.containers.manage({ operation: 'start' })

// Stop container
await client.api.containers.manage({ operation: 'stop' })

// Restart container
await client.api.containers.manage({ operation: 'restart' })

// Pause container
await client.api.containers.manage({ operation: 'pause' })

// Resume container
await client.api.containers.manage({ operation: 'resume' })

// Force stop
await client.api.containers.manage({ operation: 'force-stop' })
```

#### 6.3 Container Copy and Sync

```
// Copy a container (async operation)
const copy = await client.api.containers.copy('source-container-id', {
  alias: 'cloned-container',
  project_id: 'target-project-id'
})

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

#### 6.4 Container Authorization

```
// Get signed authorization claim
const claim = await client.api.containers.authorize({ id: 'container-id' })
// Returns ED25519-signed container_claim for portable access
```

#### 6.5 Container Status Logs and Stats

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

// Get real-time resource stats
const stats = await client.api.containers.getStats({ id: 'container-id' })
```

---

### 7. Container Environment Variables

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

// Bulk set environment variables (merge semantics)
await client.api.env.bulkSet('container-id', {
  DATABASE_URL: 'postgres://...',
  API_KEY: 'secret-key'
})

// Set a single variable
await client.api.env.set('container-id', 'MY_VAR', {
  value: 'my-value'
})

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

---

### 8. Container Network Configuration

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

// Update network configuration
await client.api.containers.updateNetworkConfig('container-id', {
  proxy: { enabled: true },
  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' })

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

---

### 9. Container Firewall

#### 9.1 View and Reset Rules

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

// Reset firewall to open state
await client.api.firewall.reset({ id: 'container-id' })
```

#### 9.2 Ingress Rules

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

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

// Remove ingress rule(s)
await client.api.firewall.removeIngressRule('container-id', {
  protocol: 'tcp',
  port: 80
})
```

#### 9.3 Egress Rules

```
// Add egress rule
await client.api.firewall.addEgressRule('container-id', {
  protocol: 'tcp',
  port: 443,
  destination: '0.0.0.0/0',
  action: 'allow'
})

// Toggle egress rule state
await client.api.firewall.toggleEgressRule('container-id', {
  protocol: 'tcp',
  port: 443,
  state: 'disabled'
})

// Remove egress rule(s)
await client.api.firewall.removeEgressRule('container-id', {
  protocol: 'tcp',
  port: 443
})
```

---

### 10. Container Snapshots

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

// Create snapshot
await client.api.containers.createSnapshot('container-id', {
  name: 'before-upgrade',
  alias: 'Pre-upgrade snapshot'
})

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

// Update snapshot alias
await client.api.containers.updateSnapshotAlias('container-id', 'before-upgrade', {
  alias: 'Renamed snapshot'
})

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

---

### 11. Container Images

```
// List public images
const publicImages = await client.api.images.listPublic()

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

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

// List user's imported/purchased 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 an image
await client.api.images.rate('image-id', {
  rating: 5
})
```

---

### 12. Proxy Permissions (Project Level)

```
// Get project proxy permissions
const perms = await client.api.proxyPermissionsProject.get({ id: 'project-id' })

// Replace entire proxy permissions configuration
await client.api.proxyPermissionsProject.replace('project-id', undefined, {
  enable_proxy: true,
  default: 'allow',
  auth_groups: {},
  permissions: {}
})

// Delete all proxy permissions (revert to open)
await client.api.proxyPermissionsProject.delete({ id: 'project-id' })

// Update default policy
await client.api.proxyPermissionsProject.updateDefault('project-id', undefined, {
  default: 'deny'
})

// Enable/disable proxy
await client.api.proxyPermissionsProject.updateState('project-id', undefined, {
  enable_proxy: true
})

// Set JWT authentication group
await client.api.proxyPermissionsProject.setJwtGroup(
  'project-id', 'admin-group', undefined, {
    issuer: 'https://auth.example.com',
    audience: 'my-app',
    jwks_url: 'https://auth.example.com/.well-known/jwks.json'
  }
)

// Set password authentication group
await client.api.proxyPermissionsProject.setPasswordGroup(
  'project-id', 'users', undefined, {
    username: 'admin',
    password_hash: '$2b$...'
  }
)

// Set IP authentication group
await client.api.proxyPermissionsProject.setIpGroup(
  'project-id', 'office', undefined, {
    allowed_ips: ['10.0.0.0/8']
  }
)

// Set token authentication group
await client.api.proxyPermissionsProject.setTokenGroup(
  'project-id', 'api-clients', undefined, {
    tokens: ['token1', 'token2']
  }
)

// Set group program permissions
await client.api.proxyPermissionsProject.setGroup(
  'project-id', 'admin-group', undefined, {
    programs: { 'my-app': 'allow' }
  }
)

// Remove group
await client.api.proxyPermissionsProject.removeGroup({ id: 'project-id', groupName: 'admin-group' })

// Remove single program permission
await client.api.proxyPermissionsProject.removeProgram(
  'project-id', 'admin-group', 'my-app'
)

// Remove authentication group
await client.api.proxyPermissionsProject.removeAuthGroup({ id: 'project-id', groupName: 'admin-group' })
```

---

### 13. Proxy Permissions (Container Level)

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

// Replace container proxy permissions (requires If-Match header)
await client.api.proxyPermissionsContainer.replace('container-id', 'file:v1', {
  enable_proxy: true,
  default: 'allow',
  auth_groups: {},
  permissions: {}
})

// Delete container proxy permissions
await client.api.proxyPermissionsContainer.delete('container-id', 'file:v1')

// Update default policy
await client.api.proxyPermissionsContainer.updateDefault('container-id', 'file:v1', {
  default: 'deny'
})

// Enable/disable proxy
await client.api.proxyPermissionsContainer.updateState('container-id', 'file:v1', {
  enable_proxy: true
})

// Set JWT group
await client.api.proxyPermissionsContainer.setJwtGroup(
  'container-id', 'admin-group', 'file:v1', {
    issuer: 'https://auth.example.com',
    audience: 'my-app',
    jwks_url: 'https://auth.example.com/.well-known/jwks.json'
  }
)

// Set password group
await client.api.proxyPermissionsContainer.setPasswordGroup(
  'container-id', 'users', 'file:v1', {
    username: 'admin',
    password_hash: '$2b$...'
  }
)

// Set IP group
await client.api.proxyPermissionsContainer.setIpGroup(
  'container-id', 'office', 'file:v1', {
    allowed_ips: ['10.0.0.0/8']
  }
)

// Set token group
await client.api.proxyPermissionsContainer.setTokenGroup(
  'container-id', 'api-clients', 'file:v1', {
    tokens: ['token1', 'token2']
  }
)

// Set group program permissions
await client.api.proxyPermissionsContainer.setGroup(
  'container-id', 'admin-group', 'file:v1', {
    programs: { 'my-app': 'allow' }
  }
)

// Remove group
await client.api.proxyPermissionsContainer.removeGroup({ id: 'container-id', groupName: 'admin-group' })

// Remove single program
await client.api.proxyPermissionsContainer.removeProgram(
  'container-id', 'admin-group', 'my-app'
)

// Remove authentication group
await client.api.proxyPermissionsContainer.removeAuthGroup({ id: 'container-id', groupName: 'admin-group' })
```

---

### 14. Proxy Hooks

```
// List all hooks for a container
const hooks = await client.api.proxyHooks.listContainerProxyHooks({ id: 'container-id' })

// List hooks for a specific service
const serviceHooks = await client.api.proxyHooks.listContainerProxyServiceHooks(
  'container-id', 'my-app'
)

// Add a hook
await client.api.proxyHooks.addContainerProxyHook(
  'container-id', 'my-app', 'file:v1', {
    match: '/api/*',
    script: 'return { status: 200, body: "ok" }',
    timeout: 5000
  }
)

// Get a single hook
const hook = await client.api.proxyHooks.getContainerProxyHook(
  'container-id', 'my-app', 'hook-id'
)

// Update a hook
await client.api.proxyHooks.updateContainerProxyHook(
  'container-id', 'my-app', 'hook-id', 'file:v1', {
    match: '/api/v2/*',
    script: 'return { status: 200, body: "updated" }'
  }
)

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

// Delete a hook
await client.api.proxyHooks.removeContainerProxyHook(
  'container-id', 'my-app', 'hook-id', 'file:v1'
)

// Clear all hooks for a service
await client.api.proxyHooks.clearContainerProxyServiceHooks(
  'container-id', 'my-app', 'file:v1'
)
```

---

### 15. Proxy Discovery

```
// Get proxy root settings
const settings = await client.api.proxyDiscovery.getContainerProxySettings({ id: 'container-id' })

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

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

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

// Get merged proxy view for a service
const serviceView = await client.api.proxyDiscovery.getContainerProxyService(
  'container-id', 'my-app'
)
```

---

### 16. Proxy Aliases

```
// List all proxy aliases
const aliases = await client.api.proxyAliases.list()

// Create a custom domain alias
const alias = await client.api.proxyAliases.create({
  alias: 'my-app.example.com',
  container_id: 'container-id',
  project_id: 'project-id'
})

// Get alias details
const details = await client.api.proxyAliases.get({ id: 'alias-id' })

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

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

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

---

### 17. Storage Shares

#### 17.1 Create and Manage Shares

```
// List shares from a container
const shares = await client.api.storageShares.list({ id: 'container-id' })

// Create a storage share
const share = await client.api.storageShares.create('container-id', {
  path: '/data/shared',
  target_container_id: 'target-container-id',
  mode: 'rw',
  label: 'shared-data'
})

// Get share details
const details = await client.api.storageShares.get({ id: 'container-id', shareId: 'share-id' })

// Update share
await client.api.storageShares.update('container-id', 'share-id', {
  mode: 'ro',
  label: 'read-only-data'
})

// Delete share (globally unique ID)
await client.api.storageShares.delete({ shareId: 'share-id' })
```

#### 17.2 Incoming Shares

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

// List all incoming shares across all containers
const allIncoming = await client.api.storageShares.listIncomingGlobal()

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

#### 17.3 Global Share Views

```
// List all shares you've created
const myShares = await client.api.storageShares.listGlobal()
```

---

### 18. Notifications

```
// Get public notifications (no auth required)
const publicNotifs = await client.api.notifications.listPublic()

// Get user notifications
const notifs = await client.api.notifications.list()

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

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

---

### 19. Events

```
// Get event statistics
const stats = await client.api.events.getStats()

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

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

// Delete single event
await client.api.events.delete({ id: 'event-id' })

// Bulk delete events
await client.api.events.bulkDelete({
  resource_type: 'container',
  before: '2025-01-01T00:00:00Z'
})

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

---

### 20. Activity Logs

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

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

---

### 21. AI Models

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

---

### 22. Meta

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

// Get social stats (GitHub stars, Discord members, etc.)
const socialStats = await client.api.meta.getPublicKey()
```

---

### 23. Realms

```
// List all realm IDs accessible to you
const realms = await client.api.realms.list()
```

---

### 24. Vault (Encrypted Key-Value Store)

```
// Get vault statistics
const stats = await client.api.vault.getStats()

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

// Get a specific key-value pair
const value = await client.api.vault.get(undefined, 'my-secret-key')

// Set a key-value pair
await client.api.vault.set(undefined, 'my-secret-key', {
  value: JSON.stringify({ api_key: 'secret', endpoint: 'https://api.example.com' })
})

// Delete a key
await client.api.vault.delete(undefined, 'my-secret-key')

// Clear entire vault (DANGER — irreversible)
await client.api.vault.clear()
```

---

### 25. Wallet & Billing

#### 25.1 Balances

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

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

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

// Transfer from general to AI credits
await client.api.wallet.transferToAi({
  amount: '10.00'
})
```

#### 25.2 Transactions

```
// List transactions
const transactions = await client.api.wallet.listTransactions()

// Get transaction details
const tx = await client.api.wallet.getTransaction({ id: 'transaction-id' })

// Get AI fee history
const fees = await client.api.wallet.listAiFeeHistory()
```

#### 25.3 Payment Methods

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

// Add payment method
const method = await client.api.wallet.addPaymentMethod({
  type: 'card',
  token: 'stripe-token'
})

// Get payment method
const details = await client.api.wallet.getPaymentMethod({ id: 'method-id' })

// Update payment method
await client.api.wallet.updatePaymentMethod('method-id', {
  alias: 'Work Card'
})

// Set as default
await client.api.wallet.setDefaultPaymentMethod({ id: 'method-id' })

// Delete payment method
await client.api.wallet.deletePaymentMethod({ id: 'method-id' })
```

#### 25.4 Payments and Invoices

```
// Process a payment
const payment = await client.api.wallet.processPayment({
  amount: '25.00',
  payment_method_id: 'method-id'
})

// Get payment status
const status = await client.api.wallet.getPaymentStatus({ id: 'payment-id' })

// List invoices
const invoices = await client.api.wallet.listInvoices()

// Get invoice details
const invoice = await client.api.wallet.getInvoice({ id: 'invoice-id' })

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

// Generate invoice for transaction
await client.api.wallet.generateInvoice({ id: 'transaction-id' })
```

---

### 26. Pools (Team Collaboration)

#### 26.1 Pool CRUD

```
// List pools
const pools = await client.api.pools.list()

// Create a pool
const pool = await client.api.pools.create({
  name: 'Engineering Team',
  description: 'Shared infrastructure pool'
})

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

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

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

#### 26.2 Pool Members

```
// Invite a member
await client.api.poolMembers.invite('pool-id', {
  user_id: 'user-id',
  role: 'member'
})

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

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

#### 26.3 Pool Invitations

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

---

### 27. Server Rental

#### 27.1 Browse and Rent Servers

```
// Browse available servers
const available = await client.api.serverRental.browse({
  country: 'US',
  min_cpu_cores: 4,
  min_ram_gb: 8
})

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

// List rented servers
const servers = await client.api.serverRental.list()

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

#### 27.2 Rentals

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

// Get rental details
const rental = await client.api.rentals.get({ id: 'rental-id' })

// Extend rental
await client.api.rentals.extend('rental-id', {
  duration_days: 7
})
```

#### 27.3 Server Commands

```
// Get available commands
const commands = await client.api.serverCommands.list({ serverId: 'server-id' })

// Execute a command
const result = await client.api.serverCommands.execute('server-id', {
  command: 'restart-services'
})
```

---

### 28. Utilities

```
// Get caller IP information
const ipInfo = await client.api.utilities.getIpInfo()
```

---

## Advanced Operations

### 1. Full Container Lifecycle

A complete workflow from project creation to a running, secured container with proxy access.

```
// Step 1: Create project
const project = await client.api.projects.create({
  alias: 'production-app',
  color: '#10B981'
})
const projectId = project.data.id

// Step 2: Create container
const container = await client.api.containers.create(projectId, {
  alias: 'web-server',
  image: 'ubuntu:22.04',
  runtime: 'lxc'
})
const containerId = container.data.id

// Step 3: Set environment variables
await client.api.env.bulkSet(containerId, {
  NODE_ENV: 'production',
  PORT: '3000',
  DATABASE_URL: 'postgres://user:pass@db:5432/app'
})

// Step 4: Configure firewall — allow HTTP/HTTPS, block everything else
await client.api.firewall.addIngressRule(containerId, {
  protocol: 'tcp',
  port: 80,
  source: '0.0.0.0/0',
  action: 'allow'
})
await client.api.firewall.addIngressRule(containerId, {
  protocol: 'tcp',
  port: 443,
  source: '0.0.0.0/0',
  action: 'allow'
})

// Step 5: Start container
await client.api.containers.manage({ operation: 'start' })

// Step 6: Create snapshot of clean state
await client.api.containers.createSnapshot(containerId, {
  name: 'initial-setup',
  alias: 'Clean install with env vars'
})

// Step 7: Monitor resource usage
const stats = await client.api.containers.getStats(containerId)
```

### 2. Proxy Security Configuration

Set up a complete proxy authentication layer with multiple auth groups.

```
const containerId = 'container-id'

// Step 1: Get current proxy settings (for ETag)
const settings = await client.api.proxyDiscovery.getContainerProxySettings(containerId)
const etag = settings.headers?.etag || 'file:v1'

// Step 2: Enable proxy
await client.api.proxyDiscovery.updateContainerProxySettings(containerId, etag, {
  enable_proxy: true,
  default: 'deny'
})

// Step 3: Create JWT auth group for API access
await client.api.proxyPermissionsContainer.setJwtGroup(
  containerId, 'api-clients', etag, {
    issuer: 'https://auth.mycompany.com',
    audience: 'my-app',
    jwks_url: 'https://auth.mycompany.com/.well-known/jwks.json'
  }
)

// Step 4: Create IP auth group for internal network
await client.api.proxyPermissionsContainer.setIpGroup(
  containerId, 'internal', etag, {
    allowed_ips: ['10.0.0.0/8', '172.16.0.0/12']
  }
)

// Step 5: Set program permissions for each group
await client.api.proxyPermissionsContainer.setGroup(
  containerId, 'api-clients', etag, {
    programs: { 'my-app': 'allow', 'admin-panel': 'deny' }
  }
)
await client.api.proxyPermissionsContainer.setGroup(
  containerId, 'internal', etag, {
    programs: { 'my-app': 'allow', 'admin-panel': 'allow' }
  }
)

// Step 6: Add a request hook for logging
await client.api.proxyHooks.addContainerProxyHook(
  containerId, 'my-app', etag, {
    match: '/api/*',
    script: `
      const log = { path: request.path, method: request.method, timestamp: Date.now() };
      return { continue: true };
    `,
    timeout: 1000
  }
)
```

### 3. Storage Sharing Between Containers

Share data from a database container to an application container.

```
// Step 1: Create share from database container
const share = await client.api.storageShares.create('db-container-id', {
  path: '/var/lib/postgresql/data/backups',
  target_container_id: 'app-container-id',
  mode: 'ro',
  label: 'db-backups'
})

// Step 2: On the target container, check incoming shares
const incoming = await client.api.storageShares.listIncoming({ id: 'app-container-id' })

// Step 3: Enable mounting on target
await client.api.storageShares.toggleIncomingMount(
  'app-container-id', share.data.id, {
    mount_enabled: true
  }
)

// Step 4: Verify the share is active
const details = await client.api.storageShares.get('db-container-id', share.data.id)
```

### 4. Server Provisioning Workflow

Rent a server and set up containers on it.

```
// Step 1: Browse available servers
const available = await client.api.serverRental.browse({
  country: 'US',
  min_cpu_cores: 8,
  min_ram_gb: 16,
  min_total_storage_gb: 500
})

// Step 2: Rent the server
const rental = await client.api.serverRental.rent(available.data[0].id, {
  duration_days: 30
})

// Step 3: Check available commands
const commands = await client.api.serverCommands.list(rental.data.server_id)

// Step 4: Execute setup command
await client.api.serverCommands.execute(rental.data.server_id, {
  command: 'initialize'
})

// Step 5: Create project and containers on the rented server
const project = await client.api.projects.create({
  alias: 'rented-infra'
})

const container = await client.api.containers.create(project.data.id, {
  alias: 'primary-app',
  image: 'ubuntu:22.04'
})
```

### 5. Container Clone and Sync Pattern

Clone a container for staging, then keep it in sync.

```
// Step 1: Clone production container for staging
const clone = await client.api.containers.copy('prod-container-id', {
  alias: 'staging-container',
  project_id: 'staging-project-id'
})
const stagingId = clone.data.id

// Step 2: Wait for clone to be ready, then modify env
await client.api.env.set(stagingId, 'NODE_ENV', {
  value: 'staging'
})

// Step 3: Periodically sync from production
await client.api.containers.sync(stagingId)

// Step 4: Verify sync via status logs
const logs = await client.api.containers.getStatusLogs(stagingId)
```

### 6. Batch Event Management

Clean up old events and monitor system health.

```
// Step 1: Get event statistics
const stats = await client.api.events.getStats()

// Step 2: List recent error events
const errors = await client.api.events.list({
  event_type: 'error',
  limit: 100,
  sort_by: 'created_at',
  sort_order: 'desc'
})

// Step 3: Bulk delete old events
await client.api.events.bulkDelete({
  before: '2024-01-01T00:00:00Z'
})

// Step 4: Run retention cleanup
await client.api.events.cleanup({
  retention_days: 90
})
```

### 7. Error Recovery Patterns

#### Recovering from Failed Container Operations

```
try {
  await client.api.containers.manage({ operation: 'start' })
} catch (error) {
  // Check current status
  const status = await client.api.containers.get({ id: 'container-id' })

  // If stuck, try force stop then restart
  if (status.data.state === 'error') {
    await client.api.containers.manage({ operation: 'force-stop' })
    await client.api.containers.manage({ operation: 'start' })
  }
}
```

#### Recovering from Proxy Configuration Errors

```
try {
  await client.api.proxyPermissionsContainer.replace('container-id', 'file:v5', config)
} catch (error) {
  if (error.status === 412) {
    // ETag mismatch — re-fetch and retry
    const current = await client.api.proxyPermissionsContainer.get({ id: 'container-id' })
    const freshEtag = `file:${current.data.file_version}`
    await client.api.proxyPermissionsContainer.replace(
      'container-id', freshEtag, config
    )
  }
}
```

#### Recovering from Firewall Lockout

```
// If you accidentally locked yourself out, reset to open
await client.api.firewall.reset({ id: 'container-id' })

// Then re-add rules carefully
await client.api.firewall.addIngressRule('container-id', {
  protocol: 'tcp',
  port: 22,
  source: 'your-ip/32',
  action: 'allow'
})
```

### 8. Multi-Resource Orchestration

#### Complete Project Teardown

```
const projectId = 'project-to-delete'

// Step 1: List all containers in the project
const containers = await client.api.containers.listByProject(projectId)

// Step 2: Stop all containers
for (const container of containers.data.items) {
  await client.api.containers.manage({ operation: 'force-stop' })
}

// Step 3: Delete all storage shares
for (const container of containers.data.items) {
  const shares = await client.api.storageShares.list(container.id)
  for (const share of shares.data.items) {
    await client.api.storageShares.delete(share.id)
  }
}

// Step 4: Delete all proxy aliases
const aliases = await client.api.proxyAliases.list({ project_id: projectId })
for (const alias of aliases.data.items) {
  await client.api.proxyAliases.delete(alias.id)
}

// Step 5: Delete the project (cascades to containers)
await client.api.projects.delete(projectId)
```

---

## Quick Reference

### Endpoint Groups Summary

| Resource Group | SDK Namespace | Base Path | Key Operations |
|---|---|---|---|
| Authentication | `client.api.authentication` | `/api/v1/users/auth/`, `/api/v1/auth/` | login, logout, refresh, signup, verify, OAuth |
| Auth Tokens | `client.api.authTokens` | `/api/v1/auth/tokens` | list, create, update, delete, copy, realms |
| Two-Factor Auth | `client.api.tfa` | `/api/v1/users/auth/2fa/` | setup, verify, status, disable, backup codes |
| Users | `client.api.users` | `/api/v1/users/` | get, update, retry-setup |
| Projects | `client.api.projects` | `/api/v1/projects/` | CRUD, permissions, stats |
| Containers | `client.api.containers` | `/api/v1/containers/`, `/api/v1/projects/{id}/containers` | CRUD, copy, sync, authorize, operations |
| Container Env | `client.api.env` | `/api/v1/containers/{id}/env` | list, bulk set, set, delete |
| Container Firewall | `client.api.firewall` | `/api/v1/containers/{id}/firewall/` | rules, reset, ingress, egress |
| Container Snapshots | `client.api.containers` | `/api/v1/containers/{id}/snapshots` | list, create, restore, delete, alias |
| Container Images | `client.api.images` | `/api/v1/images/` | public, user, import, purchase, rate |
| Proxy Permissions (Project) | `client.api.proxyPermissionsProject` | `/api/v1/projects/{id}/proxy/permissions` | get, replace, delete, groups, policies |
| Proxy Permissions (Container) | `client.api.proxyPermissionsContainer` | `/api/v1/containers/{id}/proxy/permissions` | get, replace, delete, groups, policies |
| Proxy Hooks | `client.api.proxyHooks` | `/api/v1/containers/{id}/proxy/hooks` | list, add, update, delete, move |
| Proxy Discovery | `client.api.proxyDiscovery` | `/api/v1/containers/{id}/proxy/` | settings, groups, services |
| Proxy Aliases | `client.api.proxyAliases` | `/api/v1/proxy/aliases` | CRUD, state toggle |
| Storage Shares | `client.api.storageShares` | `/api/v1/containers/{id}/storage/`, `/api/v1/storage/` | shares, incoming, mount toggle |
| Notifications | `client.api.notifications` | `/api/v1/notifications/` | list, public, mark read |
| Events | `client.api.events` | `/api/v1/events` | list, stats, delete, cleanup |
| Activity Logs | `client.api.activity` | `/api/v1/users/auth/activity` | list, stats |
| AI Models | `client.api.ai` | `/api/v1/ai/models` | list |
| Meta | `client.api.meta` | `/api/v1/meta/` | public-key, social-stats |
| Realms | `client.api.realms` | `/api/v1/realms/` | list |
| Vault | `client.api.vault` | `/api/v1/vault/` | stats, keys CRUD, clear |
| Wallet | `client.api.wallet` | `/api/v1/wallet/` | balances, transfers, transactions, payments, invoices |
| Pools | `client.api.pools` | `/api/v1/pools` | CRUD |
| Pool Members | `client.api.poolMembers` | `/api/v1/pools/{id}/members` | invite, update role, remove |
| Pool Invitations | `client.api.poolInvitations` | `/api/v1/pools/invitations/` | list, accept, reject |
| Server Rental | `client.api.serverRental` | `/api/v1/servers/` | browse, rent, list, get |
| Rentals | `client.api.rentals` | `/api/v1/rentals` | list, get, extend |
| Server Commands | `client.api.serverCommands` | `/api/v1/servers/{id}/` | execute, available-commands |
| Utilities | `client.api.utilities` | `/api/v1/ip` | getIpInfo |

### Essential Parameters

| Parameter | Description | Used By |
|---|---|---|
| `page`, `limit` | Pagination controls | Most list endpoints |
| `sort_by`, `sort_order` | Sorting (asc/desc) | Most list endpoints |
| `realm_id` | Scope to specific realm | projects, containers, events, vault |
| `If-Match` | Optimistic concurrency (ETag) | proxy permissions, hooks, settings |
| `include_proxy_domains` | Include proxy URLs in response | containers |
| `runtime` | Filter by container runtime | containers |
| `enabled` | Filter by enabled state | proxy aliases, storage shares |

### Typical Response Format

All API responses follow this structure:

```
{
  "success": true,
  "data": {
    "id": "resource-id",
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-01T00:00:00Z"
  }
}
```

Paginated responses include:

```
{
  "success": true,
  "data": {
    "items": [],
    "total": 100,
    "page": 1,
    "limit": 20,
    "pages": 5
  }
}
```

### Proxy URL Pattern

All Hoody Kit services use this automatic routing pattern:

```
https://{projectId}-{containerId}-{serviceName}-{serviceId}.{node}.containers.hoody.icu
```

Custom aliases mask this pattern for cleaner URLs:

```
https://my-app.example.com
```

### Error Handling

| Status | Meaning | Action |
|---|---|---|
| 400 | Bad request — invalid input | Check request body against schema |
| 401 | Unauthorized | Refresh token or re-authenticate |
| 403 | Forbidden — insufficient permissions | Check project/token permissions |
| 404 | Not found | Verify resource ID exists |
| 409 | Conflict — resource already exists | Check for duplicates |
| 412 | Precondition failed (ETag mismatch) | Re-fetch resource, get fresh ETag |
| 428 | Precondition required (missing ETag) | Add `If-Match` header |
| 429 | Rate limited | Implement backoff |
| 500 | Server error | Retry with exponential backoff |