API reference
The Connect-RPC services behind the dashboard, CLI and agents, and the plain-HTTP compatibility APIs — Loki, OTLP, Pyroscope, OpenCost and FOCUS.
The .proto files in packages/proto/kubehero/v1 are the source of truth. The same contracts generate the Go servers, the TypeScript client the dashboard uses and the CLI's client.
Calling the API
Every RPC is served by Connect over HTTP/1.1 or HTTP/2, so gRPC tools, generated clients and plain curl with JSON all work:
curl -s -X POST "$KUBEHERO_ENDPOINT/kubehero.v1.CostService/GetAllocation" \
-H "Authorization: Bearer $KUBEHERO_TOKEN" -H "Content-Type: application/json" \
-d '{"window":"24h","aggregate":["namespace"]}'JSON follows protobuf's canonical mapping: lowerCamelCase field names, 64-bit integers as strings, zero values omitted.
Auth. Authorization: Bearer <token> — an API key, a per-cluster token or an OIDC ID token. Roles: viewer < member < admin < owner, plus auditor (read everything, including the audit log). Reads need viewer, ingest needs member, mutations need admin. WhoAmI returns the resolved caller. See Identity.
Demo data. When a signal's store isn't configured, responses carry source: "demo". With KUBEHERO_DEMO_MODE=false those RPCs return failed_precondition instead.
Services
| Service | Proto | Key RPCs |
|---|---|---|
ControlPlaneService | control.proto | HealthCheck, WhoAmI, ListClusters, RegisterCluster, ListAuditLog, AppendAuditEntry, GetBurnRate, ListWasteRecommendations, GetWorkload, ListPolicies, ArmPolicy, GetTeamSpend, ListVulnerabilities, ListAnomalies, ListCapacityDemands, IngestPodCost |
TelemetryService | telemetry.proto | IngestLogs, IngestProfiles, IngestFlows, IngestUsage, IngestEvents — the collector's write path |
CostService | cost.proto | GetAllocation, GetCostTimeseries, ListRightsizing, GetEfficiency |
LogsService | observe.proto | QueryLogs, GetLogVolume, GetLogPatterns, ListLogLabels, TailLogs (server stream) |
ProfilesService | observe.proto | ListProfileTargets, GetFlamegraph, GetTopFunctions |
NetworkService | observe.proto | GetServiceMap, ListNetworkCosts |
AlertsService | alerts.proto | ListAlertRules, UpsertAlertRule, DeleteAlertRule, TestAlertRule, ListAlerts, CreateSilence, ListSilences, DeleteSilence |
AdvisorService (advisor) | advisor.proto | GetBriefing, ListAdvice, Investigate, InvestigateStream (server stream) |
PricingService (pricing engine) | pricing.proto | Quote |
Ingest limits
TelemetryService requests are validated and bounded: up to 10,000 log entries, 5,000 flows, 2,000 profiles or 20,000 stack samples per request; log lines over 64 KiB are truncated and marked; timestamps more than 10 minutes in the future are rejected. Every call returns accepted and dropped counts; rejected rows are never retried. When an ingest queue is full the RPC returns resource_exhausted — back off and retry.
Query limits
QueryLogs returns at most 5,000 lines (100 by default) and defaults to the last hour. GetFlamegraph prunes to max_nodes (2,048 by default). GetServiceMap keeps the busiest max_nodes (60) and folds the rest into other. Alert queries are capped at 4,096 characters, 20 matchers and 24h ranges.
HTTP compatibility APIs
Served by the control plane on the same port, with the same bearer tokens.
| Endpoint | Compatible with | Docs |
|---|---|---|
POST /loki/api/v1/push | Loki push (JSON, protobuf + snappy) | Logs |
GET /loki/api/v1/query_range, /query, /labels, /label/{name}/values, /series, /index/volume, /index/stats, /status/buildinfo, GET /ready | Loki query API — Grafana's Loki data source | Logs |
POST /v1/logs | OTLP/HTTP logs (protobuf, JSON) | Logs |
POST /ingest | Pyroscope HTTP ingest (pprof, folded) | Profiling |
GET /allocation/compute, GET /allocation | OpenCost allocation API | Cost allocation |
GET /api/v1/export/focus | FinOps FOCUS 1.2 CSV | Cost allocation |
GET /metrics | Prometheus exposition | Metrics |
Errors
Standard Connect codes:
| Code | Meaning |
|---|---|
unauthenticated | missing or invalid token |
permission_denied | the token's role can't do this |
invalid_argument | malformed request — e.g. a LogQL parse error (with position), an unknown aggregate, a range too long |
not_found | unknown cluster, policy, rule or SKU |
failed_precondition | the store behind this RPC isn't configured and demo mode is off |
resource_exhausted | an ingest queue is full — retry with backoff |
Versioning
Contracts live under kubehero/v1. Changes within v1 are additive; a breaking change would ship as v2 alongside v1 for at least one minor release.