openapi: 3.0.3 info: title: Kradle API version: 1.0.0 description: | Kubernetes-native Git forge HTTP API. Kradle provides resource management, agent orchestration, external backend sync, secret management, and real-time event streaming for developer platforms built on Kubernetes. contact: name: a5c.ai url: https://a5c.ai license: name: MIT servers: - url: http://localhost:3080 description: Local development server - url: https://kradle.example.com description: Production server tags: - name: Health description: Health and readiness checks - name: Controller description: Controller snapshot and UI model - name: Organizations description: Organization management - name: Resources description: Kubernetes resource CRUD (org-scoped) - name: Secrets description: Secret management (AgentSecretGrant resources) - name: SecretGrants description: Fine-grained secret grant management - name: External description: External backend sync, conflict resolution, and write intents - name: Agents description: Agent dispatch, memory queries, and event streaming - name: Webhooks description: Webhook ingestion for external provider events paths: /healthz: get: tags: [Health] summary: Health check description: Returns 200 OK when the server is healthy and ready to serve requests. operationId: getHealth responses: '200': description: Server is healthy content: application/json: schema: type: object properties: ok: type: boolean example: true project: type: string example: Kradle '500': $ref: '#/components/responses/InternalError' /api/controller: get: tags: [Controller] summary: Get controller UI model description: | Returns a full controller snapshot formatted as a UI model, optionally scoped to a specific organization. Includes resources, org list, agents, status, and dashboard views. operationId: getController parameters: - name: org in: query description: Organization slug to scope the UI model to required: false schema: type: string example: default responses: '200': description: Controller UI model content: application/json: schema: $ref: '#/components/schemas/ControllerUiModel' '500': $ref: '#/components/responses/InternalError' /api/orgs: get: tags: [Organizations] summary: List organizations description: Returns all organizations from the controller snapshot. operationId: listOrganizations responses: '200': description: Organization list content: application/json: schema: type: object properties: organizations: type: array items: $ref: '#/components/schemas/OrgSummary' '500': $ref: '#/components/responses/InternalError' post: tags: [Organizations] summary: Create organization description: Creates a new organization resource. operationId: createOrganization requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string description: Organization slug (DNS-safe label) example: acme displayName: type: string description: Human-readable organization name example: Acme Corp responses: '201': description: Organization created content: application/json: schema: $ref: '#/components/schemas/KradleResource' '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/resources: get: tags: [Resources] summary: List resources by kind description: | Lists all resources of the specified kind within the organization's namespace. Defaults to 'Repository' if kind is not specified. operationId: listResources parameters: - $ref: '#/components/parameters/OrgParam' - name: kind in: query description: Kubernetes resource kind to list (e.g. Repository, AgentStack) required: false schema: type: string example: Repository responses: '200': description: Resource list content: application/json: schema: $ref: '#/components/schemas/ResourceList' '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' post: tags: [Resources] summary: Apply (create or update) a resource description: | Creates or updates a Kubernetes resource in the organization's namespace. The org context is automatically injected into metadata and spec. operationId: applyResource parameters: - $ref: '#/components/parameters/OrgParam' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/KradleResource' example: apiVersion: kradle.a5c.ai/v1alpha1 kind: AgentStack metadata: name: my-stack spec: organizationRef: default description: My agent stack responses: '201': description: Resource applied content: application/json: schema: $ref: '#/components/schemas/ApplyResult' '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/resources/{kind}/{name}: get: tags: [Resources] summary: Get a resource description: Returns a single resource by kind and name within the organization namespace. operationId: getResource parameters: - $ref: '#/components/parameters/OrgParam' - $ref: '#/components/parameters/KindParam' - $ref: '#/components/parameters/NameParam' responses: '200': description: Resource object content: application/json: schema: $ref: '#/components/schemas/KradleResource' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' delete: tags: [Resources] summary: Delete a resource description: Deletes the resource with the given kind and name from the organization namespace. operationId: deleteResource parameters: - $ref: '#/components/parameters/OrgParam' - $ref: '#/components/parameters/KindParam' - $ref: '#/components/parameters/NameParam' responses: '200': description: Resource deleted content: application/json: schema: $ref: '#/components/schemas/DeleteResult' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/secrets: get: tags: [Secrets] summary: List secrets description: | Lists all secrets (AgentSecretGrant resources) for the organization. Returns a simplified view with name, type, createdAt, and grants. operationId: listSecrets parameters: - $ref: '#/components/parameters/OrgParam' responses: '200': description: Secret list content: application/json: schema: type: object properties: secrets: type: array items: $ref: '#/components/schemas/SecretItem' '500': $ref: '#/components/responses/InternalError' post: tags: [Secrets] summary: Create a secret description: | Creates an AgentSecretGrant resource that registers a secret reference with the specified permissions and grant target. operationId: createSecret parameters: - $ref: '#/components/parameters/OrgParam' requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string description: Secret name example: github-token grantedTo: type: string description: Agent or system the secret is granted to example: agent-stack-builder permissions: type: array items: type: string enum: [read, write, admin] default: [read] data: type: object description: Optional secret data (key-value pairs) additionalProperties: type: string responses: '201': description: Secret created content: application/json: schema: $ref: '#/components/schemas/ApplyResult' '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/secrets/{name}: delete: tags: [Secrets] summary: Delete a secret description: Deletes the AgentSecretGrant with the given name from the organization. operationId: deleteSecret parameters: - $ref: '#/components/parameters/OrgParam' - $ref: '#/components/parameters/NameParam' responses: '200': description: Secret deleted content: application/json: schema: $ref: '#/components/schemas/DeleteResult' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/secret-grants: get: tags: [SecretGrants] summary: List secret grants description: Lists all AgentSecretGrant resources for the organization (full resource view). operationId: listSecretGrants parameters: - $ref: '#/components/parameters/OrgParam' responses: '200': description: Secret grant list content: application/json: schema: $ref: '#/components/schemas/ResourceList' '500': $ref: '#/components/responses/InternalError' post: tags: [SecretGrants] summary: Create a secret grant description: | Creates an AgentSecretGrant resource granting a specific agent access to a named secret with the specified permissions. operationId: createSecretGrant parameters: - $ref: '#/components/parameters/OrgParam' requestBody: required: true content: application/json: schema: type: object required: [secretName, grantedTo] properties: name: type: string description: Grant resource name (auto-generated if omitted) example: grant-github-token secretName: type: string description: Name of the secret to grant access to example: github-token grantedTo: type: string description: Agent stack or system receiving the grant example: agent-stack-builder permissions: type: array items: type: string enum: [read, write, admin] default: [read] responses: '201': description: Secret grant created content: application/json: schema: $ref: '#/components/schemas/ApplyResult' '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/external/sync: post: tags: [External] summary: Sync external binding description: | Triggers a synchronization of a named external binding (e.g. GitHub repository adapter). Reconciles local resource state against the external provider. operationId: syncExternal parameters: - $ref: '#/components/parameters/OrgParam' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SyncInput' example: bindingName: github-binding kind: Repository localName: my-repo spec: {} externalEnvelope: nativeId: '123456' url: https://github.com/org/repo etag: abc123 providerRef: github responses: '200': description: Sync result content: application/json: schema: type: object properties: synced: type: boolean resource: $ref: '#/components/schemas/KradleResource' conflicts: type: array items: type: object '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/external/conflicts/{name}/resolve: post: tags: [External] summary: Resolve external conflict description: | Resolves a named external sync conflict using the specified strategy. Strategies: local-wins, remote-wins, or manual (provide resolvedValue). operationId: resolveConflict parameters: - $ref: '#/components/parameters/OrgParam' - name: name in: path required: true description: Conflict resource name schema: type: string example: repo-conflict-abc123 requestBody: required: true content: application/json: schema: type: object required: [strategy] properties: strategy: type: string enum: [local-wins, remote-wins, manual] description: Conflict resolution strategy resolvedValue: type: object description: Merged spec value (required for manual strategy) resources: type: object description: Additional resource context responses: '200': description: Conflict resolved content: application/json: schema: type: object properties: resolved: type: boolean conflictName: type: string strategy: type: string '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/external/write-intents/{name}/approve: post: tags: [External] summary: Approve write intent description: | Approves a pending external write intent, allowing the agent to commit changes to the external provider (e.g. push a branch to GitHub). operationId: approveWriteIntent parameters: - $ref: '#/components/parameters/OrgParam' - name: name in: path required: true description: Write intent resource name schema: type: string example: write-intent-push-abc requestBody: required: true content: application/json: schema: type: object properties: approvedBy: type: string description: Identity of the approver example: alice resources: type: object description: Additional resource context for the approval responses: '200': description: Write intent approved content: application/json: schema: type: object properties: approved: type: boolean intentName: type: string '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/external/write-intents/{name}/cancel: post: tags: [External] summary: Cancel write intent description: Cancels a pending external write intent, preventing the agent from writing to the external provider. operationId: cancelWriteIntent parameters: - $ref: '#/components/parameters/OrgParam' - name: name in: path required: true description: Write intent resource name schema: type: string example: write-intent-push-abc requestBody: required: true content: application/json: schema: type: object properties: cancelledBy: type: string description: Identity of the person cancelling the intent example: alice resources: type: object description: Additional resource context responses: '200': description: Write intent cancelled content: application/json: schema: type: object properties: cancelled: type: boolean intentName: type: string '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/agents/dispatch: post: tags: [Agents] summary: Dispatch an agent run description: | Dispatches a new AgentDispatchRun against the named stack. The agent will process the prompt in the context of the specified repository and branch. operationId: dispatchAgent parameters: - $ref: '#/components/parameters/OrgParam' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DispatchInput' example: stackRef: claude-code-stack repository: my-repo branch: main prompt: Fix the failing tests in the auth module responses: '201': description: Agent run dispatched content: application/json: schema: type: object properties: run: $ref: '#/components/schemas/KradleResource' runName: type: string description: Name of the created AgentDispatchRun status: type: string example: dispatched '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/agents/runs/{name}/cancel: post: tags: [Agents] summary: Cancel an agent run description: Requests cancellation of a running AgentDispatchRun. operationId: cancelAgentRun parameters: - $ref: '#/components/parameters/OrgParam' - name: name in: path required: true description: AgentDispatchRun resource name schema: type: string example: run-abc123 responses: '200': description: Run cancelled content: application/json: schema: type: object properties: cancelled: type: boolean runName: type: string '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/agents/memory/query: post: tags: [Agents] summary: Query agent memory description: | Queries the agent memory graph or grep index. Supports graph traversal, grep-style pattern matching, and semantic search strategies. operationId: queryAgentMemory parameters: - $ref: '#/components/parameters/OrgParam' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MemoryQueryInput' example: query: deployment pipeline failures in main branch strategy: graph topK: 10 context: organizationRef: default responses: '200': description: Memory query results content: application/json: schema: $ref: '#/components/schemas/MemoryQueryResult' '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/agents/events/stream: get: tags: [Agents] summary: SSE event stream description: | Server-Sent Events stream for real-time agent and system events. Emits a "connected" event on open, then "heartbeat" every 30 seconds. Event data is JSON-encoded: `{ type, payload }`. **Note:** This endpoint returns `text/event-stream` and does not accept standard JSON requests. Use the EventSource API in browsers. operationId: streamAgentEvents parameters: - $ref: '#/components/parameters/OrgParam' responses: '200': description: SSE event stream established content: text/event-stream: schema: type: string description: | Newline-delimited SSE events. Each event is: `data: {"type":"","payload":{...}}\n\n` example: | data: {"type":"connected"} data: {"type":"heartbeat"} data: {"type":"run.status.changed","payload":{"runName":"run-abc","phase":"Running"}} '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/agents/approvals/{name}/decide: post: tags: [Agents] summary: Decide on an agent approval description: | Approves or denies a pending AgentApproval resource. The agent run that triggered the approval will proceed or be blocked accordingly. operationId: decideAgentApproval parameters: - $ref: '#/components/parameters/OrgParam' - name: name in: path required: true description: AgentApproval resource name schema: type: string example: approval-abc123 requestBody: required: true content: application/json: schema: type: object required: [decision] properties: decision: type: string enum: [approve, deny] description: Approval decision decidedBy: type: string description: Identity of the decision maker example: alice reason: type: string description: Optional reason for the decision example: Approved for hotfix deployment responses: '200': description: Approval decision recorded content: application/json: schema: type: object properties: decided: type: boolean decision: type: string enum: [approve, deny] approvalName: type: string '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/agents/webhooks/ingest: post: tags: [Webhooks] summary: Ingest agent webhook event description: | Ingests a raw webhook payload (from GitHub, Gitea, or other providers) and dispatches it to matching AgentTriggerRule resources. Normalizes the event type from the payload structure automatically. operationId: ingestAgentWebhook parameters: - $ref: '#/components/parameters/OrgParam' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/WebhookPayload' example: action: opened pull_request: number: 42 title: Fix auth bug head: ref: fix/auth-bug repository: full_name: org/my-repo sender: login: alice responses: '200': description: Webhook processed content: application/json: schema: type: object properties: processed: type: boolean triggeredRules: type: array items: type: string dispatchedRuns: type: array items: type: string '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' /api/orgs/{org}/webhooks/ingest: post: tags: [Webhooks] summary: Ingest webhook event (alias) description: Alias for `/api/orgs/{org}/agents/webhooks/ingest`. Accepts the same payload and produces the same result. operationId: ingestWebhook parameters: - $ref: '#/components/parameters/OrgParam' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/WebhookPayload' responses: '200': description: Webhook processed content: application/json: schema: type: object properties: processed: type: boolean triggeredRules: type: array items: type: string '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' components: parameters: OrgParam: name: org in: path required: true description: Organization slug schema: type: string example: default KindParam: name: kind in: path required: true description: Kubernetes resource kind schema: type: string example: Repository NameParam: name: name in: path required: true description: Resource name schema: type: string example: my-repo responses: BadRequest: description: Bad request — invalid input or malformed JSON content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' NotFound: description: Resource not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' InternalError: description: Internal server error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' schemas: KradleResource: type: object description: A Kradle (Kubernetes-style) resource object required: [apiVersion, kind, metadata] properties: apiVersion: type: string example: kradle.a5c.ai/v1alpha1 kind: type: string description: Resource kind (e.g. Repository, AgentStack) example: AgentStack metadata: type: object required: [name] properties: name: type: string example: my-stack namespace: type: string example: kradle-org-default labels: type: object additionalProperties: type: string annotations: type: object additionalProperties: type: string creationTimestamp: type: string format: date-time spec: type: object description: Resource spec (kind-specific fields) additionalProperties: true status: type: object description: Resource status (set by controller) additionalProperties: true ResourceList: type: object properties: items: type: array items: $ref: '#/components/schemas/KradleResource' total: type: integer description: Total number of items example: 5 kind: type: string description: Resource kind that was listed example: Repository ApplyResult: type: object properties: resource: $ref: '#/components/schemas/KradleResource' created: type: boolean description: True if created, false if updated name: type: string description: Resource name DeleteResult: type: object properties: deleted: type: boolean name: type: string kind: type: string ErrorResponse: type: object required: [error] properties: error: type: string description: Error code example: not_found message: type: string description: Human-readable error message example: Resource not found code: type: integer description: HTTP status code example: 404 OrgSummary: type: object properties: slug: type: string example: acme displayName: type: string example: Acme Corp namespace: type: string example: kradle-org-acme ControllerUiModel: type: object description: UI-facing snapshot of the controller state properties: org: $ref: '#/components/schemas/OrgSummary' orgs: type: array items: $ref: '#/components/schemas/OrgSummary' namespace: type: string status: type: string enum: [ok, degraded, unknown] resources: type: array items: type: object agents: type: object properties: stacks: type: object runs: type: object rules: type: object approvals: type: object views: type: object SecretItem: type: object description: Simplified secret view (from AgentSecretGrant) properties: name: type: string example: github-token type: type: string example: Opaque createdAt: type: string format: date-time nullable: true namespace: type: string example: kradle-org-default grants: type: array items: type: string description: List of agents or systems that have access MemoryQueryInput: type: object required: [query] properties: query: type: string description: Natural language or pattern query example: deployment failures in the auth module strategy: type: string enum: [graph, grep, semantic, auto] default: auto description: Query strategy to use topK: type: integer minimum: 1 maximum: 100 default: 10 description: Maximum number of results to return context: type: object description: Additional context for the query properties: organizationRef: type: string example: default repository: type: string namespace: type: string MemoryQueryResult: type: object properties: results: type: array items: type: object properties: id: type: string score: type: number content: type: string metadata: type: object total: type: integer strategy: type: string DispatchInput: type: object anyOf: - required: [agentDefinition] - required: [definitionRef] - required: [stackRef] - required: [agentStack] properties: agentDefinition: type: string description: Name of the AgentDefinition to dispatch example: aria-reviewer definitionRef: type: string description: Alias for agentDefinition example: aria-reviewer stackRef: type: string description: Name of the legacy AgentStack to dispatch example: claude-code-stack agentStack: type: string description: Alias for stackRef example: claude-code-stack repository: type: string description: Repository name for the agent run context example: my-repo branch: type: string description: Git branch the agent should operate on default: main example: fix/auth-bug prompt: type: string description: Initial prompt or task for the agent example: Fix the failing tests in the auth module context: type: object description: Additional context passed to the agent additionalProperties: true SyncInput: type: object required: [kind, localName] properties: bindingName: type: string description: Name of the TransportBinding to sync example: github-binding kind: type: string description: Resource kind being synced example: Repository localName: type: string description: Local resource name example: my-repo namespace: type: string description: Kubernetes namespace (defaults to org namespace) spec: type: object description: Local resource spec additionalProperties: true externalEnvelope: type: object description: External provider metadata properties: nativeId: type: string description: External provider's identifier example: '123456' url: type: string format: uri example: https://github.com/org/repo etag: type: string description: ETag / version for optimistic concurrency providerRef: type: string example: github watermark: type: string description: Sync watermark for incremental syncs WebhookPayload: type: object description: | Raw webhook payload from an external provider (GitHub, Gitea, etc.). The server automatically normalizes the event type from the payload structure. properties: action: type: string description: Webhook action (opened, created, labeled, etc.) example: opened pull_request: type: object description: Pull request data (if applicable) issue: type: object description: Issue data (if applicable) comment: type: object description: Comment data (if applicable) label: type: object description: Label data (if applicable) repository: type: object description: Repository data properties: full_name: type: string example: org/my-repo sender: type: object description: Actor who triggered the event properties: login: type: string example: alice workflow_run: type: object description: CI workflow run data (for pipeline events) ref: type: string description: Git ref (for push events) commits: type: array description: Commit list (for push events) items: type: object