All routes live under /api/v1, with two exceptions mounted at the root: the
exec WebSocket at /ws/exec/{namespace}/{name} and the port-forward reverse
proxy at /pf/{id}/ — see Real-time and Port-forward below.
When authentication is enabled, everything requires a session except these
public routes:
| Route | Why it is public |
|---|
GET /auth/config | The login page needs to know which methods are enabled |
POST /auth/login · POST /auth/refresh | Establishing and rotating the session |
POST /auth/signup | Self-service org signup. Returns 409 requires_ee in the open-source build |
GET /copilot/config | The login page decides whether to render the chat panel. Best-effort auth: a valid token resolves your tenant, an invalid one is ignored rather than rejected |
GET /config/ui | Display name and default refresh interval — chrome, no secrets |
POST /prom/write | Remote-write ingest. Gated by KUBEBOLT_REMOTE_WRITE_ENABLED (default off), not by a session |
POST /ingest/falco | Falco runtime events. Authenticated inside the handler with a cluster-scoped ingest token — strict, no permissive fallback |
Write actions additionally require the Editor role; destructive ones
(DELETE on a resource, node drain) and every admin surface require Admin.
Authenticate with Authorization: Bearer <token> — a session access token or
an API token (kbk_ / kbs_). Cluster-scoped routes act
on the active cluster unless you send X-KubeBolt-Cluster: <context-name>.
Routes that need a live cluster return 503 while it is disconnected.
API tokens and the public edge. kbs_ service tokens are rejected when
the request arrives through the bundled nginx, which force-sets
X-KubeBolt-Edge: public on everything under /api/. Reach the API Service
directly for machine-to-machine calls — see API tokens.
Clusters
| Method | Endpoint | Description |
|---|
| GET | /clusters | List all registered clusters (kubeconfig contexts + agent-connected) |
| GET | /clusters/names | Display names for every cluster, including decommissioned ones |
| POST | /clusters/switch | Switch active cluster |
| POST | /clusters | Register clusters by uploading a kubeconfig — {"kubeconfig": "<yaml>"} or a raw YAML body (admin) |
| PUT | /clusters/{context}/rename | Rename a cluster — {"displayName": "…"} (admin) |
| DELETE | /clusters/{context} | Remove an uploaded kubeconfig context (admin) |
| DELETE | /clusters/by-id/{clusterId} | Remove an agent-connected cluster by its cluster id (admin). It reappears if its agent is still connected |
| GET | /cluster/overview | Full cluster summary with counts, CPU/memory, health, events, workloads |
| GET | /cluster/health | Health score detail |
| GET | /cluster/permissions | Probed RBAC permissions per resource type |
| GET | /coverage | Data-source coverage for the active cluster |
| GET | /update-check | Latest stable KubeBolt release on GitHub. {"enabled": false} when the poller is off |
Resources
| Method | Endpoint | Description |
|---|
| GET | /resources/{type} | List with pagination (?limit=50), filtering (?namespace=, ?search=, ?status=) |
| GET | /resources/{type}/{ns}/{name} | Detail with metrics injection |
| GET | /resources/{type}/{ns}/{name}/yaml | Raw YAML — Secret values redacted, sensitive-looking ConfigMap values redacted, managedFields stripped |
| GET | /resources/{type}/{ns}/{name}/describe | kubectl-describe style output |
| GET | /resources/pods/{ns}/{name}/logs | Pod logs (?container=, ?tailLines=100) |
| GET | /resources/pods/{ns}/{name}/files[/content|/download] | Pod file browser |
| GET | /resources/{workload}/{ns}/{name}/pods | Pods owned by deployment/statefulset/daemonset/job |
| GET | /resources/{type}/{ns}/{name}/history | Revision history (Deployments via ReplicaSets; StatefulSets/DaemonSets via ControllerRevisions) |
| GET | /resources/cronjobs/{ns}/{name}/jobs | Job children of a CronJob |
| GET | /topology | The cluster’s relationship graph — see Cluster Map |
| GET | /events | Kubernetes events, filterable |
| GET | /search | Global search across resource types. ?scope=fleet fans out across every cluster you may see, so ⌘K still works when one cluster is down |
Actions (Editor, audited)
| Method | Endpoint | Description |
|---|
| PUT | /resources/{type}/{ns}/{name}/yaml | Apply edited YAML |
| POST | /resources/{type}/{ns} | Create a resource |
| POST | /resources/{type}/{ns}/{name}/restart | Rolling restart |
| POST | /resources/{type}/{ns}/{name}/scale | Scale replicas |
| POST | /resources/{type}/{ns}/{name}/rollback | Roll back to a revision |
| POST | /resources/{type}/{ns}/{name}/set-image | Set container image |
| POST | /resources/{type}/{ns}/{name}/set-resources | Set requests/limits |
| POST | /resources/{type}/{ns}/{name}/set-env | Set environment variables |
| POST | /resources/hpas/{ns}/{name}/set-bounds | HorizontalPodAutoscaler min/max replicas (server-side cap at 1000) |
| POST | /resources/{type}/{ns}/{name}/edit-metadata | Labels and annotations — the kubectl label / kubectl annotate equivalents, on any kind |
| POST | /resources/secrets/{ns}/{name}/reveal | Decode Secret values. Editor, escalated to Admin for production-pattern namespaces; requires a written reason; doubly audited — see below |
| POST | /resources/{type}/{ns}/{name}/debug | Attach an ephemeral debug container to a running pod |
| POST | /resources/{type}/{ns}/{name}/cordon · /uncordon | Node scheduling toggle |
| POST | /resources/{type}/{ns}/{name}/evict | Evict a pod through the policy/v1 Eviction API — returns 429 when a PDB blocks it |
| POST | /resources/{type}/{ns}/{name}/rollout-pause · /rollout-resume | Pause/resume a Deployment rollout |
| POST | /resources/{type}/{ns}/{name}/suspend · /resume · /trigger | CronJob controls |
Destructive (Admin)
| Method | Endpoint | Description |
|---|
| DELETE | /resources/{type}/{ns}/{name} | Delete a resource |
| POST · GET · DELETE | /resources/{type}/{ns}/{name}/drain | Start a node drain, re-attach to the in-flight SSE stream, cancel it |
Secret reveal
POST /resources/secrets/{ns}/{name}/reveal is the audited replacement for
kubectl get secret -o yaml | base64 -d. It reads from the apiserver rather than
the informer cache so a rotation check sees the current value, takes a body of
{"keys": ["…"], "reason": "…"} with a reason between 10 and 500 characters,
and emits two audit records — one on the general action log, one on a dedicated
secret-reveal channel — neither of which ever contains a value or a hash of one.
Full behavior in Resource Views.
Insights
Everything except GET /insights is served without a connected cluster:
history has to answer for clusters that are gone. GET /insights reads the
live engine, so it needs the cluster. See Insights Engine.
| Method | Endpoint | Description |
|---|
| GET | /insights | Active insights for the current cluster, with hiddenByProfile and profile |
| GET | /insights/summary | Per-cluster insight state for the fleet view |
| GET | /insights/episodes | Episode history — status, severity, rule, cluster, since, until, limit, page |
| GET | /insights/episodes/{id} | One episode with its transitions and recurrence |
| GET | /insights/operational-episodes | Deterministically clustered bursts over a window |
| GET | /insights/shift-report | ”While you were away”, scoped to your presence anchor |
| POST | /account/dashboard-seen | The presence beacon Home fires after rendering |
| GET | /insights/mutes | List silences (?cluster=) |
| POST | /insights/mutes | Create a silence (Editor, audited) |
| DELETE | /insights/mutes/{id} | Lift a silence (Editor, audited) |
| GET · PUT · DELETE | /admin/insight-policies[/{rule}] | Per-rule policy layer (Admin, audited) |
Security
The security surface is persisted by the sweep, so it also answers with no live
connector — and it spans the whole fleet, so one dead cluster does not 503 the
dashboard.
| Method | Endpoint | Description |
|---|
| GET | /findings | Vulnerability, misconfiguration and compliance findings. Scope: cluster, status; facets: source, kind, severity, resourceName, resourceNamespace, group |
| GET | /findings/workloads | The same findings aggregated workload-first |
| GET | /findings/{fingerprint} | One finding, including for a cluster that no longer exists (live: false) |
| GET | /runtime-events | Falco runtime events, newest first (?since=24h or RFC3339, ?limit=, ?cluster=, ?source=, ?priority=) |
| POST | /ingest/falco | Falco webhook ingest. Public route, cluster-scoped ingest-token auth inside the handler |
Metrics & network
| Method | Endpoint | Description |
|---|
| GET | /metrics/{type}/{ns}/{name} | CPU/memory/network series for a workload, pod, or node |
| GET | /metrics/query | PromQL instant query against the embedded metrics store |
| GET | /metrics/query_range | PromQL range query |
| GET | /flows/edges | Network flow edges (Hubble, when the agent ships flows) |
| GET | /deploys | Recent deploys detected in the range |
| POST | /prom/write | Prometheus remote-write ingest. Off unless KUBEBOLT_REMOTE_WRITE_ENABLED=true; bearer ingest token per KUBEBOLT_REMOTE_WRITE_AUTH_MODE (default disabled) — see Metrics |
Port-forward
| Method | Endpoint | Description |
|---|
| POST | /portforward | Open a forward (Editor) |
| GET | /portforward | List active forwards |
| DELETE | /portforward/{id} | Stop a forward |
| ANY | /pf/{id}/* | HTTP reverse proxy into the forwarded port — mounted at the root, not under /api/v1 |
POST /portforward binds a real TCP listener on the backend host through
client-go, capped at 20 concurrent forwards. What the browser can reach is the
HTTP reverse proxy at /pf/{id}/, which is the surface the dashboard uses; a
raw TCP client (psql, mysql) would have to reach the backend’s own network.
See Remote Clusters for the
tunnelled case and its limitations.
Helm
| Method | Endpoint | Description |
|---|
| GET | /helm/releases | All releases in the cluster |
| GET | /helm/releases/{ns}/{name} | Release detail (values, manifest, history, dependencies) |
Copilot & account
| Method | Endpoint | Description |
|---|
| POST | /copilot/chat | Kobi chat (SSE stream). Answers even with no cluster connected |
| POST | /copilot/compact | Compact the conversation |
| GET/PATCH/DELETE | /copilot/conversations[/{id}] | Conversation history, scoped to the calling user |
| GET | /account/plan · /account/usage | Plan and usage (where plans apply) |
| GET | /account/capabilities | Capability states behind the truncation banner (active-series cap) |
| POST | /mcp | MCP server — Kobi’s read-only tools over Streamable HTTP, API-token authenticated |
Integrations
| Method | Endpoint | Description |
|---|
| GET | /integrations · /integrations/{id} | Detected integrations (OpenCost, Hubble, …). Any role, and served with no cluster connected so the catalog still renders |
| POST | /integrations/{id}/install | Install via the wizard (admin, audited) |
| GET/PUT | /integrations/{id}/config | Integration configuration (admin) |
| DELETE | /integrations/{id} | Uninstall (admin) |
| GET | /integrations/agent/install-defaults | Values the Add-Cluster wizard bakes into the helm command (admin) |
| GET | /integrations/agent/auth-info | Which channel auth mode the backend expects (admin) |
| POST | /integrations/agent/issue-token | Mint an ingest token for a new cluster (admin) |
Auth, users and administration
| Method | Endpoint | Description |
|---|
| POST | /auth/logout | Revoke the refresh token and clear the cookie |
| GET | /auth/me | Current user |
| PUT | /auth/me/password | Change your own password |
| GET · POST · PUT · DELETE | /users[/{id}], PUT /users/{id}/password | User management (admin) |
| GET | /teams[/{id}] | Teams. The open-source edition has a single default team |
| GET · POST · DELETE | /admin/api-tokens[/{id}] | REST API tokens (admin) |
| GET | /admin/actions | The audit trail, newest first — ?class=mutation|access|all, ?limit= (default 100, max 1000). Admin. There is no audit page in the UI; this is how you read it |
| GET · PUT · POST | /admin/settings/{copilot,notifications,auth,general,ingest-channel} (+ /reset) | UI-editable settings that override the environment (admin, audited) |
| GET | /admin/copilot/usage/{summary,timeseries,sessions} | Kobi usage analytics (admin) |
| GET | /notifications/config · POST /notifications/test/{channel} | Notification channel status and test send (admin) |
| GET | /admin/agents | Connected agents (admin) |
Real-time
| Method | Endpoint | Description |
|---|
| WS | /api/v1/ws | WebSocket for real-time updates — see WebSocket Events |
| WS | /ws/exec/{ns}/{name} | Pod terminal — mounted at the root, not under /api/v1 |