API Reference
Complete REST API documentation for the Kure Monitor backend.
Base URL: http://<backend-host>:8000/api
Authentication
Section titled “Authentication”Two distinct mechanisms (since 2.3.0):
- User sessions (cookie-based) for dashboard / browser traffic
- Service token (
X-Service-Tokenheader) for agent and scanner traffic
The legacy AUTH_API_KEY / auth.apiKey single-key model was removed in 2.3.0.
User sessions (dashboard)
Section titled “User sessions (dashboard)”Log in with POST /api/auth/login (username + password). On success the backend sets an HttpOnly cookie named kure_session, signed with SESSION_SECRET. All subsequent /api/* calls from the browser use that cookie automatically.
Rate limit: 5 login attempts per 30 seconds.
Service token (agent / scanner)
Section titled “Service token (agent / scanner)”Ingest endpoints authenticate with the X-Service-Token HTTP header:
X-Service-Token: <SERVICE_TOKEN value>WebSocket and SSE log streams use a query parameter instead:
ws://localhost:8000/api/ws?token=YOUR_SERVICE_TOKENGET /api/pods/{namespace}/{pod_name}/logs/stream?token=YOUR_SERVICE_TOKENAlways-public endpoints
Section titled “Always-public endpoints”| Endpoint | Purpose |
|---|---|
GET /health, GET /metrics | Liveness / Prometheus scrape |
GET /api/auth/status | Whether initial admin setup is needed |
POST /api/auth/login | Log in with username + password |
POST /api/auth/signup | Create the initial admin (only when no users exist) |
Service-token-only ingest
Section titled “Service-token-only ingest”| Endpoint | Caller |
|---|---|
POST /api/pods/failed | Agent |
POST /api/pods/dismiss-deleted | Agent |
POST /api/security/findings | Scanner |
POST /api/security/scan/clear | Scanner |
POST /api/security/rescan-status | Scanner |
DELETE /api/security/findings/resource/{type}/{ns}/{name} | Scanner |
POST /api/metrics/security-scan-duration | Scanner |
Error response
Section titled “Error response”401 Unauthorized{ "detail": "Not authenticated"}Endpoints overview
Section titled “Endpoints overview”| Category | Endpoint | Description |
|---|---|---|
| Config | GET /config | App status |
| Pods | POST /pods/failed | Report failure |
| Pods | GET /pods/failed | List active failures |
| Pods | GET /pods/history | List resolved pods |
| Pods | GET /pods/ignored | List ignored pods |
| Pods | PUT /pods/{id}/status | Update status |
| Pods | DELETE /pods/failed/{id} | Dismiss |
| Pods | POST /pods/failed/{id}/retry-solution | Regenerate AI solution |
| Pods | GET /pods/{ns}/{name}/logs | Get logs |
| Security | POST /security/findings | Report finding |
| Security | GET /security/findings | List findings |
| Security | POST /security/findings/{id}/fix | Generate AI fix |
| Security | GET / POST / DELETE /security/trusted-registries | Manage trusted registries |
| Mirror | POST /mirror/preview/{id} | Generate fixed manifest |
| Mirror | POST /mirror/deploy/{id} | Deploy mirror pod |
| Mirror | GET /mirror/status/{id} | Mirror status |
| Mirror | DELETE /mirror/{id} | Delete mirror |
| Mirror | GET /mirror/active | List active mirrors |
| Diagram | GET /diagram/namespaces | List namespaces |
| Diagram | GET /diagram/namespace/{ns} | Per-namespace graph |
| Diagram | GET /diagram/workload/{ns}/{kind}/{name} | Per-workload graph |
| Diagram | GET /diagram/manifest/{ns}/{kind}/{name} | Live manifest (rejects Secret with 403) |
| Admin | GET / POST / DELETE /admin/llm/* | LLM config |
| Admin | GET / POST / DELETE /admin/excluded-* | Suppressions |
| Admin | GET / POST / PUT / DELETE /admin/notifications | Notifications |
| Admin | GET / POST /admin/settings/* | App settings |
Pod monitoring
Section titled “Pod monitoring”Report failed pod
Section titled “Report failed pod”POST /api/pods/failedRequest body:
{ "pod_name": "my-app-7d9f8b6c4-abc12", "namespace": "default", "node_name": "worker-1", "failure_reason": "CrashLoopBackOff", "failure_message": "Back-off restarting failed container", "creation_timestamp": "2024-01-15T10:30:00Z", "events": [...], "container_statuses": [...], "manifest": "apiVersion: v1\nkind: Pod\n...", "logs": "Error: Database connection failed..."}Response 200:
{ "id": 1, "pod_name": "my-app-7d9f8b6c4-abc12", "namespace": "default", "failure_reason": "CrashLoopBackOff", "solution": "## Root Cause\n...", "events": [...], "container_statuses": [...], "timestamp": "2024-01-15T10:30:00Z"}List failed pods
Section titled “List failed pods”GET /api/pods/failedReturns all active (non-dismissed) failures.
Get history / ignored
Section titled “Get history / ignored”GET /api/pods/historyGET /api/pods/ignoredUpdate status
Section titled “Update status”PUT /api/pods/{pod_id}/status{ "status": "investigating"}Valid: new, investigating, resolved, ignored.
Dismiss / restore
Section titled “Dismiss / restore”DELETE /api/pods/failed/{pod_id}PUT /api/pods/ignored/{pod_id}/restoreRetry AI
Section titled “Retry AI”POST /api/pods/failed/{pod_id}/retry-solutionGet logs
Section titled “Get logs”GET /api/pods/{namespace}/{pod_name}/logs ?container=app &tail_lines=100 &previous=falseStream logs (SSE)
Section titled “Stream logs (SSE)”GET /api/pods/{namespace}/{pod_name}/logs/stream ?container=app &tail_lines=100 &token=<SERVICE_TOKEN>Security
Section titled “Security”Report finding
Section titled “Report finding”POST /api/security/findings{ "resource_type": "Pod", "resource_name": "my-app-7d9f8b6c4-abc12", "namespace": "default", "check_name": "privileged_container", "severity": "critical", "message": "Container 'app' is running in privileged mode", "remediation": "Remove 'privileged: true' from securityContext", "details": {"container": "app", "field": "securityContext.privileged"}}List / dismiss / restore / clear
Section titled “List / dismiss / restore / clear”GET /api/security/findingsDELETE /api/security/findings/{id}PUT /api/security/findings/{id}/restorePOST /api/security/scan/clearDELETE /api/security/findings/resource/{type}/{ns}/{name}Generate AI fix
Section titled “Generate AI fix”POST /api/security/findings/{id}/fixReturns the LLM-generated remediation.
Trusted registries
Section titled “Trusted registries”GET /api/security/trusted-registriesPOST /api/security/trusted-registries { "registry": "..." }DELETE /api/security/trusted-registries/{registry}Mirror Pod Testing
Section titled “Mirror Pod Testing”Preview fix
Section titled “Preview fix”POST /api/mirror/preview/{pod_id}Returns:
{ "fixed_manifest": "apiVersion: v1\nkind: Pod\n...", "explanation": "## Changes Made\n1. Added resource limits...", "is_fallback": false}Deploy
Section titled “Deploy”POST /api/mirror/deploy/{pod_id}{ "ttl_seconds": 180, "manifest": "apiVersion: v1\nkind: Pod\n..." // optional, overrides preview}Returns:
{ "mirror_id": "abc123", "mirror_pod_name": "my-app-mirror-abc123", "namespace": "default", "status": "Pending", "ttl_seconds": 180, "created_at": "2026-03-26T10:30:00Z", "fixed_manifest": "...", "explanation": "..."}Status / delete / list
Section titled “Status / delete / list”GET /api/mirror/status/{mirror_id}DELETE /api/mirror/{mirror_id}GET /api/mirror/activeTTL setting
Section titled “TTL setting”GET /api/admin/settings/mirror-ttlPUT /api/admin/settings/mirror-ttl { "seconds": 300 }Range: 30 – 3600 seconds. Admin role required for PUT.
Diagram
Section titled “Diagram”Introduced in 2.3.2. All endpoints gated by
require_read.
List namespaces
Section titled “List namespaces”GET /api/diagram/namespaces{ "namespaces": ["default", "kube-system", "kure-system"] }Per-namespace graph
Section titled “Per-namespace graph”GET /api/diagram/namespace/{namespace}{ "nodes": [{ "id": "...", "kind": "Deployment", "name": "...", "namespace": "..." }], "edges": [{ "id": "...", "source": "...", "target": "...", "kind": "owns" }], "groups": [{ "id": "...", "label": "my-app", "members": ["..."] }]}Per-workload graph
Section titled “Per-workload graph”GET /api/diagram/workload/{namespace}/{kind}/{name}Valid kind values: Deployment, StatefulSet, DaemonSet, Job, CronJob. Same response shape as the namespace graph.
Get node manifest
Section titled “Get node manifest”GET /api/diagram/manifest/{namespace}/{kind}/{name}Returns the live manifest as YAML. Rejects kind=Secret with HTTP 403 by design — the backend ServiceAccount has no read access to Secrets. Synthesized kinds (Permission, Subject:User, Subject:Group) are rejected with HTTP 400 because they have no underlying manifest.
List Roles + ClusterRoles
Section titled “List Roles + ClusterRoles”Added in 2.3.3.
GET /api/diagram/roles{ "cluster_roles": [{ "name": "..." }], "roles": [{ "namespace": "...", "name": "..." }]}Per-Role graph
Section titled “Per-Role graph”Added in 2.3.3.
GET /api/diagram/role/{namespace}/{name}Same response shape as the namespace graph. Nodes include the Role, its RoleBindings, synthesized Permission nodes (one per (apiGroup, resource) tuple, with verbs and resourceNames in metadata), and Subject:User / Subject:Group / Subject:ServiceAccount nodes.
Per-ClusterRole graph
Section titled “Per-ClusterRole graph”Added in 2.3.3.
GET /api/diagram/clusterrole/{name}Same shape as the per-Role graph but for ClusterRoles + ClusterRoleBindings.
Admin — LLM
Section titled “Admin — LLM”GET /api/admin/llm/statusPOST /api/admin/llm/config { "provider": "...", "api_key": "...", "model": "..." }POST /api/admin/llm/test { "provider": "...", "api_key": "...", "model": "..." }DELETE /api/admin/llm/configSee LLM Providers for supported provider/model combinations.
Admin — Exclusions
Section titled “Admin — Exclusions”GET /api/admin/excluded-namespacesPOST /api/admin/excluded-namespaces { "namespace": "kube-system" }DELETE /api/admin/excluded-namespaces/{namespace}
GET /api/admin/excluded-podsPOST /api/admin/excluded-pods { "pod_name": "test-*" }DELETE /api/admin/excluded-pods/{pod_name}Admin — Notifications
Section titled “Admin — Notifications”GET /api/admin/notificationsPOST /api/admin/notificationsPUT /api/admin/notifications/{provider}DELETE /api/admin/notifications/{provider}POST /api/admin/notifications/{provider}/testSample body:
{ "provider": "slack", "enabled": true, "config": { "webhook_url": "https://hooks.slack.com/services/..." }}Admin — Settings
Section titled “Admin — Settings”GET /api/admin/settings/{key}POST /api/admin/settings/{key} { "value": "10080" }Common keys:
history_retention_minutes— auto-delete resolved pods after N minutes (0= disabled)ignored_retention_minutes— auto-delete ignored pods after N minutes (0= disabled)
WebSocket
Section titled “WebSocket”WS /api/wsPush messages from the backend:
{ "type": "pod_failure", "data": { "id": 1, "pod_name": "...", "solution": "..." } }{ "type": "pod_deleted", "data": { "namespace": "default", "pod_name": "..." } }{ "type": "solution_updated", "data": { "id": 1, "solution": "..." } }{ "type": "security_finding", "data": { "id": 1, "severity": "critical", "message": "..." } }{ "type": "namespace_exclusion", "data": { "namespace": "kube-system", "action": "excluded" } }{ "type": "trusted_registry_change", "data": { "registry": "...", "action": "added" } }{ "type": "pod_status_change", "data": { "id": 1, "status": "investigating" } }{ "type": "security_rescan_status", "data": { "status": "started", "reason": "trusted_registry_change" } }Error responses
Section titled “Error responses”| Status | Body |
|---|---|
400 | { "detail": "Pod name and namespace are required" } |
401 | { "detail": "Not authenticated" } |
403 | { "detail": "Secret manifests are not readable by design." } |
404 | { "detail": "Pod failure not found" } |
500 | { "detail": "Internal server error..." } |
503 | { "detail": "Kubernetes client not available" } |
OpenAPI / interactive docs
Section titled “OpenAPI / interactive docs”- Swagger UI:
http://<backend-host>:8000/docs - ReDoc:
http://<backend-host>:8000/redoc