{ "openapi": "3.1.0", "info": { "title": "Agent Swarm API", "version": "1.75.0", "description": "Multi-agent orchestration API for Claude Code, Codex, and Gemini CLI. Enables task distribution, agent communication, and service discovery.\n\nMCP tools are documented separately in [MCP.md](./MCP.md)." }, "servers": [ { "url": "http://localhost:3013", "description": "Local development" } ], "components": { "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer", "description": "API key via Authorization: Bearer " }, "agentId": { "type": "apiKey", "in": "header", "name": "X-Agent-ID", "description": "Agent UUID for agent-scoped operations" } }, "schemas": {}, "parameters": {} }, "paths": { "/api/active-sessions": { "get": { "summary": "List active sessions", "tags": [ "Active Sessions" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "format": "uuid" }, "required": false, "name": "agentId", "in": "query" } ], "responses": { "200": { "description": "Active session list" } } }, "post": { "summary": "Create a new active session", "tags": [ "Active Sessions" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "agentId": { "type": "string", "minLength": 1 }, "taskId": { "type": "string" }, "triggerType": { "type": "string", "minLength": 1 }, "inboxMessageId": { "type": "string" }, "taskDescription": { "type": "string" }, "runnerSessionId": { "type": "string" } }, "required": [ "agentId", "triggerType" ] } } } }, "responses": { "201": { "description": "Session created" }, "400": { "description": "Validation error" } } } }, "/api/active-sessions/by-task/{taskId}": { "delete": { "summary": "Delete active session by task ID", "tags": [ "Active Sessions" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "taskId", "in": "path" } ], "responses": { "200": { "description": "Session deleted" } } } }, "/api/active-sessions/{id}": { "delete": { "summary": "Delete active session by ID", "tags": [ "Active Sessions" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Session deleted" } } } }, "/api/active-sessions/heartbeat/{taskId}": { "put": { "summary": "Update heartbeat for an active session", "tags": [ "Active Sessions" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "taskId", "in": "path" } ], "responses": { "200": { "description": "Heartbeat updated" } } } }, "/api/active-sessions/provider-session/{taskId}": { "put": { "summary": "Update provider session ID on an active session", "tags": [ "Active Sessions" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "taskId", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "providerSessionId": { "type": "string", "minLength": 1 } }, "required": [ "providerSessionId" ] } } } }, "responses": { "200": { "description": "Provider session ID updated" } } } }, "/api/active-sessions/cleanup": { "post": { "summary": "Clean up stale sessions", "tags": [ "Active Sessions" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "agentId": { "type": "string" }, "maxAgeMinutes": { "type": "integer" } } } } } }, "responses": { "200": { "description": "Cleanup result" } } } }, "/api/agents": { "post": { "summary": "Register or re-register an agent", "tags": [ "Agents" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "isLead": { "type": "boolean" }, "description": { "type": "string" }, "role": { "type": "string" }, "capabilities": { "type": "array", "items": { "type": "string" } }, "maxTasks": { "type": "integer" }, "provider": { "type": "string", "enum": [ "claude", "codex", "pi", "devin", "claude-managed", "opencode" ] }, "harness_provider": { "type": "string", "enum": [ "claude", "codex", "pi", "devin", "claude-managed", "opencode" ] } }, "required": [ "name" ] } } } }, "responses": { "200": { "description": "Agent re-registered (already existed)" }, "201": { "description": "Agent created" }, "400": { "description": "Validation error" } } }, "get": { "summary": "List all agents", "tags": [ "Agents" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "tasks" ] }, "required": false, "name": "include", "in": "query" } ], "responses": { "200": { "description": "Agent list with capacity info" } } } }, "/api/agents/{id}/harness-provider": { "patch": { "summary": "Re-assign an agent's harness_provider (planning/forecast — not live)", "description": "Updates the `agents.harness_provider` column. Worker does NOT react in real time — the new value is picked up on the next worker restart, where the env-driven HARNESS_PROVIDER still wins on register. Live per-agent re-assignment is tracked in DES-359.", "tags": [ "Agents" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "harness_provider": { "type": "string", "enum": [ "claude", "codex", "pi", "devin", "claude-managed", "opencode" ] } }, "required": [ "harness_provider" ] } } } }, "responses": { "200": { "description": "Updated agent row" }, "400": { "description": "Validation error (unknown provider)" }, "404": { "description": "Agent not found" } } } }, "/api/agents/{id}/name": { "put": { "summary": "Update agent name", "tags": [ "Agents" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 } }, "required": [ "name" ] } } } }, "responses": { "200": { "description": "Agent updated" }, "404": { "description": "Agent not found" }, "409": { "description": "Name conflict" } } } }, "/api/agents/{id}/setup-script": { "get": { "summary": "Fetch agent + global setup scripts for Docker entrypoint", "tags": [ "Agents" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Setup scripts" }, "404": { "description": "Agent not found" } } } }, "/api/agents/{id}/profile": { "put": { "summary": "Update agent profile (role, description, capabilities, etc.)", "tags": [ "Agents" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "role": { "type": "string", "maxLength": 100 }, "description": { "type": "string" }, "capabilities": { "type": "array", "items": { "type": "string" } }, "claudeMd": { "type": "string", "maxLength": 65536 }, "soulMd": { "type": "string", "maxLength": 65536 }, "identityMd": { "type": "string", "maxLength": 65536 }, "setupScript": { "type": "string", "maxLength": 65536 }, "toolsMd": { "type": "string", "maxLength": 65536 }, "heartbeatMd": { "type": "string", "maxLength": 65536 }, "changeSource": { "type": "string" }, "changedByAgentId": { "type": "string" }, "changeReason": { "type": "string" } } } } } }, "responses": { "200": { "description": "Profile updated" }, "400": { "description": "Validation error" }, "404": { "description": "Agent not found" } } } }, "/api/agents/{id}/activity": { "put": { "summary": "Update agent last activity timestamp", "tags": [ "Agents" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "204": { "description": "Activity updated" } } } }, "/api/agents/{id}": { "get": { "summary": "Get a single agent", "tags": [ "Agents" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "string", "enum": [ "tasks" ] }, "required": false, "name": "include", "in": "query" } ], "responses": { "200": { "description": "Agent with capacity info" }, "404": { "description": "Agent not found" } } } }, "/api/agents/{id}/credential-status": { "put": { "summary": "Worker self-report of credential readiness (Phase 3 boot loop)", "tags": [ "Agents" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "ready": { "type": "boolean" }, "missing": { "type": [ "array", "null" ], "items": { "type": "string" } } }, "required": [ "ready" ] } } } }, "responses": { "200": { "description": "State updated; returns the agent row." }, "404": { "description": "Agent not found" } } }, "get": { "summary": "Single-agent credential-status snapshot for the dashboard", "tags": [ "Agents" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Credential status payload" }, "404": { "description": "Agent not found" } } } }, "/api/agents/credential-status": { "get": { "summary": "Bulk credential-status across all agents (powers the dashboard)", "tags": [ "Agents" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "idle", "busy", "offline", "waiting_for_credentials" ] }, "required": false, "name": "status", "in": "query" } ], "responses": { "200": { "description": "List of {agentId, status, missing[], lastCheckedAt}" } } } }, "/api/approval-requests": { "post": { "summary": "Create a new approval request", "tags": [ "ApprovalRequests" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "title": { "type": "string", "minLength": 1 }, "questions": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "type": { "type": "string", "enum": [ "approval", "text", "single-select", "multi-select", "boolean" ] }, "label": { "type": "string" }, "required": { "type": "boolean" }, "description": { "type": "string" }, "placeholder": { "type": "string" }, "multiline": { "type": "boolean" }, "options": { "type": "array", "items": { "type": "object", "properties": { "value": { "type": "string" }, "label": { "type": "string" }, "description": { "type": "string" } }, "required": [ "value", "label" ] } }, "minSelections": { "type": "integer", "minimum": 0 }, "maxSelections": { "type": "integer", "minimum": 1 }, "defaultValue": { "type": "boolean" } }, "required": [ "id", "type", "label" ] }, "minItems": 1 }, "approvers": { "type": "object", "properties": { "users": { "type": "array", "items": { "type": "string" } }, "roles": { "type": "array", "items": { "type": "string" } }, "policy": { "anyOf": [ { "type": "string", "enum": [ "any" ] }, { "type": "string", "enum": [ "all" ] }, { "type": "object", "properties": { "min": { "type": "integer", "minimum": 1 } }, "required": [ "min" ] } ] } }, "required": [ "policy" ] }, "workflowRunId": { "type": "string", "format": "uuid" }, "workflowRunStepId": { "type": "string", "format": "uuid" }, "sourceTaskId": { "type": "string", "format": "uuid" }, "timeoutSeconds": { "type": "integer", "minimum": 1 }, "notifications": { "type": "array", "items": { "type": "object", "properties": { "channel": { "type": "string", "enum": [ "slack", "email" ] }, "target": { "type": "string" } }, "required": [ "channel", "target" ] } } }, "required": [ "title", "questions", "approvers" ] } } } }, "responses": { "201": { "description": "Approval request created" }, "400": { "description": "Validation error" } } }, "get": { "summary": "List approval requests with optional filters", "tags": [ "ApprovalRequests" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "status", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "workflowRunId", "in": "query" }, { "schema": { "type": [ "number", "null" ] }, "required": false, "name": "limit", "in": "query" } ], "responses": { "200": { "description": "List of approval requests" } } } }, "/api/approval-requests/{id}": { "get": { "summary": "Get approval request details", "tags": [ "ApprovalRequests" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "format": "uuid" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Approval request details" }, "404": { "description": "Not found" } } } }, "/api/approval-requests/{id}/respond": { "post": { "summary": "Submit a response to an approval request", "tags": [ "ApprovalRequests" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "format": "uuid" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "responses": { "type": "object", "additionalProperties": {} }, "respondedBy": { "type": "string" } }, "required": [ "responses" ] } } } }, "responses": { "200": { "description": "Response recorded" }, "400": { "description": "Validation error" }, "404": { "description": "Not found" }, "409": { "description": "Already resolved" } } } }, "/api/budgets": { "get": { "summary": "List all configured budget rows", "tags": [ "Budgets" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Budget list", "content": { "application/json": { "schema": { "type": "object", "properties": { "budgets": { "type": "array", "items": { "type": "object", "properties": { "scope": { "type": "string", "enum": [ "global", "agent" ] }, "scopeId": { "type": "string" }, "dailyBudgetUsd": { "type": "number", "minimum": 0 }, "createdAt": { "type": "number" }, "lastUpdatedAt": { "type": "number" } }, "required": [ "scope", "scopeId", "dailyBudgetUsd", "createdAt", "lastUpdatedAt" ] } } }, "required": [ "budgets" ] } } } } } } }, "/api/budgets/refusals": { "get": { "summary": "List recent budget refusal notifications", "tags": [ "Budgets" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "integer", "exclusiveMinimum": 0, "maximum": 500 }, "required": false, "name": "limit", "in": "query" } ], "responses": { "200": { "description": "Recent budget refusals (newest first)", "content": { "application/json": { "schema": { "type": "object", "properties": { "refusals": { "type": "array", "items": { "type": "object", "properties": { "taskId": { "type": "string" }, "date": { "type": "string" }, "agentId": { "type": "string" }, "cause": { "type": "string", "enum": [ "agent", "global" ] }, "agentSpendUsd": { "type": [ "number", "null" ] }, "agentBudgetUsd": { "type": [ "number", "null" ] }, "globalSpendUsd": { "type": [ "number", "null" ] }, "globalBudgetUsd": { "type": [ "number", "null" ] }, "followUpTaskId": { "type": [ "string", "null" ] }, "createdAt": { "type": "number" } }, "required": [ "taskId", "date", "agentId", "cause", "createdAt" ] } } }, "required": [ "refusals" ] } } } } } } }, "/api/budgets/{scope}/{scopeId}": { "get": { "summary": "Get a single budget row", "tags": [ "Budgets" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "global", "agent" ] }, "required": true, "name": "scope", "in": "path" }, { "schema": { "type": "string", "maxLength": 255, "description": "Scope identifier — empty string for global, agent UUID otherwise" }, "required": true, "description": "Scope identifier — empty string for global, agent UUID otherwise", "name": "scopeId", "in": "path" } ], "responses": { "200": { "description": "Budget row", "content": { "application/json": { "schema": { "type": "object", "properties": { "scope": { "type": "string", "enum": [ "global", "agent" ] }, "scopeId": { "type": "string" }, "dailyBudgetUsd": { "type": "number", "minimum": 0 }, "createdAt": { "type": "number" }, "lastUpdatedAt": { "type": "number" } }, "required": [ "scope", "scopeId", "dailyBudgetUsd", "createdAt", "lastUpdatedAt" ] } } } }, "404": { "description": "Budget not configured" } } }, "put": { "summary": "Create or update a budget row", "tags": [ "Budgets" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "global", "agent" ] }, "required": true, "name": "scope", "in": "path" }, { "schema": { "type": "string", "maxLength": 255, "description": "Scope identifier — empty string for global, agent UUID otherwise" }, "required": true, "description": "Scope identifier — empty string for global, agent UUID otherwise", "name": "scopeId", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "dailyBudgetUsd": { "type": "number", "minimum": 0 } }, "required": [ "dailyBudgetUsd" ] } } } }, "responses": { "200": { "description": "Budget upserted", "content": { "application/json": { "schema": { "type": "object", "properties": { "scope": { "type": "string", "enum": [ "global", "agent" ] }, "scopeId": { "type": "string" }, "dailyBudgetUsd": { "type": "number", "minimum": 0 }, "createdAt": { "type": "number" }, "lastUpdatedAt": { "type": "number" } }, "required": [ "scope", "scopeId", "dailyBudgetUsd", "createdAt", "lastUpdatedAt" ] } } } }, "400": { "description": "Validation error" } } }, "delete": { "summary": "Delete a budget row", "tags": [ "Budgets" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "global", "agent" ] }, "required": true, "name": "scope", "in": "path" }, { "schema": { "type": "string", "maxLength": 255, "description": "Scope identifier — empty string for global, agent UUID otherwise" }, "required": true, "description": "Scope identifier — empty string for global, agent UUID otherwise", "name": "scopeId", "in": "path" } ], "responses": { "204": { "description": "Budget deleted" }, "404": { "description": "Budget not configured" } } } }, "/api/config/resolved": { "get": { "summary": "Get resolved config (merged global + agent + repo scopes)", "tags": [ "Config" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "agentId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "repoId", "in": "query" }, { "schema": { "type": "string", "enum": [ "true", "false" ] }, "required": false, "name": "includeSecrets", "in": "query" } ], "responses": { "200": { "description": "Resolved config entries" } } } }, "/api/config/env-presence": { "get": { "summary": "Check which of the given env var keys are currently set in process.env (presence only, no values)", "tags": [ "Config" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "keys", "in": "query" } ], "responses": { "200": { "description": "Map of key -> boolean (true iff set in process.env)" }, "400": { "description": "Validation error" } } } }, "/api/config/reload": { "post": { "summary": "Reload global swarm_config into process.env (override=true) and re-init integrations (Slack, GitHub, Linear, AgentMail)", "tags": [ "Config" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": {} } } } }, "responses": { "200": { "description": "Reload result" }, "500": { "description": "Reload failed" } } } }, "/api/config/{id}": { "get": { "summary": "Get a single config entry by ID", "tags": [ "Config" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "string", "enum": [ "true", "false" ] }, "required": false, "name": "includeSecrets", "in": "query" } ], "responses": { "200": { "description": "Config entry" }, "404": { "description": "Config not found" } } }, "delete": { "summary": "Delete a config entry by ID (including legacy reserved rows for cleanup)", "tags": [ "Config" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Config deleted" }, "404": { "description": "Config not found" } } } }, "/api/config": { "get": { "summary": "List config entries with optional filters", "tags": [ "Config" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "scope", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "scopeId", "in": "query" }, { "schema": { "type": "string", "enum": [ "true", "false" ] }, "required": false, "name": "includeSecrets", "in": "query" } ], "responses": { "200": { "description": "List of config entries" } } }, "put": { "summary": "Create or update a config entry (reserved env-only keys are rejected)", "tags": [ "Config" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "scope": { "type": "string", "enum": [ "global", "agent", "repo" ] }, "scopeId": { "type": [ "string", "null" ] }, "key": { "type": "string", "minLength": 1 }, "value": {}, "isSecret": { "type": "boolean" }, "envPath": { "type": [ "string", "null" ] }, "description": { "type": [ "string", "null" ] } }, "required": [ "scope", "key" ] } } } }, "responses": { "200": { "description": "Config entry upserted" }, "400": { "description": "Validation error" } } } }, "/api/tasks/{id}/context": { "post": { "summary": "Record a context usage snapshot for a task", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "eventType": { "type": "string", "enum": [ "progress", "compaction", "completion" ] }, "sessionId": { "type": "string" }, "contextUsedTokens": { "type": "integer", "minimum": 0 }, "contextTotalTokens": { "type": "integer", "minimum": 0 }, "contextPercent": { "type": "number", "minimum": 0, "maximum": 100 }, "compactTrigger": { "type": "string", "enum": [ "auto", "manual" ] }, "preCompactTokens": { "type": "integer", "minimum": 0 }, "cumulativeInputTokens": { "type": "integer", "minimum": 0 }, "cumulativeOutputTokens": { "type": "integer", "minimum": 0 } }, "required": [ "eventType", "sessionId" ] } } } }, "responses": { "200": { "description": "Snapshot recorded" }, "400": { "description": "Validation error" }, "404": { "description": "Task not found" } } }, "get": { "summary": "Get context usage history for a task", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 500, "default": 100 }, "required": false, "name": "limit", "in": "query" } ], "responses": { "200": { "description": "Context snapshot history" }, "404": { "description": "Task not found" } } } }, "/api/db-query": { "post": { "summary": "Execute a read-only SQL query", "tags": [ "Debug" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "sql": { "type": "string", "minLength": 1, "maxLength": 10000 }, "params": { "type": "array", "items": {}, "default": [] } }, "required": [ "sql" ] } } } }, "responses": { "200": { "description": "Query results", "content": { "application/json": { "schema": { "type": "object", "properties": { "columns": { "type": "array", "items": { "type": "string" } }, "rows": { "type": "array", "items": { "type": "array", "items": {} } }, "elapsed": { "type": "number" }, "total": { "type": "number" } }, "required": [ "columns", "rows", "elapsed", "total" ] } } } }, "400": { "description": "Invalid or disallowed SQL" } } } }, "/ecosystem": { "get": { "summary": "Get PM2 ecosystem config for agent services", "tags": [ "Ecosystem" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "PM2 ecosystem config" }, "400": { "description": "Missing X-Agent-ID" } } } }, "/api/keys/report-usage": { "post": { "summary": "Record which API key was used for a task", "tags": [ "API Keys" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "keyType": { "type": "string" }, "keySuffix": { "type": "string", "minLength": 1, "maxLength": 10 }, "keyIndex": { "type": "integer", "minimum": 0 }, "taskId": { "type": "string", "format": "uuid" }, "scope": { "type": "string" }, "scopeId": { "type": "string" } }, "required": [ "keyType", "keySuffix", "keyIndex" ] } } } }, "responses": { "200": { "description": "Usage recorded" }, "400": { "description": "Validation error" }, "401": { "description": "Unauthorized" } } } }, "/api/keys/report-rate-limit": { "post": { "summary": "Mark an API key as rate-limited", "tags": [ "API Keys" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "keyType": { "type": "string" }, "keySuffix": { "type": "string", "minLength": 1, "maxLength": 10 }, "keyIndex": { "type": "integer", "minimum": 0 }, "rateLimitedUntil": { "type": "string", "format": "date-time" }, "scope": { "type": "string" }, "scopeId": { "type": "string" } }, "required": [ "keyType", "keySuffix", "keyIndex", "rateLimitedUntil" ] } } } }, "responses": { "200": { "description": "Key marked as rate-limited" }, "400": { "description": "Validation error" }, "401": { "description": "Unauthorized" } } } }, "/api/keys/available": { "get": { "summary": "Get available (non-rate-limited) key indices for a credential type", "tags": [ "API Keys" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "keyType", "in": "query" }, { "schema": { "type": "integer", "minimum": 1 }, "required": true, "name": "totalKeys", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "scope", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "scopeId", "in": "query" } ], "responses": { "200": { "description": "List of available key indices" }, "400": { "description": "Validation error" }, "401": { "description": "Unauthorized" } } } }, "/api/keys/status": { "get": { "summary": "Get all API key status records", "tags": [ "API Keys" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "keyType", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "scope", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "scopeId", "in": "query" } ], "responses": { "200": { "description": "List of key status records" }, "401": { "description": "Unauthorized" } } } }, "/api/keys/costs": { "get": { "summary": "Get aggregated cost data per API key", "tags": [ "API Keys" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "keyType", "in": "query" } ], "responses": { "200": { "description": "Per-key cost aggregation" }, "401": { "description": "Unauthorized" } } } }, "/api/keys/name": { "patch": { "summary": "Set or clear the human-friendly label on a pooled credential", "tags": [ "API Keys" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "keyType": { "type": "string", "minLength": 1 }, "keySuffix": { "type": "string", "minLength": 1, "maxLength": 10 }, "name": { "type": [ "string", "null" ], "maxLength": 60 }, "scope": { "type": "string" }, "scopeId": { "type": "string" } }, "required": [ "keyType", "keySuffix", "name" ] } } } }, "responses": { "200": { "description": "Name updated" }, "400": { "description": "Validation error" }, "401": { "description": "Unauthorized" }, "404": { "description": "Key not found" } } } }, "/api/events": { "post": { "summary": "Store a single event", "tags": [ "Events" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "category": { "type": "string", "enum": [ "tool", "skill", "session", "api", "task", "workflow", "system" ] }, "event": { "type": "string", "enum": [ "tool.start", "tool.end", "skill.invoke", "skill.complete", "session.start", "session.end", "session.resume", "session.cost", "api.request", "api.error", "task.poll", "task.assign", "task.timeout", "workflow.step.start", "workflow.step.end", "workflow.run.start", "workflow.run.end", "system.boot", "system.migration", "system.error" ] }, "status": { "type": "string", "enum": [ "ok", "error", "timeout", "skipped" ] }, "source": { "type": "string", "enum": [ "worker", "api", "hook", "scheduler", "cli" ] }, "agentId": { "type": "string" }, "taskId": { "type": "string" }, "sessionId": { "type": "string" }, "parentEventId": { "type": "string" }, "numericValue": { "type": "number" }, "durationMs": { "type": "integer" }, "data": { "type": "object", "additionalProperties": {} } }, "required": [ "category", "event", "source" ] } } } }, "responses": { "201": { "description": "Event stored" }, "400": { "description": "Validation error" } } }, "get": { "summary": "Query events with filters", "tags": [ "Events" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "tool", "skill", "session", "api", "task", "workflow", "system" ] }, "required": false, "name": "category", "in": "query" }, { "schema": { "type": "string", "enum": [ "tool.start", "tool.end", "skill.invoke", "skill.complete", "session.start", "session.end", "session.resume", "session.cost", "api.request", "api.error", "task.poll", "task.assign", "task.timeout", "workflow.step.start", "workflow.step.end", "workflow.run.start", "workflow.run.end", "system.boot", "system.migration", "system.error" ] }, "required": false, "name": "event", "in": "query" }, { "schema": { "type": "string", "enum": [ "ok", "error", "timeout", "skipped" ] }, "required": false, "name": "status", "in": "query" }, { "schema": { "type": "string", "enum": [ "worker", "api", "hook", "scheduler", "cli" ] }, "required": false, "name": "source", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "agentId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "taskId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "sessionId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "since", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "until", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 1000 }, "required": false, "name": "limit", "in": "query" } ], "responses": { "200": { "description": "List of events" } } } }, "/api/events/batch": { "post": { "summary": "Store multiple events in a batch", "tags": [ "Events" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "events": { "type": "array", "items": { "type": "object", "properties": { "category": { "type": "string", "enum": [ "tool", "skill", "session", "api", "task", "workflow", "system" ] }, "event": { "type": "string", "enum": [ "tool.start", "tool.end", "skill.invoke", "skill.complete", "session.start", "session.end", "session.resume", "session.cost", "api.request", "api.error", "task.poll", "task.assign", "task.timeout", "workflow.step.start", "workflow.step.end", "workflow.run.start", "workflow.run.end", "system.boot", "system.migration", "system.error" ] }, "status": { "type": "string", "enum": [ "ok", "error", "timeout", "skipped" ] }, "source": { "type": "string", "enum": [ "worker", "api", "hook", "scheduler", "cli" ] }, "agentId": { "type": "string" }, "taskId": { "type": "string" }, "sessionId": { "type": "string" }, "parentEventId": { "type": "string" }, "numericValue": { "type": "number" }, "durationMs": { "type": "integer" }, "data": { "type": "object", "additionalProperties": {} } }, "required": [ "category", "event", "source" ] }, "minItems": 1, "maxItems": 500 } }, "required": [ "events" ] } } } }, "responses": { "201": { "description": "Events stored" }, "400": { "description": "Validation error" } } } }, "/api/events/counts": { "get": { "summary": "Get event counts grouped by event name", "tags": [ "Events" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "tool", "skill", "session", "api", "task", "workflow", "system" ] }, "required": false, "name": "category", "in": "query" }, { "schema": { "type": "string", "enum": [ "worker", "api", "hook", "scheduler", "cli" ] }, "required": false, "name": "source", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "agentId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "taskId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "sessionId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "since", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "until", "in": "query" } ], "responses": { "200": { "description": "Event counts" } } } }, "/api/heartbeat/sweep": { "post": { "summary": "Trigger an immediate heartbeat sweep", "tags": [ "Heartbeat" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Sweep completed successfully" }, "401": { "description": "Unauthorized" } } } }, "/api/heartbeat/checklist": { "post": { "summary": "Trigger an immediate heartbeat checklist check", "tags": [ "Heartbeat" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Checklist check completed successfully" }, "401": { "description": "Unauthorized" } } } }, "/api/integrations/claude-managed/test": { "post": { "summary": "Test the claude-managed integration: resolves ANTHROPIC_API_KEY + MANAGED_AGENT_ID from swarm_config and calls beta.agents.retrieve.", "tags": [ "Integrations" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": {} } } } }, "responses": { "200": { "description": "Connection result — `{ ok: true, agentName, model }` on success or `{ ok: false, error }` on any failure (missing config, Anthropic API error). Always 200 OK." } } } }, "/api/memory/index": { "post": { "summary": "Ingest content into memory system (async embedding)", "tags": [ "Memory" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "agentId": { "type": "string", "format": "uuid" }, "content": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1 }, "scope": { "type": "string", "enum": [ "agent", "swarm" ] }, "source": { "type": "string", "enum": [ "manual", "file_index", "session_summary", "task_completion" ] }, "sourceTaskId": { "type": "string", "format": "uuid" }, "sourcePath": { "type": "string" }, "tags": { "type": "array", "items": { "type": "string" } } }, "required": [ "content", "name", "scope", "source" ] } } } }, "responses": { "202": { "description": "Content queued for embedding" }, "400": { "description": "Validation error" } } } }, "/api/memory/search": { "post": { "summary": "Search memories by natural language query", "tags": [ "Memory" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "query": { "type": "string", "minLength": 1 }, "limit": { "type": "integer", "minimum": 1, "maximum": 20, "default": 5 } }, "required": [ "query" ] } } } }, "responses": { "200": { "description": "Search results" }, "400": { "description": "Missing query or agent ID" } } } }, "/api/memory/re-embed": { "post": { "summary": "Re-embed all memories using the current embedding provider", "tags": [ "Memory" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "agentId": { "type": "string", "format": "uuid", "description": "Re-embed only this agent's memories. Omit for all." }, "batchSize": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20, "description": "Memories per batch" } } } } } }, "responses": { "202": { "description": "Re-embedding started" } } } }, "/api/memory/list": { "post": { "summary": "List or semantically search memories across all agents (debug/admin)", "tags": [ "Memory" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "query": { "type": "string", "description": "Natural-language query. If present, runs semantic search; otherwise lists by recency." }, "agentId": { "type": "string", "format": "uuid", "description": "Filter to a single agent. Omit for all." }, "scope": { "type": "string", "enum": [ "agent", "swarm", "all" ], "default": "all" }, "source": { "type": "string", "enum": [ "manual", "file_index", "session_summary", "task_completion" ] }, "sourcePath": { "type": "string", "description": "Substring match against sourcePath (case-insensitive). Useful for file_index memories." }, "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 }, "offset": { "type": "integer", "minimum": 0, "default": 0 } } } } } }, "responses": { "200": { "description": "Memory list / search results" }, "400": { "description": "Validation error" } } } }, "/api/memory/{id}": { "delete": { "summary": "Delete a single memory by ID (debug/admin)", "tags": [ "Memory" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "format": "uuid" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Memory deleted" }, "404": { "description": "Memory not found" } } } }, "/api/memory/rate": { "post": { "summary": "Submit RatingEvents to update memory usefulness posteriors", "tags": [ "Memory" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "events": { "type": "array", "items": { "type": "object", "properties": { "memoryId": { "type": "string", "minLength": 1 }, "signal": { "type": "number", "minimum": -1, "maximum": 1 }, "weight": { "type": "number", "minimum": 0, "maximum": 1 }, "source": { "type": "string", "enum": [ "llm", "explicit-self" ] }, "reasoning": { "type": "string", "maxLength": 500 }, "taskId": { "type": "string", "format": "uuid" }, "referencesSource": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Optional external source ID this memory references. Free-form string, convention \":\" (e.g. \"github:owner/repo#N\", \"linear:KEY-N\", \"customer:\", \"slack::\", \"agentmail:\"). Pick any prefix that fits — no closed enum. When present, an edge from this memory to the external source is created/updated." } }, "required": [ "memoryId", "signal", "weight", "source" ] }, "minItems": 1, "maxItems": 50 } }, "required": [ "events" ] } } } }, "responses": { "200": { "description": "Ratings applied; per-event rejections returned in body" }, "400": { "description": "Validation error or explicit-self R6 spam-guard rejection" }, "409": { "description": "Duplicate explicit-self rating for (taskId, memoryId)" } } } }, "/api/memory/retrievals": { "get": { "summary": "List memories retrieved for a task or session (rater input)", "tags": [ "Memory" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "format": "uuid" }, "required": false, "name": "taskId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "sessionId", "in": "query" } ], "responses": { "200": { "description": "Retrieval rows joined with agent_memory" }, "400": { "description": "Missing taskId/sessionId or X-Agent-ID" } } } }, "/api/memory/edges": { "get": { "summary": "List references-source edges for a memory", "tags": [ "Memory" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "memoryId", "in": "query" } ], "responses": { "200": { "description": "Edges with computed usefulness scores" }, "400": { "description": "Missing memoryId or X-Agent-ID" } } } }, "/api/prompt-templates/resolved": { "get": { "summary": "Resolve a prompt template for a given event type and scope chain", "tags": [ "PromptTemplates" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "eventType", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "agentId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "repoId", "in": "query" } ], "responses": { "200": { "description": "Resolved template info" }, "400": { "description": "Missing eventType" } } } }, "/api/prompt-templates/events": { "get": { "summary": "List all registered event types with their available variables", "tags": [ "PromptTemplates" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "List of event template definitions" } } } }, "/api/prompt-templates/preview": { "post": { "summary": "Dry-run render a template with provided variables", "tags": [ "PromptTemplates" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "eventType": { "type": "string" }, "body": { "type": "string" }, "variables": { "type": "object", "additionalProperties": {} } }, "required": [ "eventType" ] } } } }, "responses": { "200": { "description": "Rendered template preview" }, "400": { "description": "Validation error" } } } }, "/api/prompt-templates/render": { "post": { "summary": "Full scope-aware template resolution with interpolation (used by workers via HTTP)", "tags": [ "PromptTemplates" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "eventType": { "type": "string" }, "variables": { "type": "object", "additionalProperties": {} }, "agentId": { "type": "string" }, "repoId": { "type": "string" } }, "required": [ "eventType" ] } } } }, "responses": { "200": { "description": "Fully resolved and interpolated template" }, "400": { "description": "Validation error" } } } }, "/api/prompt-templates/{id}/checkout": { "post": { "summary": "Checkout a specific version of a prompt template from history", "tags": [ "PromptTemplates" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "version": { "type": "number" } }, "required": [ "version" ] } } } }, "responses": { "200": { "description": "Checked-out template" }, "400": { "description": "Validation error" }, "404": { "description": "Template or version not found" } } } }, "/api/prompt-templates/{id}/reset": { "post": { "summary": "Reset a prompt template to its code-defined default", "tags": [ "PromptTemplates" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Reset template" }, "404": { "description": "Template not found or no code default available" } } } }, "/api/prompt-templates/{id}": { "get": { "summary": "Get a single prompt template with its version history", "tags": [ "PromptTemplates" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Template with history" }, "404": { "description": "Template not found" } } }, "delete": { "summary": "Delete a prompt template override", "tags": [ "PromptTemplates" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Template deleted" }, "400": { "description": "Cannot delete default template" }, "404": { "description": "Template not found" } } } }, "/api/prompt-templates": { "get": { "summary": "List prompt templates with optional filters", "tags": [ "PromptTemplates" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "eventType", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "scope", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "scopeId", "in": "query" }, { "schema": { "type": "string", "enum": [ "true", "false" ] }, "required": false, "name": "isDefault", "in": "query" } ], "responses": { "200": { "description": "List of prompt templates" } } }, "put": { "summary": "Create or update a prompt template override", "tags": [ "PromptTemplates" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "eventType": { "type": "string", "minLength": 1 }, "scope": { "type": "string", "enum": [ "global", "agent", "repo" ] }, "scopeId": { "type": "string" }, "state": { "type": "string", "enum": [ "enabled", "default_prompt_fallback", "skip_event" ] }, "body": { "type": "string" }, "changedBy": { "type": "string" }, "changeReason": { "type": "string" } }, "required": [ "eventType", "body" ] } } } }, "responses": { "200": { "description": "Upserted template" }, "400": { "description": "Validation error" } } } }, "/api/poll": { "get": { "summary": "Poll for triggers (tasks, mentions)", "tags": [ "Poll" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Trigger data or null" }, "400": { "description": "Missing X-Agent-ID" }, "404": { "description": "Agent not found" } } } }, "/api/channel-activity/commit-cursors": { "post": { "summary": "Commit channel activity cursors after successful processing", "tags": [ "Poll" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "cursorUpdates": { "type": "array", "items": { "type": "object", "properties": { "channelId": { "type": "string" }, "ts": { "type": "string" } }, "required": [ "channelId", "ts" ] } } }, "required": [ "cursorUpdates" ] } } } }, "responses": { "200": { "description": "Cursors committed" }, "400": { "description": "Invalid request" } } } }, "/api/pricing": { "get": { "summary": "List every pricing row across all providers", "tags": [ "Pricing" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Pricing rows", "content": { "application/json": { "schema": { "type": "object", "properties": { "rows": { "type": "array", "items": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ "claude", "codex", "pi" ] }, "model": { "type": "string" }, "tokenClass": { "type": "string", "enum": [ "input", "cached_input", "output" ] }, "effectiveFrom": { "type": "number", "minimum": 0 }, "pricePerMillionUsd": { "type": "number", "minimum": 0 }, "createdAt": { "type": "number" }, "lastUpdatedAt": { "type": "number" } }, "required": [ "provider", "model", "tokenClass", "effectiveFrom", "pricePerMillionUsd", "createdAt", "lastUpdatedAt" ] } } }, "required": [ "rows" ] } } } } } } }, "/api/pricing/{provider}/{model}/{tokenClass}": { "get": { "summary": "List pricing history for a (provider, model, tokenClass) triple", "tags": [ "Pricing" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "claude", "codex", "pi" ] }, "required": true, "name": "provider", "in": "path" }, { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "model", "in": "path" }, { "schema": { "type": "string", "enum": [ "input", "cached_input", "output" ] }, "required": true, "name": "tokenClass", "in": "path" } ], "responses": { "200": { "description": "Pricing rows (latest first)" } } }, "post": { "summary": "Append a new pricing row", "tags": [ "Pricing" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "claude", "codex", "pi" ] }, "required": true, "name": "provider", "in": "path" }, { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "model", "in": "path" }, { "schema": { "type": "string", "enum": [ "input", "cached_input", "output" ] }, "required": true, "name": "tokenClass", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "pricePerMillionUsd": { "type": "number", "minimum": 0 }, "effectiveFrom": { "type": "number", "minimum": 0 } }, "required": [ "pricePerMillionUsd" ] } } } }, "responses": { "201": { "description": "Pricing row inserted", "content": { "application/json": { "schema": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ "claude", "codex", "pi" ] }, "model": { "type": "string" }, "tokenClass": { "type": "string", "enum": [ "input", "cached_input", "output" ] }, "effectiveFrom": { "type": "number", "minimum": 0 }, "pricePerMillionUsd": { "type": "number", "minimum": 0 }, "createdAt": { "type": "number" }, "lastUpdatedAt": { "type": "number" } }, "required": [ "provider", "model", "tokenClass", "effectiveFrom", "pricePerMillionUsd", "createdAt", "lastUpdatedAt" ] } } } }, "400": { "description": "Validation error" }, "409": { "description": "Duplicate (provider, model, tokenClass, effectiveFrom)" } } } }, "/api/pricing/{provider}/{model}/{tokenClass}/active": { "get": { "summary": "Get the currently active pricing row", "tags": [ "Pricing" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "claude", "codex", "pi" ] }, "required": true, "name": "provider", "in": "path" }, { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "model", "in": "path" }, { "schema": { "type": "string", "enum": [ "input", "cached_input", "output" ] }, "required": true, "name": "tokenClass", "in": "path" } ], "responses": { "200": { "description": "Active pricing row", "content": { "application/json": { "schema": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ "claude", "codex", "pi" ] }, "model": { "type": "string" }, "tokenClass": { "type": "string", "enum": [ "input", "cached_input", "output" ] }, "effectiveFrom": { "type": "number", "minimum": 0 }, "pricePerMillionUsd": { "type": "number", "minimum": 0 }, "createdAt": { "type": "number" }, "lastUpdatedAt": { "type": "number" } }, "required": [ "provider", "model", "tokenClass", "effectiveFrom", "pricePerMillionUsd", "createdAt", "lastUpdatedAt" ] } } } }, "404": { "description": "No pricing row in effect" } } } }, "/api/pricing/{provider}/{model}/{tokenClass}/{effectiveFrom}": { "delete": { "summary": "Delete a pricing row (typo correction)", "tags": [ "Pricing" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "claude", "codex", "pi" ] }, "required": true, "name": "provider", "in": "path" }, { "schema": { "type": "string", "minLength": 1 }, "required": true, "name": "model", "in": "path" }, { "schema": { "type": "string", "enum": [ "input", "cached_input", "output" ] }, "required": true, "name": "tokenClass", "in": "path" }, { "schema": { "type": "string", "pattern": "^\\d+$" }, "required": true, "name": "effectiveFrom", "in": "path" } ], "responses": { "204": { "description": "Pricing row deleted" }, "404": { "description": "Pricing row not found" } } } }, "/api/repos/{id}": { "get": { "summary": "Get a repo by ID", "tags": [ "Repos" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "format": "uuid" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Repo details", "content": { "application/json": { "schema": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "url": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1, "maxLength": 100 }, "clonePath": { "type": "string", "minLength": 1 }, "defaultBranch": { "type": "string", "default": "main" }, "autoClone": { "type": "boolean", "default": true }, "guidelines": { "type": [ "object", "null" ], "properties": { "prChecks": { "type": "array", "items": { "type": "string" } }, "mergeChecks": { "type": "array", "items": { "type": "string" } }, "allowMerge": { "type": "boolean", "default": false }, "review": { "type": "array", "items": { "type": "string" } } }, "required": [ "prChecks", "mergeChecks", "review" ] }, "createdAt": { "type": "string" }, "lastUpdatedAt": { "type": "string" } }, "required": [ "id", "url", "name", "clonePath", "createdAt", "lastUpdatedAt" ] } } } }, "404": { "description": "Repo not found", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] } } } } } }, "put": { "summary": "Update a repo", "tags": [ "Repos" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "format": "uuid" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "url": { "type": "string" }, "name": { "type": "string" }, "clonePath": { "type": "string" }, "defaultBranch": { "type": "string" }, "autoClone": { "type": "boolean" }, "guidelines": { "type": [ "object", "null" ], "properties": { "prChecks": { "type": "array", "items": { "type": "string" } }, "mergeChecks": { "type": "array", "items": { "type": "string" } }, "allowMerge": { "type": "boolean", "default": false }, "review": { "type": "array", "items": { "type": "string" } } }, "required": [ "prChecks", "mergeChecks", "review" ] } } } } } }, "responses": { "200": { "description": "Repo updated", "content": { "application/json": { "schema": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "url": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1, "maxLength": 100 }, "clonePath": { "type": "string", "minLength": 1 }, "defaultBranch": { "type": "string", "default": "main" }, "autoClone": { "type": "boolean", "default": true }, "guidelines": { "type": [ "object", "null" ], "properties": { "prChecks": { "type": "array", "items": { "type": "string" } }, "mergeChecks": { "type": "array", "items": { "type": "string" } }, "allowMerge": { "type": "boolean", "default": false }, "review": { "type": "array", "items": { "type": "string" } } }, "required": [ "prChecks", "mergeChecks", "review" ] }, "createdAt": { "type": "string" }, "lastUpdatedAt": { "type": "string" } }, "required": [ "id", "url", "name", "clonePath", "createdAt", "lastUpdatedAt" ] } } } }, "404": { "description": "Repo not found", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] } } } }, "409": { "description": "Duplicate repo", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] } } } } } }, "delete": { "summary": "Delete a repo", "tags": [ "Repos" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "format": "uuid" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Repo deleted", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" } }, "required": [ "success" ] } } } }, "404": { "description": "Repo not found", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] } } } } } } }, "/api/repos": { "get": { "summary": "List repos with optional filters", "tags": [ "Repos" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "true", "false" ] }, "required": false, "name": "autoClone", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "name", "in": "query" } ], "responses": { "200": { "description": "List of repos", "content": { "application/json": { "schema": { "type": "object", "properties": { "repos": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "url": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1, "maxLength": 100 }, "clonePath": { "type": "string", "minLength": 1 }, "defaultBranch": { "type": "string", "default": "main" }, "autoClone": { "type": "boolean", "default": true }, "guidelines": { "type": [ "object", "null" ], "properties": { "prChecks": { "type": "array", "items": { "type": "string" } }, "mergeChecks": { "type": "array", "items": { "type": "string" } }, "allowMerge": { "type": "boolean", "default": false }, "review": { "type": "array", "items": { "type": "string" } } }, "required": [ "prChecks", "mergeChecks", "review" ] }, "createdAt": { "type": "string" }, "lastUpdatedAt": { "type": "string" } }, "required": [ "id", "url", "name", "clonePath", "createdAt", "lastUpdatedAt" ] } } }, "required": [ "repos" ] } } } } } }, "post": { "summary": "Create a new repo", "tags": [ "Repos" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "url": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1 }, "clonePath": { "type": "string" }, "defaultBranch": { "type": "string" }, "autoClone": { "type": "boolean" }, "guidelines": { "type": [ "object", "null" ], "properties": { "prChecks": { "type": "array", "items": { "type": "string" } }, "mergeChecks": { "type": "array", "items": { "type": "string" } }, "allowMerge": { "type": "boolean", "default": false }, "review": { "type": "array", "items": { "type": "string" } } }, "required": [ "prChecks", "mergeChecks", "review" ] } }, "required": [ "url", "name" ] } } } }, "responses": { "201": { "description": "Repo created", "content": { "application/json": { "schema": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "url": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1, "maxLength": 100 }, "clonePath": { "type": "string", "minLength": 1 }, "defaultBranch": { "type": "string", "default": "main" }, "autoClone": { "type": "boolean", "default": true }, "guidelines": { "type": [ "object", "null" ], "properties": { "prChecks": { "type": "array", "items": { "type": "string" } }, "mergeChecks": { "type": "array", "items": { "type": "string" } }, "allowMerge": { "type": "boolean", "default": false }, "review": { "type": "array", "items": { "type": "string" } } }, "required": [ "prChecks", "mergeChecks", "review" ] }, "createdAt": { "type": "string" }, "lastUpdatedAt": { "type": "string" } }, "required": [ "id", "url", "name", "clonePath", "createdAt", "lastUpdatedAt" ] } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] } } } }, "409": { "description": "Duplicate repo", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string" } }, "required": [ "error" ] } } } } } } }, "/api/schedules": { "post": { "summary": "Create a new schedule", "tags": [ "Schedules" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "description": { "type": "string" }, "cronExpression": { "type": "string" }, "intervalMs": { "type": "integer" }, "taskTemplate": { "type": "string", "minLength": 1 }, "taskType": { "type": "string" }, "tags": { "type": "array", "items": { "type": "string" } }, "priority": { "type": "integer" }, "targetAgentId": { "type": "string", "format": "uuid" }, "enabled": { "type": "boolean" }, "timezone": { "type": "string" }, "model": { "type": "string" }, "scheduleType": { "type": "string", "enum": [ "recurring", "one_time" ] }, "delayMs": { "type": "integer" }, "runAt": { "type": "string" } }, "required": [ "name", "taskTemplate" ] } } } }, "responses": { "201": { "description": "Schedule created" }, "400": { "description": "Validation error" }, "409": { "description": "Duplicate name" } } } }, "/api/schedules/{id}/run": { "post": { "summary": "Run a schedule immediately", "tags": [ "Schedules" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Schedule run triggered" }, "400": { "description": "Schedule is disabled" }, "404": { "description": "Schedule not found" } } } }, "/api/schedules/{id}": { "get": { "summary": "Get a schedule by ID", "tags": [ "Schedules" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Schedule details" }, "404": { "description": "Schedule not found" } } }, "put": { "summary": "Update a schedule", "tags": [ "Schedules" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" }, "cronExpression": { "type": "string" }, "intervalMs": { "type": "integer" }, "taskTemplate": { "type": "string" }, "taskType": { "type": "string" }, "tags": { "type": "array", "items": { "type": "string" } }, "priority": { "type": "integer" }, "targetAgentId": { "type": "string", "format": "uuid" }, "enabled": { "type": "boolean" }, "timezone": { "type": "string" }, "model": { "type": "string" }, "nextRunAt": { "type": [ "string", "null" ] } } } } } }, "responses": { "200": { "description": "Schedule updated" }, "400": { "description": "Validation error" }, "404": { "description": "Schedule not found" }, "409": { "description": "Duplicate name" } } }, "delete": { "summary": "Delete a schedule", "tags": [ "Schedules" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Schedule deleted" }, "404": { "description": "Schedule not found" } } } }, "/api/session-logs": { "post": { "summary": "Store session logs", "tags": [ "Session Data" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "sessionId": { "type": "string", "minLength": 1 }, "iteration": { "type": "integer", "minimum": 1 }, "lines": { "type": "array", "items": { "type": "string" }, "minItems": 1 }, "taskId": { "type": "string" }, "cli": { "type": "string" } }, "required": [ "sessionId", "iteration", "lines" ] } } } }, "responses": { "201": { "description": "Logs stored" }, "400": { "description": "Validation error" } } } }, "/api/tasks/{taskId}/session-logs": { "get": { "summary": "Get session logs for a task", "tags": [ "Session Data" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "taskId", "in": "path" } ], "responses": { "200": { "description": "Session logs" }, "404": { "description": "Task not found" } } } }, "/api/session-costs": { "post": { "summary": "Store session cost record", "tags": [ "Session Data" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "sessionId": { "type": "string", "minLength": 1 }, "agentId": { "type": "string", "minLength": 1 }, "totalCostUsd": { "type": "number" }, "taskId": { "type": "string" }, "inputTokens": { "type": "integer" }, "outputTokens": { "type": "integer" }, "cacheReadTokens": { "type": "integer" }, "cacheWriteTokens": { "type": "integer" }, "durationMs": { "type": "integer" }, "numTurns": { "type": "integer" }, "model": { "type": "string" }, "isError": { "type": "boolean" }, "provider": { "type": "string", "enum": [ "claude", "codex", "pi", "opencode" ] }, "createdAt": { "type": "integer", "minimum": 0 } }, "required": [ "sessionId", "agentId", "totalCostUsd" ] } } } }, "responses": { "201": { "description": "Cost record stored" }, "400": { "description": "Validation error" } } }, "get": { "summary": "Query session costs with filters", "tags": [ "Session Data" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "agentId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "taskId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "startDate", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "endDate", "in": "query" }, { "schema": { "type": "integer", "minimum": 1 }, "required": false, "name": "limit", "in": "query" } ], "responses": { "200": { "description": "Session costs" } } } }, "/api/session-costs/summary": { "get": { "summary": "Aggregated session cost summary", "tags": [ "Session Data" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "day", "agent", "both" ] }, "required": false, "name": "groupBy", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "startDate", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "endDate", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "agentId", "in": "query" } ], "responses": { "200": { "description": "Cost summary" }, "400": { "description": "Invalid groupBy" } } } }, "/api/session-costs/dashboard": { "get": { "summary": "Cost today and month-to-date for dashboard", "tags": [ "Session Data" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Dashboard cost data" } } } }, "/api/skills": { "get": { "summary": "List skills with optional filters", "tags": [ "Skills" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "type", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "scope", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "agentId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "enabled", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "search", "in": "query" } ], "responses": { "200": { "description": "Skill list" } } }, "post": { "summary": "Create a new skill", "tags": [ "Skills" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "content": { "type": "string", "minLength": 1 }, "type": { "type": "string" }, "scope": { "type": "string" }, "ownerAgentId": { "type": "string" } }, "required": [ "content" ] } } } }, "responses": { "201": { "description": "Skill created" }, "400": { "description": "Validation error" } } } }, "/api/skills/{id}": { "get": { "summary": "Get skill by ID", "tags": [ "Skills" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Skill details" }, "404": { "description": "Skill not found" } } }, "put": { "summary": "Update a skill", "tags": [ "Skills" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "additionalProperties": {} } } } }, "responses": { "200": { "description": "Skill updated" }, "404": { "description": "Skill not found" } } }, "delete": { "summary": "Delete a skill", "tags": [ "Skills" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Skill deleted" }, "404": { "description": "Skill not found" } } } }, "/api/skills/{id}/install": { "post": { "summary": "Install skill for an agent", "tags": [ "Skills" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "agentId": { "type": "string" } }, "required": [ "agentId" ] } } } }, "responses": { "200": { "description": "Skill installed" }, "404": { "description": "Skill not found" } } } }, "/api/skills/{id}/install/{agentId}": { "delete": { "summary": "Uninstall skill for an agent", "tags": [ "Skills" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "string" }, "required": true, "name": "agentId", "in": "path" } ], "responses": { "200": { "description": "Skill uninstalled" } } } }, "/api/skills/install-remote": { "post": { "summary": "Install a remote skill from GitHub", "tags": [ "Skills" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "sourceRepo": { "type": "string" }, "sourcePath": { "type": "string" }, "scope": { "type": "string" }, "isComplex": { "type": "boolean" } }, "required": [ "sourceRepo" ] } } } }, "responses": { "201": { "description": "Remote skill installed" }, "400": { "description": "Fetch failed" } } } }, "/api/skills/sync-remote": { "post": { "summary": "Trigger remote skill sync", "tags": [ "Skills" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "skillId": { "type": "string" }, "force": { "type": "boolean" } } } } } }, "responses": { "200": { "description": "Sync results" } } } }, "/api/skills/sync-filesystem": { "post": { "summary": "Sync installed skills to agent filesystem", "tags": [ "Skills" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Filesystem sync results" } } } }, "/api/agents/{id}/skills": { "get": { "summary": "Get all skills installed for an agent", "tags": [ "Skills" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Agent skills list" } } } }, "/api/mcp-oauth/{mcpServerId}/metadata": { "get": { "summary": "Probe OAuth metadata (PRMD + AS) for an MCP server", "tags": [ "MCP OAuth" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "mcpServerId", "in": "path" } ], "responses": { "200": { "description": "OAuth metadata or { requiresOAuth: false }" }, "400": { "description": "MCP has no URL / invalid transport" }, "404": { "description": "MCP server not found" } } } }, "/api/mcp-oauth/{mcpServerId}/status": { "get": { "summary": "Get the current OAuth connection status for an MCP server", "tags": [ "MCP OAuth" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "mcpServerId", "in": "path" }, { "schema": { "type": "string" }, "required": false, "name": "userId", "in": "query" } ], "responses": { "200": { "description": "Token status (never includes the token value itself)" }, "404": { "description": "MCP server not found" } } } }, "/api/mcp-oauth/{mcpServerId}/authorize": { "get": { "summary": "Start an OAuth flow. Redirects to the provider.", "tags": [ "MCP OAuth" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "mcpServerId", "in": "path" }, { "schema": { "type": "string" }, "required": false, "name": "redirect", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "userId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "scopes", "in": "query" } ], "responses": { "302": { "description": "Redirect to authorization server" }, "400": { "description": "MCP has no URL / does not require OAuth" }, "404": { "description": "MCP server not found" } } } }, "/api/mcp-oauth/{mcpServerId}/authorize-url": { "get": { "summary": "Build an OAuth authorize URL. Returns JSON so the browser can navigate without losing the Bearer auth header.", "tags": [ "MCP OAuth" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "mcpServerId", "in": "path" }, { "schema": { "type": "string" }, "required": false, "name": "redirect", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "userId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "scopes", "in": "query" } ], "responses": { "200": { "description": "{ providerUrl: string }" }, "400": { "description": "MCP has no URL / does not require OAuth" }, "404": { "description": "MCP server not found" } } } }, "/api/mcp-oauth/callback": { "get": { "summary": "OAuth redirect target. Exchanges code -> tokens and redirects back to dashboard.", "tags": [ "MCP OAuth" ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "code", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "state", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "error", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "error_description", "in": "query" } ], "responses": { "302": { "description": "Redirect back to dashboard with oauth=success or oauth=error" }, "400": { "description": "Bad state / missing code" } } } }, "/api/mcp-oauth/{mcpServerId}/refresh": { "post": { "summary": "Force-refresh the access token for an MCP server", "tags": [ "MCP OAuth" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "mcpServerId", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "userId": { "type": "string" } } } } } }, "responses": { "200": { "description": "Refreshed token" }, "404": { "description": "No token for this MCP server" }, "500": { "description": "Refresh failed" } } } }, "/api/mcp-oauth/{mcpServerId}": { "delete": { "summary": "Revoke and delete the OAuth token for an MCP server", "tags": [ "MCP OAuth" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "mcpServerId", "in": "path" }, { "schema": { "type": "string" }, "required": false, "name": "userId", "in": "query" } ], "responses": { "200": { "description": "Token revoked/deleted" }, "404": { "description": "No token for this MCP server" } } } }, "/api/mcp-oauth/{mcpServerId}/manual-client": { "post": { "summary": "Register a pre-existing OAuth client (DCR fallback)", "tags": [ "MCP OAuth" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "mcpServerId", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "clientId": { "type": "string", "minLength": 1 }, "clientSecret": { "type": "string" }, "authorizationServerIssuer": { "type": "string", "format": "uri" }, "authorizeUrl": { "type": "string", "format": "uri" }, "tokenUrl": { "type": "string", "format": "uri" }, "revocationUrl": { "type": "string", "format": "uri" }, "scopes": { "type": "array", "items": { "type": "string" } } }, "required": [ "clientId" ] } } } }, "responses": { "200": { "description": "Pending client stored. Call /authorize to start the flow." }, "400": { "description": "Bad input" }, "404": { "description": "MCP server not found" } } } }, "/api/mcp-servers": { "get": { "summary": "List MCP servers with optional filters", "tags": [ "MCP Servers" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "scope", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "transport", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "ownerAgentId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "enabled", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "search", "in": "query" } ], "responses": { "200": { "description": "MCP server list" } } }, "post": { "summary": "Create a new MCP server", "tags": [ "MCP Servers" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "transport": { "type": "string", "enum": [ "stdio", "http", "sse" ] }, "description": { "type": "string" }, "scope": { "type": "string" }, "ownerAgentId": { "type": "string" }, "command": { "type": "string" }, "args": { "type": "string" }, "url": { "type": "string" }, "headers": { "type": "string" }, "envConfigKeys": { "type": "string" }, "headerConfigKeys": { "type": "string" } }, "required": [ "name", "transport" ] } } } }, "responses": { "201": { "description": "MCP server created" }, "400": { "description": "Validation error" } } } }, "/api/mcp-servers/{id}": { "get": { "summary": "Get MCP server by ID", "tags": [ "MCP Servers" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "MCP server details" }, "404": { "description": "MCP server not found" } } }, "put": { "summary": "Update an MCP server", "tags": [ "MCP Servers" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "additionalProperties": {} } } } }, "responses": { "200": { "description": "MCP server updated" }, "404": { "description": "MCP server not found" } } }, "delete": { "summary": "Delete an MCP server", "tags": [ "MCP Servers" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "MCP server deleted" }, "404": { "description": "MCP server not found" } } } }, "/api/mcp-servers/{id}/install": { "post": { "summary": "Install MCP server for an agent", "tags": [ "MCP Servers" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "agentId": { "type": "string" } }, "required": [ "agentId" ] } } } }, "responses": { "200": { "description": "MCP server installed" }, "404": { "description": "MCP server not found" } } } }, "/api/mcp-servers/{id}/install/{agentId}": { "delete": { "summary": "Uninstall MCP server for an agent", "tags": [ "MCP Servers" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "string" }, "required": true, "name": "agentId", "in": "path" } ], "responses": { "200": { "description": "MCP server uninstalled" } } } }, "/api/agents/{id}/mcp-servers": { "get": { "summary": "Get all MCP servers installed for an agent", "tags": [ "MCP Servers" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "string" }, "required": false, "name": "resolveSecrets", "in": "query" } ], "responses": { "200": { "description": "Agent MCP servers list" } } } }, "/api/logs": { "get": { "summary": "List agent logs", "tags": [ "Stats" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "integer", "minimum": 1 }, "required": false, "name": "limit", "in": "query" }, { "schema": { "type": "string", "format": "uuid" }, "required": false, "name": "agentId", "in": "query" } ], "responses": { "200": { "description": "Agent logs" } } } }, "/api/stats": { "get": { "summary": "Dashboard summary stats", "tags": [ "Stats" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Agent and task statistics" } } } }, "/api/services": { "get": { "summary": "List all registered services", "tags": [ "Stats" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "status", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "agentId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "name", "in": "query" } ], "responses": { "200": { "description": "Service list" } } } }, "/api/scheduled-tasks": { "get": { "summary": "List scheduled tasks", "tags": [ "Stats" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "enum": [ "true", "false" ] }, "required": false, "name": "enabled", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "name", "in": "query" }, { "schema": { "type": "string", "enum": [ "recurring", "one_time" ] }, "required": false, "name": "scheduleType", "in": "query" }, { "schema": { "type": "string", "enum": [ "true", "false" ] }, "required": false, "name": "hideCompleted", "in": "query" } ], "responses": { "200": { "description": "Scheduled tasks list" } } } }, "/api/concurrent-context": { "get": { "summary": "Get concurrent session context for lead awareness", "tags": [ "Stats" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Concurrent context data" } } } }, "/status": { "get": { "summary": "Identity + setup readiness + live activity for the swarm dashboard", "description": "Single source of truth consumed by the UI home page. Identity comes from SWARM_* envs; the 7 setup milestones each emit `unverified | configured | verified`; activity counts agents alive in the last 5 min and tasks created in the last 24h; agent_fs reports whether AGENT_FS_API_URL is set.", "tags": [ "Status" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Status payload", "content": { "application/json": { "schema": { "type": "object", "properties": { "identity": { "type": "object", "properties": { "name": { "type": "string" }, "logo_url": { "type": [ "string", "null" ] }, "brand_color": { "type": [ "string", "null" ] }, "is_cloud": { "type": "boolean" }, "marketing_url": { "type": [ "string", "null" ] }, "hide_cloud_promo": { "type": "boolean" } }, "required": [ "name", "logo_url", "brand_color", "is_cloud", "marketing_url", "hide_cloud_promo" ] }, "setup": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "enum": [ "harness", "slack", "github", "linear", "jira", "workers", "first_task" ] }, "label": { "type": "string" }, "state": { "type": "string", "enum": [ "unverified", "configured", "verified" ] }, "hint": { "type": "string" }, "action_url": { "type": "string" }, "provider": { "type": "string", "enum": [ "claude", "codex", "pi", "devin", "claude-managed", "opencode" ] } }, "required": [ "id", "label", "state" ] } }, "activity": { "type": "object", "properties": { "agents_online": { "type": "integer", "minimum": 0 }, "leads_online": { "type": "integer", "minimum": 0 }, "recent_tasks_count": { "type": "integer", "minimum": 0 } }, "required": [ "agents_online", "leads_online", "recent_tasks_count" ] }, "agent_fs": { "type": "object", "properties": { "configured": { "type": "boolean" }, "base_url": { "type": [ "string", "null" ] } }, "required": [ "configured", "base_url" ] }, "health": { "type": "string", "enum": [ "ok", "degraded", "broken" ] } }, "required": [ "identity", "setup", "activity", "agent_fs", "health" ] } } } }, "401": { "description": "Unauthorized" } } } }, "/status/test-connection": { "post": { "summary": "Live-test the harness provider's credentials", "description": "Issues a real upstream call (Anthropic /v1/models, OpenAI /v1/models, etc.) for the given provider. Updates an in-memory cache so the next GET /status reports `harness.state = 'verified'` for SWARM_VERIFY_TTL_MS (default 1h).", "tags": [ "Status" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ "claude", "codex", "pi", "devin", "claude-managed", "opencode" ] } }, "required": [ "provider" ] } } } }, "responses": { "200": { "description": "Live-test result", "content": { "application/json": { "schema": { "type": "object", "properties": { "ok": { "type": "boolean" }, "error": { "type": "string" }, "latency_ms": { "type": "integer", "minimum": 0 } }, "required": [ "ok", "latency_ms" ] } } } }, "400": { "description": "Validation error" }, "401": { "description": "Unauthorized" } } } }, "/api/tasks": { "get": { "summary": "List tasks with filters", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": false, "name": "status", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "agentId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "scheduleId", "in": "query" }, { "schema": { "type": "string" }, "required": false, "name": "search", "in": "query" }, { "schema": { "type": "string", "enum": [ "true", "false" ] }, "required": false, "name": "includeHeartbeat", "in": "query" }, { "schema": { "type": [ "integer", "null" ] }, "required": false, "name": "limit", "in": "query" }, { "schema": { "type": [ "integer", "null" ] }, "required": false, "name": "offset", "in": "query" } ], "responses": { "200": { "description": "Paginated task list" } } }, "post": { "summary": "Create a new task", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "task": { "type": "string", "minLength": 1 }, "agentId": { "type": "string" }, "taskType": { "type": "string" }, "tags": { "type": "array", "items": { "type": "string" } }, "priority": { "type": "integer" }, "dependsOn": { "type": "array", "items": { "type": "string" } }, "offeredTo": { "type": "string" }, "dir": { "type": "string" }, "parentTaskId": { "type": "string" }, "source": { "type": "string" }, "outputSchema": { "type": "object", "additionalProperties": {} }, "contextKey": { "type": "string" } }, "required": [ "task" ] } } } }, "responses": { "201": { "description": "Task created" }, "400": { "description": "Validation error" } } } }, "/api/tasks/{id}/claude-session": { "put": { "summary": "Update Claude session ID for a task", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "anyOf": [ { "type": "object", "properties": { "claudeSessionId": { "type": "string", "minLength": 1 }, "provider": { "type": "string", "enum": [ "devin" ] }, "model": { "type": "string" }, "providerMeta": { "type": "object", "properties": { "sessionUrl": { "type": "string" }, "maxAcuLimit": { "type": "number" }, "acuCostUsd": { "type": "number" } }, "required": [ "sessionUrl" ] } }, "required": [ "claudeSessionId", "provider", "providerMeta" ] }, { "type": "object", "properties": { "claudeSessionId": { "type": "string", "minLength": 1 }, "provider": { "type": "string", "enum": [ "claude", "codex", "pi", "claude-managed", "opencode" ] }, "model": { "type": "string" }, "providerMeta": { "type": "object", "properties": {} } }, "required": [ "claudeSessionId" ] } ] } } } }, "responses": { "200": { "description": "Session ID updated" }, "404": { "description": "Task not found" } } } }, "/api/tasks/{id}/cancel": { "post": { "summary": "Cancel a pending or in-progress task", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Task cancelled" }, "400": { "description": "Cannot cancel terminal task" }, "404": { "description": "Task not found" } } } }, "/api/tasks/{id}": { "get": { "summary": "Get task details with logs", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Task with logs" }, "404": { "description": "Task not found" } } } }, "/api/tasks/{id}/progress": { "post": { "summary": "Update task progress text", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "progress": { "type": "string", "minLength": 1 } }, "required": [ "progress" ] } } } }, "responses": { "200": { "description": "Progress updated" }, "404": { "description": "Task not found" } } } }, "/api/tasks/{id}/finish": { "post": { "summary": "Mark task as completed or failed (runner endpoint)", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string", "enum": [ "completed", "failed" ] }, "output": { "type": "string" }, "failureReason": { "type": "string" } }, "required": [ "status" ] } } } }, "responses": { "200": { "description": "Task finished" }, "400": { "description": "Invalid status" }, "403": { "description": "Not assigned to this agent" }, "404": { "description": "Task not found" } } } }, "/api/paused-tasks": { "get": { "summary": "Get paused tasks for this agent", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Paused task list" } } } }, "/api/tasks/{id}/pause": { "post": { "summary": "Pause an in-progress task", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Task paused" }, "400": { "description": "Task not in_progress" }, "403": { "description": "Task belongs to another agent" }, "404": { "description": "Task not found" } } } }, "/api/tasks/{id}/resume": { "post": { "summary": "Resume a paused task", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Task resumed" }, "400": { "description": "Task not paused" }, "403": { "description": "Task belongs to another agent" }, "404": { "description": "Task not found" } } } }, "/api/tasks/{id}/vcs": { "patch": { "summary": "Update VCS (PR/MR) info for a task", "tags": [ "Tasks" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "vcsProvider": { "type": "string", "enum": [ "github", "gitlab" ] }, "vcsRepo": { "type": "string" }, "vcsNumber": { "type": "integer", "exclusiveMinimum": 0 }, "vcsUrl": { "type": "string", "format": "uri" } }, "required": [ "vcsProvider", "vcsRepo", "vcsNumber", "vcsUrl" ] } } } }, "responses": { "200": { "description": "VCS info updated" }, "404": { "description": "Task not found" } } } }, "/api/trackers/jira/authorize": { "get": { "summary": "Redirect to Atlassian OAuth consent screen", "tags": [ "Trackers" ], "responses": { "302": { "description": "Redirect to Atlassian OAuth" }, "500": { "description": "Failed to generate authorization URL" }, "503": { "description": "Jira integration not configured" } } } }, "/api/trackers/jira/callback": { "get": { "summary": "Handle Jira OAuth callback (resolves cloudId via accessible-resources)", "tags": [ "Trackers" ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "code", "in": "query" }, { "schema": { "type": "string" }, "required": true, "name": "state", "in": "query" } ], "responses": { "200": { "description": "OAuth complete" }, "400": { "description": "Invalid state or code" }, "500": { "description": "Token exchange or accessible-resources fetch failed" } } } }, "/api/trackers/jira/status": { "get": { "summary": "Jira connection status, cloudId/siteUrl, token expiry, expected webhook URL, scope/token-config flags", "tags": [ "Trackers" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Connection status" }, "503": { "description": "Jira integration not configured" } } } }, "/api/trackers/jira/refresh": { "post": { "summary": "Force a Jira OAuth token refresh and return the updated status payload. Useful when an agent observes an expired token via tracker-status / db-query and wants to recover without restarting the server or re-running 3LO.", "tags": [ "Trackers" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Token refreshed; returns same shape as /status" }, "409": { "description": "Jira not connected (no refresh token stored)" }, "500": { "description": "Refresh failed (e.g. revoked grant, network error)" }, "503": { "description": "Jira integration not configured" } } } }, "/api/trackers/jira/webhook/{token}": { "post": { "summary": "Receive Jira webhook events (URL-token authenticated). Phase 2 stub — Phase 3 fills in dispatch.", "tags": [ "Trackers" ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "token", "in": "path" } ], "responses": { "200": { "description": "Event accepted" }, "401": { "description": "Invalid URL token" }, "503": { "description": "Jira webhook handler not configured" } } } }, "/api/trackers/jira/webhook-register": { "post": { "summary": "Register a Jira dynamic webhook (admin only)", "tags": [ "Trackers" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "jqlFilter": { "type": "string", "minLength": 1 } }, "required": [ "jqlFilter" ] } } } }, "responses": { "200": { "description": "Webhook registered" }, "400": { "description": "Invalid jqlFilter" }, "503": { "description": "Jira not connected or JIRA_WEBHOOK_TOKEN missing" } } } }, "/api/trackers/jira/webhook/{id}": { "delete": { "summary": "Delete a Jira dynamic webhook (admin only)", "tags": [ "Trackers" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "integer", "exclusiveMinimum": 0 }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Webhook deleted" }, "400": { "description": "Invalid webhook id" }, "503": { "description": "Jira not connected" } } } }, "/api/trackers/jira/disconnect": { "delete": { "summary": "Fully disconnect Jira: delete all webhooks, drop tokens, clear metadata", "tags": [ "Trackers" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Disconnected" }, "503": { "description": "Jira not configured" } } } }, "/api/trackers/linear/authorize": { "get": { "summary": "Redirect to Linear OAuth consent screen", "tags": [ "Trackers" ], "responses": { "302": { "description": "Redirect to Linear OAuth" }, "500": { "description": "Failed to generate authorization URL" }, "503": { "description": "Linear integration not configured" } } } }, "/api/trackers/linear/callback": { "get": { "summary": "Handle Linear OAuth callback", "tags": [ "Trackers" ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "code", "in": "query" }, { "schema": { "type": "string" }, "required": true, "name": "state", "in": "query" } ], "responses": { "200": { "description": "OAuth complete" }, "400": { "description": "Invalid state or code" }, "500": { "description": "Token exchange failed" } } } }, "/api/trackers/linear/status": { "get": { "summary": "Linear connection status, token expiry, workspace info, expected webhook URL", "tags": [ "Trackers" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Connection status" }, "503": { "description": "Linear integration not configured" } } } }, "/api/trackers/linear/refresh": { "post": { "summary": "Force a Linear OAuth token refresh and return the updated status payload. Useful when an agent observes an expired token and wants to recover without restarting the server or re-running OAuth.", "tags": [ "Trackers" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Token refreshed; returns same shape as /status" }, "409": { "description": "Linear not connected (no refresh token stored)" }, "500": { "description": "Refresh failed" }, "503": { "description": "Linear integration not configured" } } } }, "/api/trackers/linear/webhook": { "post": { "summary": "Handle Linear webhook events (signature-verified)", "tags": [ "Trackers" ], "responses": { "200": { "description": "Event accepted" }, "401": { "description": "Invalid signature" }, "503": { "description": "Linear integration not configured" } } } }, "/api/trackers/linear/disconnect": { "delete": { "summary": "Fully disconnect Linear: revoke OAuth grant + drop tokens", "tags": [ "Trackers" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Disconnected" }, "503": { "description": "Linear not configured" } } } }, "/api/github/webhook": { "post": { "summary": "Handle GitHub webhook events", "tags": [ "Webhooks" ], "responses": { "200": { "description": "Event processed" }, "401": { "description": "Invalid signature" }, "503": { "description": "GitHub integration not configured" } } } }, "/api/gitlab/webhook": { "post": { "summary": "Handle GitLab webhook events", "tags": [ "Webhooks" ], "responses": { "200": { "description": "Event processed" }, "401": { "description": "Invalid token" }, "503": { "description": "GitLab integration not configured" } } } }, "/api/agentmail/webhook": { "post": { "summary": "Handle AgentMail webhook events", "tags": [ "Webhooks" ], "responses": { "200": { "description": "Event received" }, "401": { "description": "Invalid signature" }, "503": { "description": "AgentMail integration not configured" } } } }, "/api/workflow-runs/{runId}/events": { "post": { "summary": "Fire a run-scoped event signal", "description": "Emits an event onto the workflow event bus with `_runId` injected. Used by wait nodes in `event` mode with `scope: 'run'`. The body's `name` is the bus event name; `payload` is forwarded as-is plus `_runId`.", "tags": [ "WorkflowEvents" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string", "format": "uuid" }, "required": true, "name": "runId", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "payload": { "type": "object", "additionalProperties": {} } }, "required": [ "name" ] } } } }, "responses": { "200": { "description": "Event emitted" }, "400": { "description": "Validation error" }, "404": { "description": "Workflow run not found" } } } }, "/api/workflow-events": { "post": { "summary": "Fire a global workflow event signal", "description": "Emits an event onto the workflow event bus. Wait-states with `scope: 'global'` may match. Run-scoped waits will NOT match this broadcast unless the payload carries a matching `workflowRunId`.", "tags": [ "WorkflowEvents" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "payload": { "type": "object", "additionalProperties": {} } }, "required": [ "name" ] } } } }, "responses": { "200": { "description": "Event emitted" }, "400": { "description": "Validation error" } } } }, "/api/workflows": { "get": { "summary": "List all workflows", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "Workflow list" } } }, "post": { "summary": "Create a new workflow", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "description": { "type": "string" }, "definition": { "type": "object", "properties": { "nodes": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique node identifier, used in 'next' and 'inputs' mappings" }, "type": { "type": "string", "description": "Executor type: 'agent-task', 'script', 'raw-llm', 'validate', 'property-match'" }, "label": { "type": "string", "description": "Human-readable label for UI display" }, "config": { "type": "object", "additionalProperties": {}, "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, tags?, priority?, dir?, vcsRepo?, model? }. Values support {{interpolation}} from the node's inputs context. NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})." }, "next": { "anyOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" } }, { "type": "object", "additionalProperties": { "type": "string" } } ], "description": "Next node(s): string for simple chaining, string[] for fan-out to parallel nodes, or record for port-based routing ({pass: 'a', fail: 'b'})" }, "validation": { "type": "object", "properties": { "executor": { "type": "string", "default": "validate" }, "config": { "type": "object", "additionalProperties": {} }, "mustPass": { "type": "boolean", "default": false }, "retry": { "type": "object", "properties": { "maxRetries": { "type": "integer", "minimum": 0, "default": 3 }, "strategy": { "type": "string", "enum": [ "exponential", "static", "linear" ], "default": "exponential" }, "baseDelayMs": { "type": "integer", "minimum": 0, "default": 1000 }, "maxDelayMs": { "type": "integer", "minimum": 0, "default": 60000 } } } }, "required": [ "config" ] }, "retry": { "type": "object", "properties": { "maxRetries": { "type": "integer", "minimum": 0, "default": 3 }, "strategy": { "type": "string", "enum": [ "exponential", "static", "linear" ], "default": "exponential" }, "baseDelayMs": { "type": "integer", "minimum": 0, "default": 1000 }, "maxDelayMs": { "type": "integer", "minimum": 0, "default": 60000 } } }, "inputs": { "type": "object", "additionalProperties": { "type": "string" }, "description": "REQUIRED for cross-node data access. Maps local names to context paths. Without this, upstream step outputs are NOT available for interpolation — only 'trigger' and 'input' are. Example: { \"cityData\": \"generate-city\" } → use {{cityData.taskOutput.field}} in config templates. For trigger data: { \"pr\": \"trigger.pullRequest\" }." }, "inputSchema": { "type": "object", "additionalProperties": {}, "description": "JSON Schema to validate resolved inputs before execution" }, "outputSchema": { "type": "object", "additionalProperties": {}, "description": "JSON Schema to validate the executor's output (e.g. {taskId, taskOutput} for agent-task). Different from config.outputSchema which validates the agent's raw output." } }, "required": [ "id", "type", "config" ] }, "minItems": 1 }, "onNodeFailure": { "type": "string", "enum": [ "fail", "continue" ], "default": "fail", "description": "Behavior when a node's task fails or is cancelled. 'fail' (default): mark the entire run as failed. 'continue': treat the failed node as completed with error output and proceed — downstream convergence nodes receive '[FAILED: reason]' and can handle partial results." } }, "required": [ "nodes" ] }, "triggers": { "type": "array", "items": { "oneOf": [ { "type": "object", "properties": { "type": { "type": "string", "enum": [ "webhook" ] }, "hmacSecret": { "type": "string" }, "hmacHeader": { "type": "string", "default": "X-Hub-Signature-256" } }, "required": [ "type" ] }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "schedule" ] }, "scheduleId": { "type": "string", "format": "uuid" } }, "required": [ "type", "scheduleId" ] } ] } }, "cooldown": { "type": "object", "properties": { "hours": { "type": "number", "minimum": 0 }, "minutes": { "type": "number", "minimum": 0 }, "seconds": { "type": "number", "minimum": 0 } } }, "input": { "type": "object", "additionalProperties": { "anyOf": [ { "type": "string", "pattern": "^\\$\\{.+\\}$" }, { "type": "string", "pattern": "^secret\\..+$" }, { "type": "string" } ] } }, "triggerSchema": { "type": "object", "additionalProperties": {} }, "dir": { "type": "string", "minLength": 1 }, "vcsRepo": { "type": "string", "minLength": 1 } }, "required": [ "name", "definition" ] } } } }, "responses": { "201": { "description": "Workflow created" }, "400": { "description": "Invalid definition" } } } }, "/api/workflows/{id}": { "get": { "summary": "Get a workflow by ID", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Workflow details with auto-generated edges" }, "404": { "description": "Workflow not found" } } }, "put": { "summary": "Update a workflow", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" }, "definition": { "type": "object", "properties": { "nodes": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique node identifier, used in 'next' and 'inputs' mappings" }, "type": { "type": "string", "description": "Executor type: 'agent-task', 'script', 'raw-llm', 'validate', 'property-match'" }, "label": { "type": "string", "description": "Human-readable label for UI display" }, "config": { "type": "object", "additionalProperties": {}, "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, tags?, priority?, dir?, vcsRepo?, model? }. Values support {{interpolation}} from the node's inputs context. NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})." }, "next": { "anyOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" } }, { "type": "object", "additionalProperties": { "type": "string" } } ], "description": "Next node(s): string for simple chaining, string[] for fan-out to parallel nodes, or record for port-based routing ({pass: 'a', fail: 'b'})" }, "validation": { "type": "object", "properties": { "executor": { "type": "string", "default": "validate" }, "config": { "type": "object", "additionalProperties": {} }, "mustPass": { "type": "boolean", "default": false }, "retry": { "type": "object", "properties": { "maxRetries": { "type": "integer", "minimum": 0, "default": 3 }, "strategy": { "type": "string", "enum": [ "exponential", "static", "linear" ], "default": "exponential" }, "baseDelayMs": { "type": "integer", "minimum": 0, "default": 1000 }, "maxDelayMs": { "type": "integer", "minimum": 0, "default": 60000 } } } }, "required": [ "config" ] }, "retry": { "type": "object", "properties": { "maxRetries": { "type": "integer", "minimum": 0, "default": 3 }, "strategy": { "type": "string", "enum": [ "exponential", "static", "linear" ], "default": "exponential" }, "baseDelayMs": { "type": "integer", "minimum": 0, "default": 1000 }, "maxDelayMs": { "type": "integer", "minimum": 0, "default": 60000 } } }, "inputs": { "type": "object", "additionalProperties": { "type": "string" }, "description": "REQUIRED for cross-node data access. Maps local names to context paths. Without this, upstream step outputs are NOT available for interpolation — only 'trigger' and 'input' are. Example: { \"cityData\": \"generate-city\" } → use {{cityData.taskOutput.field}} in config templates. For trigger data: { \"pr\": \"trigger.pullRequest\" }." }, "inputSchema": { "type": "object", "additionalProperties": {}, "description": "JSON Schema to validate resolved inputs before execution" }, "outputSchema": { "type": "object", "additionalProperties": {}, "description": "JSON Schema to validate the executor's output (e.g. {taskId, taskOutput} for agent-task). Different from config.outputSchema which validates the agent's raw output." } }, "required": [ "id", "type", "config" ] }, "minItems": 1 }, "onNodeFailure": { "type": "string", "enum": [ "fail", "continue" ], "default": "fail", "description": "Behavior when a node's task fails or is cancelled. 'fail' (default): mark the entire run as failed. 'continue': treat the failed node as completed with error output and proceed — downstream convergence nodes receive '[FAILED: reason]' and can handle partial results." } }, "required": [ "nodes" ] }, "triggers": { "type": "array", "items": { "oneOf": [ { "type": "object", "properties": { "type": { "type": "string", "enum": [ "webhook" ] }, "hmacSecret": { "type": "string" }, "hmacHeader": { "type": "string", "default": "X-Hub-Signature-256" } }, "required": [ "type" ] }, { "type": "object", "properties": { "type": { "type": "string", "enum": [ "schedule" ] }, "scheduleId": { "type": "string", "format": "uuid" } }, "required": [ "type", "scheduleId" ] } ] } }, "cooldown": { "type": [ "object", "null" ], "properties": { "hours": { "type": "number", "minimum": 0 }, "minutes": { "type": "number", "minimum": 0 }, "seconds": { "type": "number", "minimum": 0 } } }, "input": { "type": [ "object", "null" ], "additionalProperties": { "anyOf": [ { "type": "string", "pattern": "^\\$\\{.+\\}$" }, { "type": "string", "pattern": "^secret\\..+$" }, { "type": "string" } ] } }, "triggerSchema": { "type": [ "object", "null" ], "additionalProperties": {} }, "dir": { "type": [ "string", "null" ], "minLength": 1 }, "vcsRepo": { "type": [ "string", "null" ], "minLength": 1 }, "enabled": { "type": "boolean" } } } } } }, "responses": { "200": { "description": "Workflow updated (version snapshot created)" }, "400": { "description": "Invalid definition" }, "404": { "description": "Workflow not found" } } }, "patch": { "summary": "Patch a workflow definition (create/update/delete nodes)", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "update": { "type": "array", "items": { "type": "object", "properties": { "nodeId": { "type": "string", "description": "ID of the node to update" }, "node": { "type": "object", "properties": { "type": { "type": "string", "description": "Executor type: 'agent-task', 'script', 'raw-llm', 'validate', 'property-match'" }, "label": { "type": "string", "description": "Human-readable label for UI display" }, "config": { "type": "object", "additionalProperties": {}, "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, tags?, priority?, dir?, vcsRepo?, model? }. Values support {{interpolation}} from the node's inputs context. NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})." }, "next": { "anyOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" } }, { "type": "object", "additionalProperties": { "type": "string" } } ], "description": "Next node(s): string for simple chaining, string[] for fan-out to parallel nodes, or record for port-based routing ({pass: 'a', fail: 'b'})" }, "validation": { "type": "object", "properties": { "executor": { "type": "string", "default": "validate" }, "config": { "type": "object", "additionalProperties": {} }, "mustPass": { "type": "boolean", "default": false }, "retry": { "type": "object", "properties": { "maxRetries": { "type": "integer", "minimum": 0, "default": 3 }, "strategy": { "type": "string", "enum": [ "exponential", "static", "linear" ], "default": "exponential" }, "baseDelayMs": { "type": "integer", "minimum": 0, "default": 1000 }, "maxDelayMs": { "type": "integer", "minimum": 0, "default": 60000 } } } }, "required": [ "config" ] }, "retry": { "type": "object", "properties": { "maxRetries": { "type": "integer", "minimum": 0, "default": 3 }, "strategy": { "type": "string", "enum": [ "exponential", "static", "linear" ], "default": "exponential" }, "baseDelayMs": { "type": "integer", "minimum": 0, "default": 1000 }, "maxDelayMs": { "type": "integer", "minimum": 0, "default": 60000 } } }, "inputs": { "type": "object", "additionalProperties": { "type": "string" }, "description": "REQUIRED for cross-node data access. Maps local names to context paths. Without this, upstream step outputs are NOT available for interpolation — only 'trigger' and 'input' are. Example: { \"cityData\": \"generate-city\" } → use {{cityData.taskOutput.field}} in config templates. For trigger data: { \"pr\": \"trigger.pullRequest\" }." }, "inputSchema": { "type": "object", "additionalProperties": {}, "description": "JSON Schema to validate resolved inputs before execution" }, "outputSchema": { "type": "object", "additionalProperties": {}, "description": "JSON Schema to validate the executor's output (e.g. {taskId, taskOutput} for agent-task). Different from config.outputSchema which validates the agent's raw output." } }, "description": "Partial node data to merge" } }, "required": [ "nodeId", "node" ] }, "description": "Nodes to update (partial merge)" }, "delete": { "type": "array", "items": { "type": "string" }, "description": "Node IDs to delete" }, "create": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique node identifier, used in 'next' and 'inputs' mappings" }, "type": { "type": "string", "description": "Executor type: 'agent-task', 'script', 'raw-llm', 'validate', 'property-match'" }, "label": { "type": "string", "description": "Human-readable label for UI display" }, "config": { "type": "object", "additionalProperties": {}, "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, tags?, priority?, dir?, vcsRepo?, model? }. Values support {{interpolation}} from the node's inputs context. NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})." }, "next": { "anyOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" } }, { "type": "object", "additionalProperties": { "type": "string" } } ], "description": "Next node(s): string for simple chaining, string[] for fan-out to parallel nodes, or record for port-based routing ({pass: 'a', fail: 'b'})" }, "validation": { "type": "object", "properties": { "executor": { "type": "string", "default": "validate" }, "config": { "type": "object", "additionalProperties": {} }, "mustPass": { "type": "boolean", "default": false }, "retry": { "type": "object", "properties": { "maxRetries": { "type": "integer", "minimum": 0, "default": 3 }, "strategy": { "type": "string", "enum": [ "exponential", "static", "linear" ], "default": "exponential" }, "baseDelayMs": { "type": "integer", "minimum": 0, "default": 1000 }, "maxDelayMs": { "type": "integer", "minimum": 0, "default": 60000 } } } }, "required": [ "config" ] }, "retry": { "type": "object", "properties": { "maxRetries": { "type": "integer", "minimum": 0, "default": 3 }, "strategy": { "type": "string", "enum": [ "exponential", "static", "linear" ], "default": "exponential" }, "baseDelayMs": { "type": "integer", "minimum": 0, "default": 1000 }, "maxDelayMs": { "type": "integer", "minimum": 0, "default": 60000 } } }, "inputs": { "type": "object", "additionalProperties": { "type": "string" }, "description": "REQUIRED for cross-node data access. Maps local names to context paths. Without this, upstream step outputs are NOT available for interpolation — only 'trigger' and 'input' are. Example: { \"cityData\": \"generate-city\" } → use {{cityData.taskOutput.field}} in config templates. For trigger data: { \"pr\": \"trigger.pullRequest\" }." }, "inputSchema": { "type": "object", "additionalProperties": {}, "description": "JSON Schema to validate resolved inputs before execution" }, "outputSchema": { "type": "object", "additionalProperties": {}, "description": "JSON Schema to validate the executor's output (e.g. {taskId, taskOutput} for agent-task). Different from config.outputSchema which validates the agent's raw output." } }, "required": [ "id", "type", "config" ] }, "description": "New nodes to add" }, "onNodeFailure": { "type": "string", "enum": [ "fail", "continue" ], "description": "Update the definition-level onNodeFailure behavior" }, "triggerSchema": { "type": [ "object", "null" ], "additionalProperties": {}, "description": "Optional JSON-Schema describing the expected trigger payload shape. Pass an object to set/replace; pass null to clear; omit to leave unchanged. Validator subset: type, required, properties, enum, const, items. Other JSON-Schema keywords are silently ignored." } } } } } }, "responses": { "200": { "description": "Workflow patched (version snapshot created)" }, "400": { "description": "Invalid patch or resulting definition" }, "404": { "description": "Workflow not found" } } }, "delete": { "summary": "Delete a workflow", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "204": { "description": "Workflow deleted" }, "404": { "description": "Workflow not found" } } } }, "/api/workflows/{id}/nodes/{nodeId}": { "patch": { "summary": "Patch a single node in a workflow definition", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "string" }, "required": true, "name": "nodeId", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "type": { "type": "string", "description": "Executor type: 'agent-task', 'script', 'raw-llm', 'validate', 'property-match'" }, "label": { "type": "string", "description": "Human-readable label for UI display" }, "config": { "type": "object", "additionalProperties": {}, "description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, tags?, priority?, dir?, vcsRepo?, model? }. Values support {{interpolation}} from the node's inputs context. NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})." }, "next": { "anyOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" } }, { "type": "object", "additionalProperties": { "type": "string" } } ], "description": "Next node(s): string for simple chaining, string[] for fan-out to parallel nodes, or record for port-based routing ({pass: 'a', fail: 'b'})" }, "validation": { "type": "object", "properties": { "executor": { "type": "string", "default": "validate" }, "config": { "type": "object", "additionalProperties": {} }, "mustPass": { "type": "boolean", "default": false }, "retry": { "type": "object", "properties": { "maxRetries": { "type": "integer", "minimum": 0, "default": 3 }, "strategy": { "type": "string", "enum": [ "exponential", "static", "linear" ], "default": "exponential" }, "baseDelayMs": { "type": "integer", "minimum": 0, "default": 1000 }, "maxDelayMs": { "type": "integer", "minimum": 0, "default": 60000 } } } }, "required": [ "config" ] }, "retry": { "type": "object", "properties": { "maxRetries": { "type": "integer", "minimum": 0, "default": 3 }, "strategy": { "type": "string", "enum": [ "exponential", "static", "linear" ], "default": "exponential" }, "baseDelayMs": { "type": "integer", "minimum": 0, "default": 1000 }, "maxDelayMs": { "type": "integer", "minimum": 0, "default": 60000 } } }, "inputs": { "type": "object", "additionalProperties": { "type": "string" }, "description": "REQUIRED for cross-node data access. Maps local names to context paths. Without this, upstream step outputs are NOT available for interpolation — only 'trigger' and 'input' are. Example: { \"cityData\": \"generate-city\" } → use {{cityData.taskOutput.field}} in config templates. For trigger data: { \"pr\": \"trigger.pullRequest\" }." }, "inputSchema": { "type": "object", "additionalProperties": {}, "description": "JSON Schema to validate resolved inputs before execution" }, "outputSchema": { "type": "object", "additionalProperties": {}, "description": "JSON Schema to validate the executor's output (e.g. {taskId, taskOutput} for agent-task). Different from config.outputSchema which validates the agent's raw output." } } } } } }, "responses": { "200": { "description": "Node patched (version snapshot created)" }, "400": { "description": "Invalid patch or resulting definition" }, "404": { "description": "Workflow or node not found" } } } }, "/api/workflows/{id}/trigger": { "post": { "summary": "Trigger a workflow execution", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "201": { "description": "Workflow run started (or skipped if cooldown active)" }, "400": { "description": "Workflow is disabled" }, "401": { "description": "Unauthorized" }, "404": { "description": "Workflow not found" } } } }, "/api/workflows/{id}/trigger/validate": { "post": { "summary": "Validate a payload against the workflow's triggerSchema (no run)", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Payload matches the workflow's triggerSchema (or workflow has none)" }, "400": { "description": "Payload failed validation; body matches the TriggerSchemaError contract" }, "404": { "description": "Workflow not found" } } } }, "/api/workflows/{id}/runs": { "get": { "summary": "List runs for a workflow", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "string", "enum": [ "running", "waiting", "completed", "failed", "skipped", "cancelled" ] }, "required": false, "name": "status", "in": "query" } ], "responses": { "200": { "description": "Workflow run list" } } } }, "/api/workflow-runs/{id}": { "get": { "summary": "Get a workflow run with steps (includes retry columns)", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Workflow run details with steps including retry info" }, "404": { "description": "Run not found" } } } }, "/api/workflow-runs/{id}/retry": { "post": { "summary": "Retry a failed workflow run", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Retry started" }, "400": { "description": "Cannot retry" } } } }, "/api/workflow-runs/{id}/cancel": { "post": { "summary": "Cancel a running or waiting workflow run", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "reason": { "type": "string" } } } } } }, "responses": { "200": { "description": "Run cancelled" }, "400": { "description": "Cannot cancel" } } } }, "/api/executor-types": { "get": { "summary": "List all executor types with their config and output schemas", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "responses": { "200": { "description": "List of executor types with schemas" } } } }, "/api/executor-types/{type}": { "get": { "summary": "Get a specific executor type with its schemas", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "type", "in": "path" } ], "responses": { "200": { "description": "Executor type details" }, "404": { "description": "Executor type not found" } } } }, "/api/webhooks/{workflowId}": { "post": { "summary": "Trigger workflow via webhook", "tags": [ "Webhooks" ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "workflowId", "in": "path" } ], "responses": { "201": { "description": "Webhook processed" }, "401": { "description": "Invalid signature" }, "404": { "description": "Workflow not found" } } } }, "/api/workflows/{id}/versions": { "get": { "summary": "List version history for a workflow", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" } ], "responses": { "200": { "description": "Version list (newest first)" }, "404": { "description": "Workflow not found" } } } }, "/api/workflows/{id}/versions/{version}": { "get": { "summary": "Get a specific version snapshot of a workflow", "tags": [ "Workflows" ], "security": [ { "bearerAuth": [] } ], "parameters": [ { "schema": { "type": "string" }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "integer", "minimum": 1 }, "required": true, "name": "version", "in": "path" } ], "responses": { "200": { "description": "Version snapshot" }, "404": { "description": "Version not found" } } } } }, "webhooks": {} }