# CodeBuddy Code HTTP API <sup>Beta</sup>

> **Beta**: This API is in Beta. Interfaces may be adjusted. Feedback is welcome.

CodeBuddy Code provides two public interface sets for developers building Agent applications:

- **REST API** (`/api/v1/*`) — Stateless HTTP request/response, suitable for webhook integration, management operations, and simple queries
- **ACP** (`/api/v1/acp`) — Stateful streaming protocol (JSON-RPC over SSE), suitable for building full Agent client applications

## Quick Start

### Starting the HTTP Service

```bash
codebuddy --serve --port 8080 --session-id my-session
```

### API Documentation (Swagger UI)

Once the service is running, visit:

- **Interactive docs**: `http://127.0.0.1:8080/api/docs`
- **OpenAPI spec**: `http://127.0.0.1:8080/api/openapi.json`

Swagger UI provides an interactive testing interface for all public endpoints.

### Verify the Service

```bash
curl http://127.0.0.1:8080/api/v1/health
# {"data":{"status":"ok","uptime":12.3,"platforms":["generic","wecom","wechat-kf"]}}
```

## API Layers

| Layer | Route Prefix | Compatibility Promise | Description |
|-------|-------------|----------------------|-------------|
| **Public REST API** | `/api/v1/*` | Semantic versioning, no breaking changes | Covered in this document |
| **Public ACP Protocol** | `/api/v1/acp` | Follows ACP specification | Full conversation capabilities, see [ACP Documentation](https://agentclientprotocol.com) |
| **Internal RPC** | `/internal/*` | No compatibility guarantee | For internal CLI use, not publicly available |

## Security

### Custom Request Header

All API requests (except [exempt paths](#exempt-paths)) must include the custom request header:

```
X-CodeBuddy-Request: 1
```

**Rationale**: A custom request header makes cross-origin browser requests "non-simple requests", forcing a CORS preflight. Combined with a CORS allowlist, requests from unauthorized origins are blocked. Even if an attacker uses `fetch(url, { mode: 'no-cors' })`, browsers do not allow custom headers in no-cors mode, so the request is rejected by the server (403) due to the missing header.

#### Exempt Paths

The following paths do not require the `X-CodeBuddy-Request` header:

| Path | Description |
|------|-------------|
| `GET /` | SPA entry page |
| `GET /assets/*` | Static assets |
| `GET /docs/*` | API documentation pages |
| `GET /manifest.webmanifest` | PWA manifest |
| `GET /api/v1/auth/status` | Authentication status check |
| `POST /api/v1/auth/login` | Login |
| `*/api/v1/webhooks/*` | Webhooks (verified by platform signature) |
| `GET /api/openapi.json` | OpenAPI spec |
| `GET /api/docs*` | Swagger UI |

This validation can be disabled via the environment variable `CODEBUDDY_DISABLE_REQUEST_VALIDATION=1`.

### Authentication

Two modes are supported (controlled by environment variable `CODEBUDDY_GATEWAY_AUTH`):

| Mode | Value | Description |
|------|-------|-------------|
| No authentication | `none` (default) | For local development, no authentication required |
| Password authentication | `password` | Automatically enabled for remote access |

Password authentication supports the following methods (any one passing is sufficient):

```bash
# Bearer Token (with security header)
curl -H "X-CodeBuddy-Request: 1" \
     -H "Authorization: Bearer YOUR_PASSWORD" \
     http://host:port/api/v1/sessions

# URL parameter
curl -H "X-CodeBuddy-Request: 1" \
     http://host:port/api/v1/sessions?password=YOUR_PASSWORD
```

## Response Format

All `/api/v1/*` endpoints use a unified envelope format:

```jsonc
// Success
{
    "data": { ... }
}

// Error
{
    "error": {
        "code": "AUTH_REQUIRED",      // Machine-readable error code
        "message": "Authentication required"  // Human-readable description
    }
}
```

## Endpoint Overview

### System

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/health` | Health check |
| GET | `/api/v1/info` | Environment info (version, OS, CWD, etc.) |
| GET | `/api/v1/metrics` | System resource metrics + instance process metrics |
| GET | `/api/v1/envs` | Environment variables (aligned with E2B envd) |

### Authentication

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/auth/status` | Get authentication status |
| POST | `/api/v1/auth/login` | Password login, returns token |

### Runs (Agent Execution)

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/runs` | Initiate Agent execution (async, returns runId) |
| GET | `/api/v1/runs/:runId` | Query execution status |
| GET | `/api/v1/runs/:runId/stream` | SSE streaming of execution results |
| POST | `/api/v1/runs/:runId/cancel` | Cancel execution |

### Webhooks (Third-party Platform Integration)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/webhooks/:platform` | Platform URL verification (WeCom, etc.) |
| POST | `/api/v1/webhooks/:platform` | Platform message webhook entry |

Supported platforms: `generic`, `wecom` (WeCom), `wechat-kf` (WeChat Customer Service)

### Sessions

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/sessions` | Get session list (supports cwd query parameter) |
| DELETE | `/api/v1/sessions/:id` | Delete session |
| POST | `/api/v1/sessions/:id/rename` | Rename session |
| GET | `/api/v1/sessions/across-projects` | ⚠️ Deprecated, use `GET /api/v1/sessions?cwd=*` instead |
| GET | `/api/v1/sessions/workspaces` | ⚠️ Deprecated |

### PTY (Terminal)

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/pty` | Create PTY session |
| GET | `/api/v1/pty` | List PTY sessions |
| GET | `/api/v1/pty/:id` | Query PTY session |
| DELETE | `/api/v1/pty/:id` | Destroy PTY session |
| GET | `/api/v1/pty/:id/output` | SSE streaming of PTY output (replaces WebSocket) |
| POST | `/api/v1/pty/:id/input/send` | Send PTY input (aligned with E2B Process.SendInput) |
| POST | `/api/v1/pty/:id/resize` | Resize PTY (aligned with E2B Process.Update) |
| WebSocket | `/api/v1/pty/:id/ws` | PTY bidirectional data transport (legacy compatible) |

### Workers & Daemon

A Worker is a running CLI process (interactive / bg / daemon), managed through a PID file registry.

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/workers` | Get all active Worker list |
| POST | `/api/v1/workers` | Manually add remote Worker |
| GET | `/api/v1/workers/:id` | Get Worker details (by PID or name) |
| GET | `/api/v1/workers/:id/logs` | Get Worker logs (supports multiple types) |
| DELETE | `/api/v1/workers/:id` | Terminate Worker process |
| GET | `/api/v1/daemon/status` | Query Daemon status |
| POST | `/api/v1/daemon/start` | Start Daemon |
| POST | `/api/v1/daemon/stop` | Stop Daemon |
| POST | `/api/v1/daemon/restart` | Restart Daemon |

**Workers query parameters**:
- `?kind=bg` — Filter by type (interactive / bg / daemon / daemon-worker)
- `?local=true` — Return local Workers only (used for remote proxy calls)

**Log type parameters** (`GET /api/v1/workers/:id/logs`):
- `?type=telemetry` — Telemetry logs (`~/.codebuddy/logs/{date}/`)
- `?type=process` — Process stdout/stderr (bg/daemon logs)
- `?type=debug` — Debug logs (`~/.codebuddy/debug/`, requires `--debug`)
- `?type=transcript` — Conversation history summary
- `?tail=200` — Return only the last N lines
- When type is omitted, the best source is automatically selected (telemetry > process > debug > transcript)

### Channels (Remote Control)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/channels` | Get client list |
| POST | `/api/v1/channels/:type/:id/start` | Start client |
| POST | `/api/v1/channels/:type/:id/stop` | Stop client |
| POST | `/api/v1/channels/wechat` | Create WeChat instance |
| POST | `/api/v1/channels/wecom` | Create WeCom instance |

### Filesystem (E2B Compatible)

File content operations (aligned with E2B envd HTTP endpoints):

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/files/download?path=...` | Download file (aligned with E2B envd GET /files) |
| POST | `/api/v1/files/upload?path=...` | Upload file (aligned with E2B envd POST /files) |
| POST | `/api/v1/files/compose` | Compose multiple files (aligned with E2B envd POST /files/compose) |

File operations (aligned with E2B filesystem.proto):

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/fs/stat` | Get file/directory info (aligned with Filesystem.Stat) |
| POST | `/api/v1/fs/list` | List directory contents (aligned with Filesystem.ListDir) |
| POST | `/api/v1/fs/mkdir` | Create directory (aligned with Filesystem.MakeDir) |
| POST | `/api/v1/fs/remove` | Remove file/directory (aligned with Filesystem.Remove) |
| POST | `/api/v1/fs/move` | Move/rename (aligned with Filesystem.Move) |

File watching (aligned with E2B filesystem.proto):

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/fs/watch` | Streaming directory watch SSE (aligned with Filesystem.WatchDir) |
| POST | `/api/v1/fs/watcher/create` | Create watcher (aligned with Filesystem.CreateWatcher) |
| POST | `/api/v1/fs/watcher/events` | Get watcher events (aligned with Filesystem.GetWatcherEvents) |
| POST | `/api/v1/fs/watcher/remove` | Remove watcher (aligned with Filesystem.RemoveWatcher) |

CBC enhancements:

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/fs/search?query=...` | Fuzzy file search (based on ripgrep, no E2B equivalent) |

### Process Management (E2B Compatible)

Aligned with E2B process.proto, mapping gRPC methods to REST endpoints:

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/process/start` | Start process (aligned with Process.Start, supports SSE/JSON) |
| GET | `/api/v1/process/list` | List running processes (aligned with Process.List) |
| POST | `/api/v1/process/connect` | Connect to process SSE stream (aligned with Process.Connect) |
| POST | `/api/v1/process/input/send` | Send stdin (aligned with Process.SendInput) |
| POST | `/api/v1/process/input/stream` | Stream stdin (aligned with Process.StreamInput) |
| POST | `/api/v1/process/signal/send` | Send signal (aligned with Process.SendSignal) |
| POST | `/api/v1/process/stdin/close` | Close stdin (aligned with Process.CloseStdin) |
| POST | `/api/v1/process/update` | Update process config such as PTY resize (aligned with Process.Update) |

### ACP (Agent Client Protocol)

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/acp/connect` | Establish ACP connection, returns connectionId and sessionToken |
| GET | `/api/v1/acp` | SSE notification subscription (requires acp-connection-id Header) |
| POST | `/api/v1/acp` | Send JSON-RPC requests (newSession, prompt, cancelRun, etc.) |
| DELETE | `/api/v1/acp` | Disconnect |

### File Changes (Checkpoint) — Internal

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/internal/file-changes/diff` | Get diff content for a single file |
| POST | `/internal/file-changes/checkpoints` | List checkpoints available for rollback |
| POST | `/internal/file-changes/revert` | Revert file changes or rollback to a checkpoint |

> **Note**: These are internal endpoints with no stability guarantee, consumed only by the Web UI.

### Plugin Management

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/plugins` | List installed plugins |
| POST | `/api/v1/plugins` | Install plugin |
| POST | `/api/v1/plugins/validate` | Validate plugin/marketplace manifest file |
| POST | `/api/v1/plugins/enable` | Enable plugin |
| POST | `/api/v1/plugins/disable` | Disable plugin |
| POST | `/api/v1/plugins/uninstall` | Uninstall plugin |
| GET | `/api/v1/plugins/marketplaces` | List configured plugin marketplaces |
| POST | `/api/v1/plugins/marketplaces` | Add plugin marketplace |
| POST | `/api/v1/plugins/marketplaces/browse` | Browse available plugins in marketplace |
| POST | `/api/v1/plugins/marketplaces/update` | Update marketplace (sync remote repository content) |
| DELETE | `/api/v1/plugins/marketplaces/:name` | Delete plugin marketplace |

### Settings Management

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/settings` | List all settings |
| GET | `/api/v1/settings/:key` | Get a single setting value |
| PUT | `/api/v1/settings/:key` | Set a setting value |
| POST | `/api/v1/settings/:key/items` | Append values to an array-type setting |
| POST | `/api/v1/settings/:key/remove` | Remove values from an array-type setting |

### Task Templates

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/tasks/templates` | Get task templates |
| POST | `/api/v1/tasks/templates/refresh` | Refresh (trigger AI recommendations) |

### Usage Statistics

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/stats` | Historical usage statistics (across all projects) |
| GET | `/api/v1/stats/session` | Current session real-time statistics |

### Traces

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/traces` | Get trace list (supports pagination and filtering) |
| GET | `/api/v1/traces/:traceId` | Get trace details (with spans) |
| DELETE | `/api/v1/traces` | Clear all traces |

**Traces query parameters**:
- `?offset=0&limit=50` — Pagination (limit max 200)
- `?session_id=xxx` — Filter by session ID
- `?worker_pid=12345` — Specify Worker instance (supports remote proxy)
- `?worker_pid=all` — Scan all instances

### Scheduled Tasks

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/scheduled-tasks` | Get scheduled task list |
| POST | `/api/v1/scheduled-tasks` | Create scheduled task |
| DELETE | `/api/v1/scheduled-tasks/:id` | Delete scheduled task |

**Scheduled task query parameters**:
- `?sessionId=xxx` — Session ID (required, uses current active session if not provided)

## Usage Examples

### Health Check

```bash
curl http://127.0.0.1:8080/api/v1/health
```

### Initiate Agent Execution

```bash
# Send message
curl -X POST http://127.0.0.1:8080/api/v1/runs \
  -H "Content-Type: application/json" \
  -d '{"text": "Help me analyze code performance", "sender": {"id": "dev", "name": "Developer"}}'

# Response: {"data": {"runId": "uuid-xxx", "status": "accepted"}}

# Get results via SSE stream
curl http://127.0.0.1:8080/api/v1/runs/uuid-xxx/stream
```

### PTY Terminal Management

```bash
# Create terminal
curl -X POST http://127.0.0.1:8080/api/v1/pty \
  -H "Content-Type: application/json" \
  -d '{"cols": 120, "rows": 40}'

# List terminals
curl http://127.0.0.1:8080/api/v1/pty

# SSE streaming output (replaces WebSocket)
curl http://127.0.0.1:8080/api/v1/pty/SESSION_ID/output

# Send input
curl -X POST http://127.0.0.1:8080/api/v1/pty/SESSION_ID/input/send \
  -H "Content-Type: application/json" \
  -d '{"data": "ls -la\n"}'

# Resize
curl -X POST http://127.0.0.1:8080/api/v1/pty/SESSION_ID/resize \
  -H "Content-Type: application/json" \
  -d '{"cols": 200, "rows": 50}'

# Destroy terminal
curl -X DELETE http://127.0.0.1:8080/api/v1/pty/SESSION_ID
```

### Filesystem Operations (E2B Compatible)

```bash
# Download file
curl "http://127.0.0.1:8080/api/v1/files/download?path=/tmp/test.txt"

# Upload file
curl -X POST "http://127.0.0.1:8080/api/v1/files/upload?path=/tmp/upload.txt" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @local-file.txt

# Get file info
curl -X POST http://127.0.0.1:8080/api/v1/fs/stat \
  -H "Content-Type: application/json" \
  -d '{"path": "/tmp"}'

# List directory
curl -X POST http://127.0.0.1:8080/api/v1/fs/list \
  -H "Content-Type: application/json" \
  -d '{"path": "/tmp", "depth": 2}'

# Create directory
curl -X POST http://127.0.0.1:8080/api/v1/fs/mkdir \
  -H "Content-Type: application/json" \
  -d '{"path": "/tmp/new-dir"}'

# Fuzzy file search (CBC enhancement)
curl "http://127.0.0.1:8080/api/v1/fs/search?query=component&limit=10"
```

### Process Management (E2B Compatible)

```bash
# Start process (JSON mode)
curl -X POST http://127.0.0.1:8080/api/v1/process/start \
  -H "Content-Type: application/json" \
  -d '{"process": {"cmd": "python3", "args": ["script.py"]}, "tag": "my-script"}'

# Start process (SSE streaming output)
curl -X POST http://127.0.0.1:8080/api/v1/process/start \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"process": {"cmd": "python3", "args": ["script.py"]}}'

# List running processes
curl http://127.0.0.1:8080/api/v1/process/list

# Send stdin
curl -X POST http://127.0.0.1:8080/api/v1/process/input/send \
  -H "Content-Type: application/json" \
  -d '{"process": {"pid": 12345}, "input": {"stdin": "hello\n"}}'

# Send signal (SIGTERM)
curl -X POST http://127.0.0.1:8080/api/v1/process/signal/send \
  -H "Content-Type: application/json" \
  -d '{"process": {"tag": "my-script"}, "signal": 15}'

# System metrics + instance process metrics
curl http://127.0.0.1:8080/api/v1/metrics
# Response: { data: { ts, cpuCount, cpuUsedPct, memTotalMib, memUsedMib, diskUsed, diskTotal, instances: [{ id, cwd, pid, rssMib, heapUsedMib, heapTotalMib, uptimeSeconds, ... }] } }
```

### Session Management

```bash
# Get session list for the current workspace
curl http://127.0.0.1:8080/api/v1/sessions

# Get session list across all workspaces
curl http://127.0.0.1:8080/api/v1/sessions?cwd=*

# Get session list for a specific working directory
curl http://127.0.0.1:8080/api/v1/sessions?cwd=/path/to/workspace

# Get session list for a specific project (filter by compressed working directory name)
curl http://127.0.0.1:8080/api/v1/sessions?cwd=*&projectId=workspace-hash

# Rename session
curl -X POST http://127.0.0.1:8080/api/v1/sessions/SESSION_ID/rename \
  -H "Content-Type: application/json" \
  -d '{"name": "Performance Optimization Discussion"}'
```

**cwd query parameter reference**:

| cwd Value | Description |
|-----------|-------------|
| Not provided | Returns sessions for the current workspace |
| `*` | Returns sessions across all workspaces |
| `/path/to/workspace` | Returns sessions for the specified working directory |

### File Change Management (Internal)

```bash
# Get file diff (requires file to be tracked in a checkpoint)
curl -X POST http://127.0.0.1:8080/internal/file-changes/diff \
  -H "Content-Type: application/json" \
  -d '{"path": "/path/to/file.ts"}'
# Response: {"data": {"path": "/path/to/file.ts", "oldText": "...", "newText": "..."}}

# List checkpoints available for rollback
curl -X POST http://127.0.0.1:8080/internal/file-changes/checkpoints \
  -H "Content-Type: application/json" \
  -d '{}'
# Response: {"data": {"checkpoints": [{"id": "xxx", "label": "...", "createdAt": 1234567890, "files": [...], "additions": 5, "deletions": 2}]}}

# Revert changes by file
curl -X POST http://127.0.0.1:8080/internal/file-changes/revert \
  -H "Content-Type: application/json" \
  -d '{"paths": ["/path/to/file.ts"]}'
# Response: {"data": {"success": true, "revertedFiles": ["/path/to/file.ts"]}}

# Rollback to a specific checkpoint
curl -X POST http://127.0.0.1:8080/internal/file-changes/revert \
  -H "Content-Type: application/json" \
  -d '{"checkpointId": "checkpoint-uuid", "scope": "CodeAndConversation"}'
# scope options: "Code" (revert files only), "Conversation" (revert conversation only), "CodeAndConversation" (revert all)

# Revert all changes (rollback to the earliest checkpoint)
curl -X POST http://127.0.0.1:8080/internal/file-changes/revert \
  -H "Content-Type: application/json" \
  -d '{}'
```

### Plugin Management

```bash
# List installed plugins
curl http://127.0.0.1:8080/api/v1/plugins

# Install plugin ("name@marketplace" format)
curl -X POST http://127.0.0.1:8080/api/v1/plugins \
  -H "Content-Type: application/json" \
  -d '{"plugin": "my-plugin@my-marketplace"}'

# Enable plugin
curl -X POST http://127.0.0.1:8080/api/v1/plugins/enable \
  -H "Content-Type: application/json" \
  -d '{"plugin": "my-plugin@my-marketplace"}'

# Disable plugin
curl -X POST http://127.0.0.1:8080/api/v1/plugins/disable \
  -H "Content-Type: application/json" \
  -d '{"plugin": "my-plugin@my-marketplace"}'

# Uninstall plugin
curl -X POST http://127.0.0.1:8080/api/v1/plugins/uninstall \
  -H "Content-Type: application/json" \
  -d '{"plugin": "my-plugin@my-marketplace"}'

# List plugin marketplaces
curl http://127.0.0.1:8080/api/v1/plugins/marketplaces

# Add plugin marketplace
curl -X POST http://127.0.0.1:8080/api/v1/plugins/marketplaces \
  -H "Content-Type: application/json" \
  -d '{"source": "https://example.com/marketplace", "name": "my-marketplace"}'

# Browse plugins in marketplace
curl -X POST http://127.0.0.1:8080/api/v1/plugins/marketplaces/browse \
  -H "Content-Type: application/json" \
  -d '{"marketplace": "my-marketplace"}'

# Update marketplace (actually pulls latest content from remote)
curl -X POST http://127.0.0.1:8080/api/v1/plugins/marketplaces/update \
  -H "Content-Type: application/json" \
  -d '{"marketplace": "my-marketplace"}'

# Delete plugin marketplace
curl -X DELETE http://127.0.0.1:8080/api/v1/plugins/marketplaces/my-marketplace
```

### Settings Management

```bash
# List all settings
curl http://127.0.0.1:8080/api/v1/settings

# List settings by scope
curl "http://127.0.0.1:8080/api/v1/settings?scope=user"

# Get a single setting
curl http://127.0.0.1:8080/api/v1/settings/model

# Set a setting value
curl -X PUT http://127.0.0.1:8080/api/v1/settings/theme \
  -H "Content-Type: application/json" \
  -d '{"value": "dark"}'

# Append values to an array-type setting
curl -X POST http://127.0.0.1:8080/api/v1/settings/permissions/items \
  -H "Content-Type: application/json" \
  -d '{"values": ["Allow: Read(**)"]}'

# Remove values from an array-type setting
curl -X POST http://127.0.0.1:8080/api/v1/settings/permissions/remove \
  -H "Content-Type: application/json" \
  -d '{"values": ["Allow: Read(**)"]}'
```

### Usage Statistics

```bash
# Get historical usage statistics (activity heatmap, model/tool usage rankings, consecutive active days, etc.)
curl http://127.0.0.1:8080/api/v1/stats

# Get current session real-time cost statistics
curl http://127.0.0.1:8080/api/v1/stats/session
```

### Traces

```bash
# Get trace list (paginated)
curl "http://127.0.0.1:8080/api/v1/traces?offset=0&limit=20"

# Filter by session ID
curl "http://127.0.0.1:8080/api/v1/traces?session_id=SESSION_ID"

# Get trace details (with all spans)
curl http://127.0.0.1:8080/api/v1/traces/TRACE_ID

# Get traces from a remote Worker
curl "http://127.0.0.1:8080/api/v1/traces?worker_pid=12345"

# Clear all traces
curl -X DELETE http://127.0.0.1:8080/api/v1/traces
```

### Scheduled Task Management

```bash
# Get scheduled task list
curl "http://127.0.0.1:8080/api/v1/scheduled-tasks?sessionId=SESSION_ID"

# Create scheduled task (every 5 minutes)
curl -X POST http://127.0.0.1:8080/api/v1/scheduled-tasks \
  -H "Content-Type: application/json" \
  -d '{"cron": "*/5 * * * *", "prompt": "Check build status", "sessionId": "SESSION_ID"}'

# Create one-time task (every Monday at 9 AM)
curl -X POST http://127.0.0.1:8080/api/v1/scheduled-tasks \
  -H "Content-Type: application/json" \
  -d '{"cron": "0 9 * * 1", "prompt": "Generate weekly report", "recurring": false, "sessionId": "SESSION_ID"}'

# Create durable task (persists after restart)
curl -X POST http://127.0.0.1:8080/api/v1/scheduled-tasks \
  -H "Content-Type: application/json" \
  -d '{"cron": "0 0 * * *", "prompt": "Daily cleanup", "durable": true, "sessionId": "SESSION_ID"}'

# Delete scheduled task
curl -X DELETE "http://127.0.0.1:8080/api/v1/scheduled-tasks/TASK_ID?sessionId=SESSION_ID"
```

## Error Codes

| Error Code | HTTP Status | Description |
|------------|------------|-------------|
| `AUTH_REQUIRED` | 401 | Authentication required |
| `AUTH_INVALID` | 401 | Invalid authentication |
| `AUTH_RATE_LIMITED` | 429 | Too many login attempts |
| `NOT_FOUND` | 404 | Resource not found |
| `BAD_REQUEST` | 400 | Invalid request parameters |
| `RATE_LIMITED` | 429 | Request rate too high |
| `INTERNAL_ERROR` | 500 | Internal server error |
| `SESSION_NOT_FOUND` | 404 | Session not found |
| `SESSION_DELETE_CURRENT` | 400 | Cannot delete current session |
| `TERMINAL_NOT_FOUND` | 404 | PTY not found |
| `PROCESS_NOT_FOUND` | 404 | Process not found |
| `PATH_REQUIRED` | 400 | Missing path parameter |
| `PATH_NOT_DIRECTORY` | 400 | Path is not a directory |
| `INSUFFICIENT_STORAGE` | 507 | Insufficient disk space |
| `RUN_NOT_FOUND` | 404 | Run not found |
| `PLATFORM_UNSUPPORTED` | 400 | Unsupported webhook platform |
| `SIGNATURE_INVALID` | 403 | Signature verification failed |
