openapi: 3.0.3 info: title: Switchboard Core API description: | Self-hosted extension platform. Identity, teams, permissions, workflows, and a package system. Everything else ships as installable extensions. ## Authentication Three authentication modes, selected by the `AUTH_MODE` environment variable. All three produce the same JWT-based session. **Builtin (default):** Username/password via `POST /api/v1/auth/login`. **mTLS:** Client certificate presented via reverse proxy headers. **OIDC:** Authorization code flow against an external IdP (e.g. Keycloak). Access tokens expire in 15 minutes. Refresh tokens expire in 7 days. Use `POST /api/v1/auth/refresh` to rotate. ## Maintenance This spec is maintained by hand. When adding a kernel route, add a corresponding path entry here. Extension routes (`/s/:slug/api/*`) and page routes are not part of this ICD. version: '${VERSION}' servers: - url: '{scheme}://{host}{basePath}' variables: scheme: default: https host: default: localhost:8080 basePath: default: '' tags: - name: System - name: Auth - name: WebSocket - name: Profile - name: Presence - name: Notifications - name: Workflows - name: Workflow Instances - name: Workflow Assignments - name: Workflow Signoffs - name: Public Workflows - name: Packages - name: Connections - name: Teams - name: Groups - name: Extensions - name: 'Admin: Users' - name: 'Admin: Settings' - name: 'Admin: Teams' - name: 'Admin: Groups' - name: 'Admin: Permissions' - name: 'Admin: Connections' - name: 'Admin: Extensions' - name: 'Admin: Packages' - name: 'Admin: System' - name: 'Admin: Workflows' - name: Triggers - name: Schedules - name: 'Admin: Triggers' - name: 'Admin: Schedules' security: - BearerAuth: [] components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT WsAuth: type: apiKey in: query name: ticket schemas: ErrorResponse: type: object properties: error: type: string required: [error] Trigger: type: object properties: id: { type: string, format: uuid } package_id: { type: string } type: { type: string, enum: [webhook, event] } enabled: { type: boolean } slug: { type: string } event_pattern: { type: string } entry_point: { type: string } config: { type: object } fire_count: { type: integer } last_fire_at: { type: string, format: date-time, nullable: true } last_error: { type: string } created_at: { type: string, format: date-time } updated_at: { type: string, format: date-time } ScheduledTask: type: object properties: id: { type: string, format: uuid } name: { type: string } description: { type: string } creator_id: { type: string, format: uuid } run_as: { type: string, enum: [creator, system] } cron_expr: { type: string } next_fire_at: { type: string, format: date-time, nullable: true } last_fire_at: { type: string, format: date-time, nullable: true } enabled: { type: boolean } script: { type: string } template_id: { type: string, nullable: true } template_params: { type: object } fire_count: { type: integer } last_error: { type: string } last_duration_ms: { type: integer, nullable: true } created_at: { type: string, format: date-time } updated_at: { type: string, format: date-time } TriggerLog: type: object properties: id: { type: string, format: uuid } trigger_id: { type: string, format: uuid, nullable: true } scheduled_task_id: { type: string, format: uuid, nullable: true } fired_at: { type: string, format: date-time } duration_ms: { type: integer, nullable: true } success: { type: boolean } error: { type: string } output: { type: string } TokenResponse: type: object properties: access_token: type: string refresh_token: type: string token_type: type: string enum: [bearer] expires_in: type: integer example: 900 user: type: object properties: id: type: string format: uuid username: type: string email: type: string display_name: type: string handle: type: string auth_source: type: string enum: [builtin, oidc, mtls] User: type: object properties: id: type: string format: uuid username: type: string email: type: string display_name: type: string avatar_url: type: string nullable: true is_active: type: boolean settings: type: object last_login_at: type: string format: date-time nullable: true auth_source: type: string enum: [builtin, oidc, mtls] handle: type: string created_at: type: string format: date-time updated_at: type: string format: date-time Team: type: object properties: id: type: string format: uuid name: type: string description: type: string created_by: type: string format: uuid is_active: type: boolean settings: type: object member_count: type: integer my_role: type: string created_at: type: string format: date-time updated_at: type: string format: date-time TeamMember: type: object properties: id: type: string format: uuid team_id: type: string format: uuid user_id: type: string format: uuid role: type: string enum: [admin, member] joined_at: type: string format: date-time email: type: string display_name: type: string username: type: string Group: type: object properties: id: type: string format: uuid name: type: string description: type: string scope: type: string enum: [global, team] team_id: type: string format: uuid nullable: true source: type: string permissions: type: array items: type: string member_count: type: integer created_at: type: string format: date-time updated_at: type: string format: date-time GroupMember: type: object properties: id: type: string format: uuid group_id: type: string format: uuid user_id: type: string format: uuid added_by: type: string format: uuid added_at: type: string format: date-time username: type: string email: type: string display_name: type: string ResourceGrant: type: object properties: id: type: string format: uuid resource_type: type: string resource_id: type: string grant_scope: type: string enum: [team_only, global, groups] granted_groups: type: array items: type: string created_by: type: string format: uuid created_at: type: string format: date-time updated_at: type: string format: date-time AuditEntry: type: object properties: id: type: string format: uuid actor_id: type: string format: uuid nullable: true actor_name: type: string nullable: true action: type: string resource_type: type: string resource_id: type: string metadata: type: object ip_address: type: string user_agent: type: string created_at: type: string format: date-time Workflow: type: object properties: id: type: string format: uuid name: type: string slug: type: string description: type: string entry_mode: type: string enum: [public_link, team_only] team_id: type: string format: uuid nullable: true is_active: type: boolean version: type: integer branding: type: object on_complete: type: object retention: type: object webhook_url: type: string webhook_secret: type: string staleness_timeout_hours: type: integer nullable: true created_by: type: string format: uuid stages: type: array items: $ref: '#/components/schemas/Stage' created_at: type: string format: date-time updated_at: type: string format: date-time Stage: type: object properties: id: type: string format: uuid workflow_id: type: string format: uuid name: type: string ordinal: type: integer stage_mode: type: string enum: [form, review, delegated, automated] audience: type: string enum: [team, public, system] stage_type: type: string enum: [simple, dynamic, automated] form_template: type: object stage_config: type: object branch_rules: type: array items: type: object starlark_hook: type: string nullable: true assignment_team_id: type: string format: uuid nullable: true surface_pkg_id: type: string format: uuid nullable: true auto_transition: type: boolean sla_seconds: type: integer nullable: true created_at: type: string format: date-time WorkflowVersion: type: object properties: id: type: string format: uuid workflow_id: type: string format: uuid version_number: type: integer snapshot: type: object created_at: type: string format: date-time WorkflowInstance: type: object properties: id: type: string format: uuid workflow_id: type: string format: uuid workflow_version: type: integer current_stage: type: string stage_data: type: object status: type: string enum: [active, completed, cancelled, stale, error] started_by: type: string entry_token: type: string nullable: true metadata: type: object stage_entered_at: type: string format: date-time created_at: type: string format: date-time updated_at: type: string format: date-time WorkflowAssignment: type: object properties: id: type: string format: uuid instance_id: type: string format: uuid stage: type: string team_id: type: string format: uuid assigned_to: type: string format: uuid nullable: true status: type: string enum: [unassigned, claimed, completed, cancelled] review_data: type: object nullable: true claimed_at: type: string format: date-time nullable: true completed_at: type: string format: date-time nullable: true created_at: type: string format: date-time WorkflowSignoff: type: object properties: id: type: string format: uuid instance_id: type: string format: uuid stage: type: string user_id: type: string format: uuid decision: type: string enum: [approve, reject] comment: type: string created_at: type: string format: date-time Package: type: object properties: id: type: string format: uuid title: type: string type: type: string enum: [surface, extension, full, workflow, library] version: type: string description: type: string author: type: string tier: type: string enum: [browser, starlark, sidecar] scope: type: string enum: [global, team, personal] team_id: type: string format: uuid nullable: true enabled: type: boolean source: type: string created_at: type: string format: date-time updated_at: type: string format: date-time Extension: type: object properties: id: type: string format: uuid ext_id: type: string name: type: string version: type: string tier: type: string description: type: string author: type: string manifest: type: object is_system: type: boolean is_enabled: type: boolean scope: type: string team_id: type: string format: uuid nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time NotificationPreference: type: object properties: user_id: type: string format: uuid type: type: string in_app: type: boolean email: type: boolean parameters: limitParam: name: limit in: query schema: type: integer default: 50 offsetParam: name: offset in: query schema: type: integer default: 0 pageParam: name: page in: query schema: type: integer default: 1 perPageParam: name: per_page in: query schema: type: integer default: 50 idPath: name: id in: path required: true schema: type: string format: uuid teamIdPath: name: teamId in: path required: true schema: type: string format: uuid paths: # ────────────────────────────────────────────── # System # ────────────────────────────────────────────── /health: get: summary: Legacy health check operationId: healthCheck tags: [System] security: [] responses: '200': description: Health status content: application/json: schema: type: object properties: status: type: string version: type: string database: type: string database_name: type: string schema_version: type: integer /healthz/live: get: summary: Liveness probe operationId: livenessProbe tags: [System] security: [] responses: '200': description: Process is alive content: application/json: schema: type: object properties: status: type: string example: ok /healthz/ready: get: summary: Readiness probe operationId: readinessProbe tags: [System] security: [] responses: '200': description: Service is ready content: application/json: schema: type: object properties: status: type: string example: ok '503': description: Service unavailable content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /metrics: get: summary: Prometheus metrics operationId: getMetrics tags: [System] security: [] responses: '200': description: Prometheus text exposition content: text/plain: schema: type: string /api/v1/health: get: summary: API health check operationId: apiHealthCheck tags: [System] security: [] responses: '200': description: API health status content: application/json: schema: type: object properties: status: type: string version: type: string schema_version: type: integer database: type: string database_name: type: string registration_enabled: type: boolean # ────────────────────────────────────────────── # Auth # ────────────────────────────────────────────── /api/v1/auth/register: post: summary: Register a new user operationId: registerUser tags: [Auth] security: [] requestBody: required: true content: application/json: schema: type: object required: [username, email, password] properties: username: type: string email: type: string password: type: string display_name: type: string responses: '201': description: User created content: application/json: schema: $ref: '#/components/schemas/TokenResponse' '400': description: Validation error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '409': description: Username or email taken content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/v1/auth/login: post: summary: Log in with username or email operationId: loginUser tags: [Auth] security: [] requestBody: required: true content: application/json: schema: type: object required: [login, password] properties: login: type: string password: type: string responses: '200': description: Authenticated content: application/json: schema: $ref: '#/components/schemas/TokenResponse' '401': description: Invalid credentials content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/v1/auth/refresh: post: summary: Refresh access token operationId: refreshToken tags: [Auth] security: [] requestBody: required: true content: application/json: schema: type: object required: [refresh_token] properties: refresh_token: type: string responses: '200': description: New token pair content: application/json: schema: $ref: '#/components/schemas/TokenResponse' '401': description: Invalid or expired refresh token content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/v1/auth/logout: post: summary: Log out and revoke tokens operationId: logoutUser tags: [Auth] security: [] requestBody: content: application/json: schema: type: object properties: refresh_token: type: string responses: '200': description: Logged out content: application/json: schema: type: object properties: message: type: string /api/v1/auth/oidc/login: get: summary: Start OIDC login flow operationId: oidcLogin tags: [Auth] security: [] parameters: - name: redirect in: query schema: type: string responses: '302': description: Redirect to IdP /api/v1/auth/oidc/callback: get: summary: OIDC callback endpoint operationId: oidcCallback tags: [Auth] security: [] parameters: - name: code in: query required: true schema: type: string - name: state in: query required: true schema: type: string - name: error in: query schema: type: string - name: error_description in: query schema: type: string responses: '302': description: Redirect to app with tokens # ────────────────────────────────────────────── # WebSocket # ────────────────────────────────────────────── /ws: get: summary: WebSocket connection operationId: wsConnect tags: [WebSocket] security: - WsAuth: [] parameters: - name: ticket in: query required: true schema: type: string responses: '101': description: Switching protocols /api/v1/ws/ticket: post: summary: Get a WebSocket ticket operationId: getWsTicket tags: [WebSocket] responses: '200': description: One-time ticket content: application/json: schema: type: object properties: ticket: type: string # ────────────────────────────────────────────── # Extension Assets # ────────────────────────────────────────────── /api/v1/extensions/{id}/assets/{path}: get: summary: Serve extension static asset operationId: getExtensionAsset tags: [Extensions] security: [] parameters: - name: id in: path required: true schema: type: string format: uuid - name: path in: path required: true schema: type: string responses: '200': description: Static file '404': description: Asset not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' # ────────────────────────────────────────────── # Profile # ────────────────────────────────────────────── /api/v1/profile: get: summary: Get current user profile operationId: getProfile tags: [Profile] responses: '200': description: Current user profile content: application/json: schema: type: object properties: id: type: string format: uuid username: type: string email: type: string display_name: type: string avatar: type: string nullable: true settings: type: object created_at: type: string format: date-time last_login_at: type: string format: date-time nullable: true put: summary: Update current user profile operationId: updateProfile tags: [Profile] requestBody: required: true content: application/json: schema: type: object properties: display_name: type: string email: type: string responses: '200': description: Updated profile content: application/json: schema: type: object properties: id: type: string format: uuid username: type: string email: type: string display_name: type: string avatar: type: string nullable: true settings: type: object created_at: type: string format: date-time last_login_at: type: string format: date-time nullable: true /api/v1/profile/password: post: summary: Change password operationId: changePassword tags: [Profile] requestBody: required: true content: application/json: schema: type: object required: [current_password, new_password] properties: current_password: type: string new_password: type: string responses: '200': description: Password changed content: application/json: schema: type: object properties: message: type: string '400': description: Validation error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/v1/settings: get: summary: Get user settings operationId: getUserSettings tags: [Profile] responses: '200': description: User settings content: application/json: schema: type: object properties: settings: type: object put: summary: Update user settings operationId: updateUserSettings tags: [Profile] requestBody: required: true content: application/json: schema: type: object responses: '200': description: Updated settings content: application/json: schema: type: object properties: settings: type: object /api/v1/profile/permissions: get: summary: Get current user permissions operationId: getMyPermissions tags: [Profile] responses: '200': description: Permissions for current user content: application/json: schema: type: object properties: permissions: type: array items: type: string groups: type: array items: type: object teams: type: array items: type: object policies: type: object /api/v1/profile/bootstrap: get: summary: Bootstrap data for current user operationId: getBootstrap tags: [Profile] responses: '200': description: Combined bootstrap payload content: application/json: schema: type: object properties: user: type: object permissions: type: array items: type: string groups: type: array items: type: object teams: type: array items: type: object policies: type: object settings: type: object # ────────────────────────────────────────────── # Presence # ────────────────────────────────────────────── /api/v1/presence/heartbeat: post: summary: Send presence heartbeat operationId: presenceHeartbeat tags: [Presence] responses: '200': description: Heartbeat acknowledged content: application/json: schema: type: object properties: ok: type: boolean /api/v1/presence: get: summary: Get presence for users operationId: getPresence tags: [Presence] parameters: - name: users in: query schema: type: string responses: '200': description: Presence map content: application/json: schema: type: object properties: presence: type: object /api/v1/users/search: get: summary: Search users by name or email operationId: searchUsers tags: [Presence] parameters: - name: q in: query required: true schema: type: string responses: '200': description: Matching users content: application/json: schema: type: object properties: data: type: array items: type: object # ────────────────────────────────────────────── # Notifications # ────────────────────────────────────────────── /api/v1/notifications: get: summary: List notifications operationId: listNotifications tags: [Notifications] parameters: - $ref: '#/components/parameters/limitParam' - $ref: '#/components/parameters/offsetParam' - name: unread_only in: query schema: type: boolean responses: '200': description: Paginated notifications content: application/json: schema: type: object properties: data: type: array items: type: object total: type: integer limit: type: integer offset: type: integer /api/v1/notifications/unread-count: get: summary: Get unread notification count operationId: getUnreadCount tags: [Notifications] responses: '200': description: Unread count content: application/json: schema: type: object properties: count: type: integer /api/v1/notifications/{id}/read: patch: summary: Mark notification as read operationId: markNotificationRead tags: [Notifications] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Marked as read content: application/json: schema: type: object properties: ok: type: boolean /api/v1/notifications/mark-all-read: post: summary: Mark all notifications as read operationId: markAllNotificationsRead tags: [Notifications] responses: '200': description: All marked as read content: application/json: schema: type: object properties: ok: type: boolean /api/v1/notifications/{id}: delete: summary: Delete a notification operationId: deleteNotification tags: [Notifications] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: ok: type: boolean /api/v1/notifications/preferences: get: summary: Get notification preferences operationId: getNotificationPreferences tags: [Notifications] responses: '200': description: Notification preferences content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/NotificationPreference' /api/v1/notifications/preferences/{type}: put: summary: Update notification preference operationId: updateNotificationPreference tags: [Notifications] parameters: - name: type in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: in_app: type: boolean email: type: boolean responses: '200': description: Updated preference content: application/json: schema: $ref: '#/components/schemas/NotificationPreference' delete: summary: Delete notification preference operationId: deleteNotificationPreference tags: [Notifications] parameters: - name: type in: path required: true schema: type: string responses: '200': description: Deleted content: application/json: schema: type: object properties: ok: type: boolean # ────────────────────────────────────────────── # User Teams / Groups # ────────────────────────────────────────────── /api/v1/teams/mine: get: summary: List teams for current user operationId: listMyTeams tags: [Teams] responses: '200': description: User teams content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Team' /api/v1/groups/mine: get: summary: List groups for current user operationId: listMyGroups tags: [Groups] responses: '200': description: User groups content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Group' # ────────────────────────────────────────────── # Public Settings # ────────────────────────────────────────────── /api/v1/settings/public: get: summary: Get public settings operationId: getPublicSettings tags: [System] security: [] responses: '200': description: Public settings content: application/json: schema: type: object properties: banner: type: string branding: type: object has_admin_prompt: type: boolean storage_configured: type: boolean paste_to_file_chars: type: integer policies: type: object # ────────────────────────────────────────────── # Workflows (user-scoped) # ────────────────────────────────────────────── /api/v1/workflows: get: summary: List workflows operationId: listWorkflows tags: [Workflows] responses: '200': description: Workflow list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Workflow' post: summary: Create a workflow operationId: createWorkflow tags: [Workflows] requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string entry_mode: type: string enum: [public_link, team_only] responses: '201': description: Workflow created content: application/json: schema: $ref: '#/components/schemas/Workflow' /api/v1/workflows/{id}: get: summary: Get a workflow operationId: getWorkflow tags: [Workflows] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Workflow detail content: application/json: schema: $ref: '#/components/schemas/Workflow' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' patch: summary: Update a workflow operationId: updateWorkflow tags: [Workflows] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object properties: name: type: string entry_mode: type: string enum: [public_link, team_only] responses: '200': description: Updated workflow content: application/json: schema: $ref: '#/components/schemas/Workflow' delete: summary: Delete a workflow operationId: deleteWorkflow tags: [Workflows] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean /api/v1/workflows/{id}/stages: get: summary: List stages for a workflow operationId: listWorkflowStages tags: [Workflows] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Stage list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Stage' post: summary: Create a stage operationId: createWorkflowStage tags: [Workflows] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string history_mode: type: string enum: [full, summary, fresh] stage_mode: type: string enum: [custom, form_only, form_chat, review] form_template: type: object transition_rules: type: object responses: '201': description: Stage created content: application/json: schema: $ref: '#/components/schemas/Stage' /api/v1/workflows/{id}/stages/{sid}: put: summary: Update a stage operationId: updateWorkflowStage tags: [Workflows] parameters: - $ref: '#/components/parameters/idPath' - name: sid in: path required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: type: object properties: name: type: string history_mode: type: string enum: [full, summary, fresh] stage_mode: type: string enum: [custom, form_only, form_chat, review] form_template: type: object transition_rules: type: object responses: '200': description: Updated stage content: application/json: schema: $ref: '#/components/schemas/Stage' delete: summary: Delete a stage operationId: deleteWorkflowStage tags: [Workflows] parameters: - $ref: '#/components/parameters/idPath' - name: sid in: path required: true schema: type: string format: uuid responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean /api/v1/workflows/{id}/stages/reorder: patch: summary: Reorder workflow stages operationId: reorderWorkflowStages tags: [Workflows] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object required: [order] properties: order: type: array items: type: string format: uuid responses: '200': description: Reordered content: application/json: schema: type: object properties: ok: type: boolean /api/v1/workflows/{id}/publish: post: summary: Publish a workflow version operationId: publishWorkflow tags: [Workflows] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Published content: application/json: schema: $ref: '#/components/schemas/WorkflowVersion' /api/v1/workflows/{id}/versions/{version}: get: summary: Get a specific workflow version operationId: getWorkflowVersion tags: [Workflows] parameters: - $ref: '#/components/parameters/idPath' - name: version in: path required: true schema: type: integer responses: '200': description: Version snapshot content: application/json: schema: $ref: '#/components/schemas/WorkflowVersion' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' # ────────────────────────────────────────────── # Workflow Clone (v0.3.5) # ────────────────────────────────────────────── /api/v1/workflows/{id}/clone: post: summary: Deep-copy a workflow and its stages operationId: cloneWorkflow tags: [Workflows] parameters: - $ref: '#/components/parameters/idPath' responses: '201': description: Cloned workflow content: application/json: schema: $ref: '#/components/schemas/Workflow' # ────────────────────────────────────────────── # Workflow Instances (v0.3.2) # ────────────────────────────────────────────── /api/v1/workflows/{id}/instances: post: summary: Start a new workflow instance operationId: startInstance tags: [Workflow Instances] parameters: - $ref: '#/components/parameters/idPath' requestBody: content: application/json: schema: type: object properties: stage_data: type: object responses: '201': description: Instance created content: application/json: schema: $ref: '#/components/schemas/WorkflowInstance' get: summary: List instances for a workflow operationId: listInstances tags: [Workflow Instances] parameters: - $ref: '#/components/parameters/idPath' - name: status in: query schema: type: string enum: [active, completed, cancelled, stale] - $ref: '#/components/parameters/limitQuery' - $ref: '#/components/parameters/offsetQuery' responses: '200': description: Instance list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/WorkflowInstance' /api/v1/workflows/{id}/instances/{iid}: get: summary: Get a workflow instance operationId: getInstance tags: [Workflow Instances] parameters: - $ref: '#/components/parameters/idPath' - name: iid in: path required: true schema: type: string format: uuid responses: '200': description: Instance details content: application/json: schema: $ref: '#/components/schemas/WorkflowInstance' /api/v1/workflows/{id}/instances/{iid}/advance: post: summary: Advance an instance to the next stage operationId: advanceInstance tags: [Workflow Instances] parameters: - $ref: '#/components/parameters/idPath' - name: iid in: path required: true schema: type: string format: uuid requestBody: content: application/json: schema: type: object properties: stage_data: type: object responses: '200': description: Advanced instance content: application/json: schema: $ref: '#/components/schemas/WorkflowInstance' /api/v1/workflows/{id}/instances/{iid}/cancel: post: summary: Cancel an active instance operationId: cancelInstance tags: [Workflow Instances] parameters: - $ref: '#/components/parameters/idPath' - name: iid in: path required: true schema: type: string format: uuid responses: '200': description: Instance cancelled content: application/json: schema: $ref: '#/components/schemas/WorkflowInstance' # ────────────────────────────────────────────── # Workflow Assignments (v0.3.2) # ────────────────────────────────────────────── /api/v1/assignments/{id}/claim: post: summary: Claim an assignment operationId: claimAssignment tags: [Workflow Assignments] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Assignment claimed content: application/json: schema: $ref: '#/components/schemas/WorkflowAssignment' /api/v1/assignments/{id}/unclaim: post: summary: Release a claimed assignment operationId: unclaimAssignment tags: [Workflow Assignments] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Assignment released content: application/json: schema: $ref: '#/components/schemas/WorkflowAssignment' /api/v1/assignments/{id}/complete: post: summary: Complete an assignment operationId: completeAssignment tags: [Workflow Assignments] parameters: - $ref: '#/components/parameters/idPath' requestBody: content: application/json: schema: type: object properties: review_data: type: object responses: '200': description: Assignment completed content: application/json: schema: $ref: '#/components/schemas/WorkflowAssignment' /api/v1/assignments/{id}/cancel: post: summary: Cancel an assignment operationId: cancelAssignment tags: [Workflow Assignments] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Assignment cancelled /api/v1/assignments/mine: get: summary: List my assignments operationId: listMyAssignments tags: [Workflow Assignments] parameters: - name: status in: query schema: type: string enum: [unassigned, claimed, completed, cancelled] responses: '200': description: Assignment list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/WorkflowAssignment' # ────────────────────────────────────────────── # Workflow Signoffs (v0.3.4) # ────────────────────────────────────────────── /api/v1/instances/{iid}/signoffs: post: summary: Submit a signoff (approve or reject) operationId: submitSignoff tags: [Workflow Signoffs] parameters: - name: iid in: path required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: type: object required: [decision] properties: decision: type: string enum: [approve, reject] comment: type: string responses: '201': description: Signoff recorded content: application/json: schema: $ref: '#/components/schemas/WorkflowSignoff' get: summary: List signoffs for an instance operationId: listSignoffs tags: [Workflow Signoffs] parameters: - name: iid in: path required: true schema: type: string format: uuid responses: '200': description: Signoff list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/WorkflowSignoff' # ────────────────────────────────────────────── # Public Workflows (v0.3.3) # ────────────────────────────────────────────── /api/v1/public/workflows/{id}/start: post: summary: Start a public workflow instance (no auth required) operationId: startPublicInstance tags: [Public Workflows] security: [] parameters: - $ref: '#/components/parameters/idPath' requestBody: content: application/json: schema: type: object properties: stage_data: type: object responses: '201': description: Public instance created (includes entry_token) content: application/json: schema: $ref: '#/components/schemas/WorkflowInstance' /api/v1/public/workflows/resume/{token}: get: summary: Resume a public instance by entry token operationId: resumePublicInstance tags: [Public Workflows] security: [] parameters: - name: token in: path required: true schema: type: string responses: '200': description: Instance details content: application/json: schema: $ref: '#/components/schemas/WorkflowInstance' /api/v1/public/workflows/advance/{token}: post: summary: Advance a public instance (public-audience stages only) operationId: advancePublicInstance tags: [Public Workflows] security: [] parameters: - name: token in: path required: true schema: type: string requestBody: content: application/json: schema: type: object properties: stage_data: type: object responses: '200': description: Advanced instance content: application/json: schema: $ref: '#/components/schemas/WorkflowInstance' # ────────────────────────────────────────────── # Team Roles (v0.3.4) # ────────────────────────────────────────────── /api/v1/teams/{teamId}/roles: get: summary: List custom roles for a team operationId: listTeamRoles tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' responses: '200': description: Role list content: application/json: schema: type: object properties: data: type: array items: type: string put: summary: Set custom roles for a team operationId: setTeamRoles tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' requestBody: required: true content: application/json: schema: type: object properties: roles: type: array items: type: string responses: '200': description: Roles updated # ────────────────────────────────────────────── # Packages (user-scoped) # ────────────────────────────────────────────── /api/v1/surfaces: get: summary: List installed surfaces operationId: listSurfaces tags: [Packages] responses: '200': description: Surface list content: application/json: schema: type: object properties: data: type: array items: type: object properties: id: type: string format: uuid title: type: string route: type: string /api/v1/packages: get: summary: List packages visible to current user operationId: listPackages tags: [Packages] responses: '200': description: Package list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Package' /api/v1/packages/install: post: summary: Install a package (personal scope) operationId: installPackage tags: [Packages] requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary responses: '201': description: Package installed content: application/json: schema: type: object properties: id: type: string format: uuid title: type: string type: type: string version: type: string scope: type: string source: type: string /api/v1/packages/{id}: delete: summary: Uninstall a package operationId: deletePackage tags: [Packages] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean # ────────────────────────────────────────────── # Connection Types # ────────────────────────────────────────────── /api/v1/connection-types: get: summary: List available connection types operationId: listConnectionTypes tags: [Connections] responses: '200': description: Connection type list content: application/json: schema: type: object properties: data: type: array items: type: object properties: type: type: string label: type: string package_id: type: string format: uuid package_title: type: string fields: type: array items: type: object scopes: type: array items: type: string # ────────────────────────────────────────────── # Connections (personal) # ────────────────────────────────────────────── /api/v1/connections: get: summary: List personal connections operationId: listConnections tags: [Connections] responses: '200': description: Connection list content: application/json: schema: type: object properties: data: type: array items: type: object post: summary: Create a personal connection operationId: createConnection tags: [Connections] requestBody: required: true content: application/json: schema: type: object required: [type, name, credentials] properties: type: type: string name: type: string credentials: type: object responses: '201': description: Connection created content: application/json: schema: type: object /api/v1/connections/resolve: get: summary: Resolve a connection by type and optional name operationId: resolveConnection tags: [Connections] parameters: - name: type in: query required: true schema: type: string - name: name in: query schema: type: string responses: '200': description: Resolved connection content: application/json: schema: type: object /api/v1/connections/{id}: get: summary: Get a connection operationId: getConnection tags: [Connections] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Connection detail content: application/json: schema: type: object put: summary: Update a connection operationId: updateConnection tags: [Connections] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object properties: name: type: string credentials: type: object responses: '200': description: Updated connection content: application/json: schema: type: object delete: summary: Delete a connection operationId: deleteConnection tags: [Connections] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean # ────────────────────────────────────────────── # Extensions (user-scoped) # ────────────────────────────────────────────── /api/v1/extensions: get: summary: List extensions visible to current user operationId: listExtensions tags: [Extensions] parameters: - name: tier in: query schema: type: string responses: '200': description: Extension list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Extension' /api/v1/extensions/{id}/settings: post: summary: Update extension settings for current user operationId: updateExtensionSettings tags: [Extensions] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object properties: settings: type: object is_enabled: type: boolean responses: '200': description: Settings updated content: application/json: schema: type: object /api/v1/extensions/{id}/manifest: get: summary: Get extension manifest operationId: getExtensionManifest tags: [Extensions] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Extension manifest content: application/json: schema: type: object /api/v1/extensions/tools: get: summary: List all extension tools operationId: listExtensionTools tags: [Extensions] responses: '200': description: Tool list content: application/json: schema: type: object properties: data: type: array items: type: object # ────────────────────────────────────────────── # Team-scoped endpoints # ────────────────────────────────────────────── /api/v1/teams/{teamId}/members: get: summary: List team members operationId: listTeamMembers tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' responses: '200': description: Team member list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/TeamMember' post: summary: Add a team member operationId: addTeamMember tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' requestBody: required: true content: application/json: schema: type: object required: [user_id] properties: user_id: type: string format: uuid role: type: string enum: [admin, member] responses: '201': description: Member added content: application/json: schema: $ref: '#/components/schemas/TeamMember' /api/v1/teams/{teamId}/members/{memberId}: put: summary: Update team member role operationId: updateTeamMember tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' - name: memberId in: path required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: type: object required: [role] properties: role: type: string enum: [admin, member] responses: '200': description: Member updated content: application/json: schema: $ref: '#/components/schemas/TeamMember' delete: summary: Remove team member operationId: removeTeamMember tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' - name: memberId in: path required: true schema: type: string format: uuid responses: '200': description: Member removed content: application/json: schema: type: object properties: removed: type: boolean /api/v1/teams/{teamId}/groups: get: summary: List groups in a team operationId: listTeamGroups tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' responses: '200': description: Team group list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Group' /api/v1/teams/{teamId}/connections: get: summary: List team connections operationId: listTeamConnections tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' responses: '200': description: Team connection list content: application/json: schema: type: object properties: data: type: array items: type: object post: summary: Create a team connection operationId: createTeamConnection tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' requestBody: required: true content: application/json: schema: type: object required: [type, name, credentials] properties: type: type: string name: type: string credentials: type: object responses: '201': description: Connection created content: application/json: schema: type: object /api/v1/teams/{teamId}/connections/{id}: put: summary: Update a team connection operationId: updateTeamConnection tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object properties: name: type: string credentials: type: object responses: '200': description: Updated content: application/json: schema: type: object delete: summary: Delete a team connection operationId: deleteTeamConnection tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean /api/v1/teams/{teamId}/packages/install: post: summary: Install a package into a team operationId: installTeamPackage tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary responses: '201': description: Package installed content: application/json: schema: type: object /api/v1/teams/{teamId}/packages/{id}: delete: summary: Uninstall a team package operationId: deleteTeamPackage tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean /api/v1/teams/{teamId}/packages/{id}/settings: get: summary: Get team package settings operationId: getTeamPackageSettings tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' responses: '200': description: Package settings content: application/json: schema: type: object put: summary: Update team package settings operationId: updateTeamPackageSettings tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object responses: '200': description: Updated settings content: application/json: schema: type: object delete: summary: Delete team package settings operationId: deleteTeamPackageSettings tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: ok: type: boolean /api/v1/teams/{teamId}/audit: get: summary: List team audit log operationId: listTeamAuditLog tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/pageParam' - $ref: '#/components/parameters/perPageParam' - name: action in: query schema: type: string - name: actor_id in: query schema: type: string format: uuid - name: resource_type in: query schema: type: string responses: '200': description: Audit log entries content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/AuditEntry' page: type: integer per_page: type: integer total: type: integer /api/v1/teams/{teamId}/audit/actions: get: summary: List available audit actions for team operationId: listTeamAuditActions tags: [Teams] parameters: - $ref: '#/components/parameters/teamIdPath' responses: '200': description: Audit action list content: application/json: schema: type: object properties: data: type: array items: type: string # Team Workflows /api/v1/teams/{teamId}/workflows: get: summary: List team workflows operationId: listTeamWorkflows tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' responses: '200': description: Team workflow list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Workflow' post: summary: Create a team workflow operationId: createTeamWorkflow tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string entry_mode: type: string enum: [public_link, team_only] responses: '201': description: Workflow created content: application/json: schema: $ref: '#/components/schemas/Workflow' /api/v1/teams/{teamId}/workflows/{id}: get: summary: Get a team workflow operationId: getTeamWorkflow tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' responses: '200': description: Workflow detail content: application/json: schema: $ref: '#/components/schemas/Workflow' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' patch: summary: Update a team workflow operationId: updateTeamWorkflow tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object properties: name: type: string entry_mode: type: string enum: [public_link, team_only] responses: '200': description: Updated workflow content: application/json: schema: $ref: '#/components/schemas/Workflow' delete: summary: Delete a team workflow operationId: deleteTeamWorkflow tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean /api/v1/teams/{teamId}/workflows/{id}/stages: get: summary: List stages for a team workflow operationId: listTeamWorkflowStages tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' responses: '200': description: Stage list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Stage' post: summary: Create a team workflow stage operationId: createTeamWorkflowStage tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string history_mode: type: string enum: [full, summary, fresh] stage_mode: type: string enum: [custom, form_only, form_chat, review] form_template: type: object transition_rules: type: object responses: '201': description: Stage created content: application/json: schema: $ref: '#/components/schemas/Stage' /api/v1/teams/{teamId}/workflows/{id}/stages/{sid}: put: summary: Update a team workflow stage operationId: updateTeamWorkflowStage tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' - name: sid in: path required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: type: object properties: name: type: string history_mode: type: string enum: [full, summary, fresh] stage_mode: type: string enum: [custom, form_only, form_chat, review] form_template: type: object transition_rules: type: object responses: '200': description: Updated stage content: application/json: schema: $ref: '#/components/schemas/Stage' delete: summary: Delete a team workflow stage operationId: deleteTeamWorkflowStage tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' - name: sid in: path required: true schema: type: string format: uuid responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean /api/v1/teams/{teamId}/workflows/{id}/stages/reorder: patch: summary: Reorder team workflow stages operationId: reorderTeamWorkflowStages tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object required: [order] properties: order: type: array items: type: string format: uuid responses: '200': description: Reordered content: application/json: schema: type: object properties: ok: type: boolean /api/v1/teams/{teamId}/workflows/{id}/publish: post: summary: Publish a team workflow version operationId: publishTeamWorkflow tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' responses: '200': description: Published content: application/json: schema: $ref: '#/components/schemas/WorkflowVersion' /api/v1/teams/{teamId}/workflows/{id}/versions/{version}: get: summary: Get a specific team workflow version operationId: getTeamWorkflowVersion tags: [Workflows] parameters: - $ref: '#/components/parameters/teamIdPath' - $ref: '#/components/parameters/idPath' - name: version in: path required: true schema: type: integer responses: '200': description: Version snapshot content: application/json: schema: $ref: '#/components/schemas/WorkflowVersion' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' # ────────────────────────────────────────────── # Admin: Users # ────────────────────────────────────────────── /api/v1/admin/users: get: summary: List all users operationId: adminListUsers tags: ['Admin: Users'] responses: '200': description: User list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/User' post: summary: Create a user operationId: adminCreateUser tags: ['Admin: Users'] requestBody: required: true content: application/json: schema: type: object required: [username, email, password] properties: username: type: string email: type: string password: type: string display_name: type: string responses: '201': description: User created content: application/json: schema: $ref: '#/components/schemas/User' /api/v1/admin/users/{id}/role: put: summary: Update user role operationId: adminUpdateUserRole tags: ['Admin: Users'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object required: [role] properties: role: type: string responses: '200': description: Role updated content: application/json: schema: type: object /api/v1/admin/users/{id}/active: put: summary: Activate or deactivate a user operationId: adminSetUserActive tags: ['Admin: Users'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object required: [is_active] properties: is_active: type: boolean responses: '200': description: Status updated content: application/json: schema: type: object /api/v1/admin/users/{id}/reset-password: post: summary: Reset user password operationId: adminResetUserPassword tags: ['Admin: Users'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object required: [new_password] properties: new_password: type: string responses: '200': description: Password reset content: application/json: schema: type: object properties: message: type: string /api/v1/admin/users/{id}/vault/reset: post: summary: Reset user vault operationId: adminResetUserVault tags: ['Admin: Users'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Vault reset content: application/json: schema: type: object properties: message: type: string /api/v1/admin/users/{id}: delete: summary: Delete a user operationId: adminDeleteUser tags: ['Admin: Users'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean # ────────────────────────────────────────────── # Admin: Settings # ────────────────────────────────────────────── /api/v1/admin/settings: get: summary: List all settings operationId: adminListSettings tags: ['Admin: Settings'] responses: '200': description: All settings content: application/json: schema: type: object /api/v1/admin/settings/{key}: get: summary: Get a setting by key operationId: adminGetSetting tags: ['Admin: Settings'] parameters: - name: key in: path required: true schema: type: string responses: '200': description: Setting value content: application/json: schema: type: object put: summary: Update a setting by key operationId: adminUpdateSetting tags: ['Admin: Settings'] parameters: - name: key in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: [value] properties: value: {} responses: '200': description: Setting updated content: application/json: schema: type: object # ────────────────────────────────────────────── # Admin: Stats # ────────────────────────────────────────────── /api/v1/admin/stats: get: summary: Get system statistics operationId: adminGetStats tags: ['Admin: System'] responses: '200': description: System stats content: application/json: schema: type: object properties: users: type: integer # ────────────────────────────────────────────── # Admin: Connections # ────────────────────────────────────────────── /api/v1/admin/connections: get: summary: List all connections operationId: adminListConnections tags: ['Admin: Connections'] responses: '200': description: Connection list content: application/json: schema: type: object properties: data: type: array items: type: object post: summary: Create a global connection operationId: adminCreateConnection tags: ['Admin: Connections'] requestBody: required: true content: application/json: schema: type: object required: [type, name, credentials] properties: type: type: string name: type: string credentials: type: object responses: '201': description: Connection created content: application/json: schema: type: object /api/v1/admin/connections/{id}: put: summary: Update a global connection operationId: adminUpdateConnection tags: ['Admin: Connections'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object properties: name: type: string credentials: type: object responses: '200': description: Updated content: application/json: schema: type: object delete: summary: Delete a global connection operationId: adminDeleteConnection tags: ['Admin: Connections'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean # ────────────────────────────────────────────── # Admin: Teams # ────────────────────────────────────────────── /api/v1/admin/teams: get: summary: List all teams operationId: adminListTeams tags: ['Admin: Teams'] responses: '200': description: Team list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Team' post: summary: Create a team operationId: adminCreateTeam tags: ['Admin: Teams'] requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string description: type: string responses: '201': description: Team created content: application/json: schema: $ref: '#/components/schemas/Team' /api/v1/admin/teams/{id}: get: summary: Get a team operationId: adminGetTeam tags: ['Admin: Teams'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Team detail content: application/json: schema: $ref: '#/components/schemas/Team' put: summary: Update a team operationId: adminUpdateTeam tags: ['Admin: Teams'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: type: string is_active: type: boolean responses: '200': description: Updated content: application/json: schema: $ref: '#/components/schemas/Team' delete: summary: Delete a team operationId: adminDeleteTeam tags: ['Admin: Teams'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean /api/v1/admin/teams/{id}/members: get: summary: List members of a team (admin) operationId: adminListTeamMembers tags: ['Admin: Teams'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Member list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/TeamMember' post: summary: Add member to a team (admin) operationId: adminAddTeamMember tags: ['Admin: Teams'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object required: [user_id] properties: user_id: type: string format: uuid role: type: string enum: [admin, member] responses: '201': description: Member added content: application/json: schema: $ref: '#/components/schemas/TeamMember' /api/v1/admin/teams/{id}/members/{memberId}: put: summary: Update team member role (admin) operationId: adminUpdateTeamMember tags: ['Admin: Teams'] parameters: - $ref: '#/components/parameters/idPath' - name: memberId in: path required: true schema: type: string format: uuid requestBody: required: true content: application/json: schema: type: object required: [role] properties: role: type: string enum: [admin, member] responses: '200': description: Updated content: application/json: schema: $ref: '#/components/schemas/TeamMember' delete: summary: Remove team member (admin) operationId: adminRemoveTeamMember tags: ['Admin: Teams'] parameters: - $ref: '#/components/parameters/idPath' - name: memberId in: path required: true schema: type: string format: uuid responses: '200': description: Removed content: application/json: schema: type: object properties: removed: type: boolean # ────────────────────────────────────────────── # Admin: Notifications # ────────────────────────────────────────────── /api/v1/admin/notifications/broadcast: post: summary: Broadcast a notification to all users operationId: adminBroadcastNotification tags: ['Admin: System'] requestBody: required: true content: application/json: schema: type: object required: [title, message] properties: title: type: string message: type: string level: type: string responses: '200': description: Broadcast sent content: application/json: schema: type: object properties: message: type: string count: type: integer # ────────────────────────────────────────────── # Admin: Audit # ────────────────────────────────────────────── /api/v1/admin/audit: get: summary: List global audit log operationId: adminListAuditLog tags: ['Admin: System'] parameters: - $ref: '#/components/parameters/pageParam' - $ref: '#/components/parameters/perPageParam' - name: action in: query schema: type: string - name: actor_id in: query schema: type: string format: uuid - name: resource_type in: query schema: type: string responses: '200': description: Audit log entries content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/AuditEntry' page: type: integer per_page: type: integer total: type: integer /api/v1/admin/audit/actions: get: summary: List available audit actions operationId: adminListAuditActions tags: ['Admin: System'] responses: '200': description: Audit action list content: application/json: schema: type: object properties: data: type: array items: type: string # ────────────────────────────────────────────── # Admin: Groups # ────────────────────────────────────────────── /api/v1/admin/groups: get: summary: List all groups operationId: adminListGroups tags: ['Admin: Groups'] responses: '200': description: Group list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Group' post: summary: Create a group operationId: adminCreateGroup tags: ['Admin: Groups'] requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string description: type: string scope: type: string enum: [global, team] team_id: type: string format: uuid permissions: type: array items: type: string responses: '201': description: Group created content: application/json: schema: $ref: '#/components/schemas/Group' /api/v1/admin/groups/{id}: get: summary: Get a group operationId: adminGetGroup tags: ['Admin: Groups'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Group detail content: application/json: schema: $ref: '#/components/schemas/Group' put: summary: Update a group operationId: adminUpdateGroup tags: ['Admin: Groups'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: type: string permissions: type: array items: type: string responses: '200': description: Updated content: application/json: schema: $ref: '#/components/schemas/Group' delete: summary: Delete a group operationId: adminDeleteGroup tags: ['Admin: Groups'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean /api/v1/admin/groups/{id}/members: get: summary: List group members operationId: adminListGroupMembers tags: ['Admin: Groups'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Member list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/GroupMember' post: summary: Add member to a group operationId: adminAddGroupMember tags: ['Admin: Groups'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object required: [user_id] properties: user_id: type: string format: uuid responses: '201': description: Member added content: application/json: schema: $ref: '#/components/schemas/GroupMember' /api/v1/admin/groups/{id}/members/{userId}: delete: summary: Remove member from a group operationId: adminRemoveGroupMember tags: ['Admin: Groups'] parameters: - $ref: '#/components/parameters/idPath' - name: userId in: path required: true schema: type: string format: uuid responses: '200': description: Removed content: application/json: schema: type: object properties: removed: type: boolean # ────────────────────────────────────────────── # Admin: Permissions # ────────────────────────────────────────────── /api/v1/admin/permissions: get: summary: List all available permissions operationId: adminListPermissions tags: ['Admin: Permissions'] responses: '200': description: Permission list content: application/json: schema: type: object properties: permissions: type: array items: type: string /api/v1/admin/users/{id}/permissions: get: summary: Get effective permissions for a user operationId: adminGetUserPermissions tags: ['Admin: Permissions'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: User permissions content: application/json: schema: type: object properties: permissions: type: array items: type: string user_id: type: string format: uuid groups: type: array items: type: object # ────────────────────────────────────────────── # Admin: Grants # ────────────────────────────────────────────── /api/v1/admin/grants/{type}/{id}: get: summary: Get grant for a resource operationId: adminGetGrant tags: ['Admin: Permissions'] parameters: - name: type in: path required: true schema: type: string - $ref: '#/components/parameters/idPath' responses: '200': description: Resource grant content: application/json: schema: $ref: '#/components/schemas/ResourceGrant' put: summary: Set grant for a resource operationId: adminSetGrant tags: ['Admin: Permissions'] parameters: - name: type in: path required: true schema: type: string - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object required: [grant_scope] properties: grant_scope: type: string enum: [team_only, global, groups] granted_groups: type: array items: type: string responses: '200': description: Grant updated content: application/json: schema: $ref: '#/components/schemas/ResourceGrant' delete: summary: Delete grant for a resource operationId: adminDeleteGrant tags: ['Admin: Permissions'] parameters: - name: type in: path required: true schema: type: string - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean # ────────────────────────────────────────────── # Admin: Storage # ────────────────────────────────────────────── /api/v1/admin/storage/status: get: summary: Get storage backend status operationId: adminGetStorageStatus tags: ['Admin: System'] responses: '200': description: Storage status content: application/json: schema: type: object properties: backend: type: string configured: type: boolean healthy: type: boolean # ────────────────────────────────────────────── # Admin: Vault # ────────────────────────────────────────────── /api/v1/admin/vault/status: get: summary: Get vault status operationId: adminGetVaultStatus tags: ['Admin: System'] responses: '200': description: Vault status content: application/json: schema: type: object # ────────────────────────────────────────────── # Admin: Email # ────────────────────────────────────────────── /api/v1/admin/notifications/test-email: post: summary: Send a test email operationId: adminSendTestEmail tags: ['Admin: System'] responses: '200': description: Test email sent content: application/json: schema: type: object properties: ok: type: boolean sent_to: type: string # ────────────────────────────────────────────── # Admin: Extensions # ────────────────────────────────────────────── /api/v1/admin/extensions: get: summary: List all extensions (admin) operationId: adminListExtensions tags: ['Admin: Extensions'] responses: '200': description: Extension list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Extension' post: summary: Register an extension (admin) operationId: adminCreateExtension tags: ['Admin: Extensions'] requestBody: required: true content: application/json: schema: type: object responses: '201': description: Extension registered content: application/json: schema: $ref: '#/components/schemas/Extension' /api/v1/admin/extensions/{id}: put: summary: Update an extension (admin) operationId: adminUpdateExtension tags: ['Admin: Extensions'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object responses: '200': description: Updated content: application/json: schema: $ref: '#/components/schemas/Extension' delete: summary: Delete an extension (admin) operationId: adminDeleteExtension tags: ['Admin: Extensions'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean # ────────────────────────────────────────────── # Admin: Extension Permissions # ────────────────────────────────────────────── /api/v1/admin/extensions/{id}/permissions: get: summary: List permissions for an extension operationId: adminListExtensionPermissions tags: ['Admin: Extensions'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Extension permissions content: application/json: schema: type: object /api/v1/admin/extensions/{id}/review: get: summary: Get extension permission review operationId: adminReviewExtensionPermissions tags: ['Admin: Extensions'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Permission review content: application/json: schema: type: object /api/v1/admin/extensions/{id}/permissions/{perm}/grant: post: summary: Grant a permission to an extension operationId: adminGrantExtensionPermission tags: ['Admin: Extensions'] parameters: - $ref: '#/components/parameters/idPath' - name: perm in: path required: true schema: type: string responses: '200': description: Permission granted content: application/json: schema: type: object /api/v1/admin/extensions/{id}/permissions/{perm}/revoke: post: summary: Revoke a permission from an extension operationId: adminRevokeExtensionPermission tags: ['Admin: Extensions'] parameters: - $ref: '#/components/parameters/idPath' - name: perm in: path required: true schema: type: string responses: '200': description: Permission revoked content: application/json: schema: type: object /api/v1/admin/extensions/{id}/permissions/grant-all: post: summary: Grant all permissions to an extension operationId: adminGrantAllExtensionPermissions tags: ['Admin: Extensions'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: All permissions granted content: application/json: schema: type: object # ────────────────────────────────────────────── # Admin: Extension Secrets # ────────────────────────────────────────────── /api/v1/admin/extensions/{id}/secrets: get: summary: Get extension secrets operationId: adminGetExtensionSecrets tags: ['Admin: Extensions'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Extension secrets content: application/json: schema: type: object put: summary: Update extension secrets operationId: adminUpdateExtensionSecrets tags: ['Admin: Extensions'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object responses: '200': description: Secrets updated content: application/json: schema: type: object delete: summary: Delete extension secrets operationId: adminDeleteExtensionSecrets tags: ['Admin: Extensions'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Secrets deleted content: application/json: schema: type: object properties: deleted: type: boolean # ────────────────────────────────────────────── # Admin: Packages # ────────────────────────────────────────────── /api/v1/admin/packages/registry: get: summary: List registry packages operationId: adminListRegistryPackages tags: ['Admin: Packages'] responses: '200': description: Registry package list content: application/json: schema: type: object properties: data: type: array items: type: object /api/v1/admin/packages/registry/install: post: summary: Install a package from registry operationId: adminInstallRegistryPackage tags: ['Admin: Packages'] requestBody: required: true content: application/json: schema: type: object required: [package_id] properties: package_id: type: string responses: '201': description: Package installed from registry content: application/json: schema: type: object /api/v1/admin/packages: get: summary: List all installed packages (admin) operationId: adminListPackages tags: ['Admin: Packages'] responses: '200': description: Package list content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Package' /api/v1/admin/packages/{id}: get: summary: Get a package (admin) operationId: adminGetPackage tags: ['Admin: Packages'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Package detail content: application/json: schema: $ref: '#/components/schemas/Package' delete: summary: Delete a package (admin) operationId: adminDeletePackage tags: ['Admin: Packages'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted content: application/json: schema: type: object properties: deleted: type: boolean /api/v1/admin/packages/install: post: summary: Install a package (admin, multipart) operationId: adminInstallPackage tags: ['Admin: Packages'] requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary responses: '201': description: Package installed content: application/json: schema: type: object /api/v1/admin/packages/{id}/enable: put: summary: Enable a package operationId: adminEnablePackage tags: ['Admin: Packages'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Package enabled content: application/json: schema: type: object /api/v1/admin/packages/{id}/disable: put: summary: Disable a package operationId: adminDisablePackage tags: ['Admin: Packages'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Package disabled content: application/json: schema: type: object /api/v1/admin/packages/{id}/settings: get: summary: Get package settings (admin) operationId: adminGetPackageSettings tags: ['Admin: Packages'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Package settings content: application/json: schema: type: object put: summary: Update package settings (admin) operationId: adminUpdatePackageSettings tags: ['Admin: Packages'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object responses: '200': description: Settings updated content: application/json: schema: type: object /api/v1/admin/packages/{id}/dependencies: get: summary: Get package dependencies operationId: adminGetPackageDependencies tags: ['Admin: Packages'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Package dependencies content: application/json: schema: type: object properties: data: type: array items: type: object /api/v1/admin/packages/{id}/consumers: get: summary: Get package consumers operationId: adminGetPackageConsumers tags: ['Admin: Packages'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Package consumers content: application/json: schema: type: object properties: data: type: array items: type: object /api/v1/admin/packages/{id}/test-tool: post: summary: Test a package tool operationId: adminTestPackageTool tags: ['Admin: Packages'] parameters: - $ref: '#/components/parameters/idPath' requestBody: required: true content: application/json: schema: type: object responses: '200': description: Tool test result content: application/json: schema: type: object /api/v1/admin/dependencies: get: summary: Get global dependency graph operationId: adminGetDependencies tags: ['Admin: Packages'] responses: '200': description: Dependency graph content: application/json: schema: type: object # ────────────────────────────────────────────── # Admin: Workflows # ────────────────────────────────────────────── /api/v1/admin/workflows/{id}/export: get: summary: Export a workflow as a zip archive operationId: adminExportWorkflow tags: ['Admin: Workflows'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Workflow zip archive content: application/zip: schema: type: string format: binary '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' # ────────────────────────────────────────────── # Webhook Inbound (v0.2.2) # ────────────────────────────────────────────── /api/v1/hooks/{package_id}/{slug}: post: summary: Inbound webhook trigger description: Public endpoint. HMAC-SHA256 verified via X-Switchboard-Signature header. operationId: webhookInbound tags: [Triggers] security: [] parameters: - name: package_id in: path required: true schema: { type: string } - name: slug in: path required: true schema: { type: string } requestBody: content: application/json: schema: { type: object } responses: '200': description: Webhook processed content: application/json: schema: { type: object } '401': description: Invalid signature '404': description: Webhook not found # ────────────────────────────────────────────── # Scheduled Tasks — User (v0.2.2) # ────────────────────────────────────────────── /api/v1/schedules: get: summary: List my scheduled tasks operationId: listMySchedules tags: [Schedules] responses: '200': description: Schedules list content: application/json: schema: type: object properties: schedules: type: array items: { $ref: '#/components/schemas/ScheduledTask' } post: summary: Create a scheduled task operationId: createSchedule tags: [Schedules] requestBody: required: true content: application/json: schema: type: object required: [name, cron_expr] properties: name: { type: string } description: { type: string } cron_expr: { type: string, example: '0 9 * * 1-5' } script: { type: string } template_id: { type: string } template_params: { type: object } responses: '201': description: Created content: application/json: schema: { $ref: '#/components/schemas/ScheduledTask' } /api/v1/schedules/{id}: get: summary: Get a scheduled task operationId: getSchedule tags: [Schedules] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Schedule details content: application/json: schema: { $ref: '#/components/schemas/ScheduledTask' } put: summary: Update a scheduled task operationId: updateSchedule tags: [Schedules] parameters: - $ref: '#/components/parameters/idPath' requestBody: content: application/json: schema: type: object properties: name: { type: string } description: { type: string } cron_expr: { type: string } script: { type: string } enabled: { type: boolean } responses: '200': description: Updated delete: summary: Delete a scheduled task operationId: deleteSchedule tags: [Schedules] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted /api/v1/schedules/{id}/run: post: summary: Manually trigger a scheduled task operationId: runSchedule tags: [Schedules] parameters: - $ref: '#/components/parameters/idPath' responses: '202': description: Task queued /api/v1/schedules/{id}/logs: get: summary: List execution logs for a scheduled task operationId: listScheduleLogs tags: [Schedules] parameters: - $ref: '#/components/parameters/idPath' - name: limit in: query schema: { type: integer, default: 50 } responses: '200': description: Execution logs content: application/json: schema: type: object properties: logs: type: array items: { $ref: '#/components/schemas/TriggerLog' } # ────────────────────────────────────────────── # Admin: Triggers (v0.2.2) # ────────────────────────────────────────────── /api/v1/admin/triggers: get: summary: List all extension triggers operationId: adminListTriggers tags: ['Admin: Triggers'] parameters: - name: package_id in: query schema: { type: string } - name: type in: query schema: { type: string, enum: [webhook, event] } - name: enabled in: query schema: { type: string, enum: ['true', 'false'] } - name: limit in: query schema: { type: integer, default: 50 } - name: offset in: query schema: { type: integer, default: 0 } responses: '200': description: Trigger list content: application/json: schema: type: object properties: triggers: type: array items: { $ref: '#/components/schemas/Trigger' } total: { type: integer } /api/v1/admin/triggers/{id}: get: summary: Get a single trigger operationId: adminGetTrigger tags: ['Admin: Triggers'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Trigger details content: application/json: schema: { $ref: '#/components/schemas/Trigger' } delete: summary: Delete a trigger operationId: adminDeleteTrigger tags: ['Admin: Triggers'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted /api/v1/admin/triggers/{id}/enable: put: summary: Enable a trigger operationId: adminEnableTrigger tags: ['Admin: Triggers'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Enabled /api/v1/admin/triggers/{id}/disable: put: summary: Disable a trigger operationId: adminDisableTrigger tags: ['Admin: Triggers'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Disabled /api/v1/admin/triggers/{id}/logs: get: summary: List trigger execution logs operationId: adminListTriggerLogs tags: ['Admin: Triggers'] parameters: - $ref: '#/components/parameters/idPath' - name: limit in: query schema: { type: integer, default: 50 } responses: '200': description: Execution logs content: application/json: schema: type: object properties: logs: type: array items: { $ref: '#/components/schemas/TriggerLog' } /api/v1/admin/packages/{id}/triggers: get: summary: List triggers for a package operationId: adminListPackageTriggers tags: ['Admin: Triggers'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Package triggers content: application/json: schema: type: object properties: triggers: type: array items: { $ref: '#/components/schemas/Trigger' } # ────────────────────────────────────────────── # Admin: Schedules (v0.2.2) # ────────────────────────────────────────────── /api/v1/admin/schedules: get: summary: List all scheduled tasks (admin view) operationId: adminListSchedules tags: ['Admin: Schedules'] parameters: - name: creator_id in: query schema: { type: string } - name: enabled in: query schema: { type: string, enum: ['true', 'false'] } - name: limit in: query schema: { type: integer, default: 50 } - name: offset in: query schema: { type: integer, default: 0 } responses: '200': description: Schedules list content: application/json: schema: type: object properties: schedules: type: array items: { $ref: '#/components/schemas/ScheduledTask' } total: { type: integer } /api/v1/admin/schedules/{id}/enable: put: summary: Enable a scheduled task operationId: adminEnableSchedule tags: ['Admin: Schedules'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Enabled /api/v1/admin/schedules/{id}/disable: put: summary: Disable a scheduled task operationId: adminDisableSchedule tags: ['Admin: Schedules'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Disabled /api/v1/admin/schedules/{id}: delete: summary: Delete a scheduled task operationId: adminDeleteSchedule tags: ['Admin: Schedules'] parameters: - $ref: '#/components/parameters/idPath' responses: '200': description: Deleted