Grafana — API Surface#
API types#
Grafana exposes functionality through five distinct API layers:
- REST/HTTP — Legacy API (
/api/...) — primary operational API for dashboards, datasources, alerting, users, orgs - REST/HTTP — Resource API (
/apis/...) — Kubernetes-style versioned resource API (in active migration) - CLI —
grafanabinary withserverandgrafana-clisubcommands (urfave/cli v2) - Plugin Extension System — gRPC-based process isolation for data source, panel, and app plugins
- Internal gRPC — Zanzana (authorization), annotation store, unified storage, search server
REST/HTTP API — Legacy (/api/...)#
Router#
- Framework: Custom Macaron-inspired router (
pkg/web/) — Grafana vendors a fork ofgopkg.in/macaron.v1internally underpkg/web/macaron.go. Therouting.RouteRegisterImplwraps it and provides theRouteRegisterinterface used throughoutpkg/api/api.go. - Route registration: All routes are programmatically registered in
pkg/api/api.go:RegisterRoutes()using aRouteRegisterfluent API. There are no annotations or reflection-based auto-discovery — every route is an explicit call tor.Get(),r.Post(),r.Group(), etc.
Middleware chain#
Middleware is applied in layers:
- Recovery (
pkg/middleware/recovery.go) — panic recovery with structured logging - Request tracing (
pkg/middleware/request_tracing.go) — OpenTelemetry span injection - Request metrics (
pkg/middleware/request_metrics.go) — Prometheus histogram per route - GZIP (
pkg/middleware/gziper.go) — response compression - CSRF (
pkg/middleware/csrf/) — CSRF token validation for mutating requests - Context handler (
pkg/services/contexthandler/) — resolves the request identity and builds a*contextmodel.ReqContextinjected into all handlers - Per-route authorization —
ac.Middleware(hs.AccessControl)wrapping individual routes, evaluated via RBAC (pkg/services/accesscontrol/) - Quota (
pkg/middleware/quota.go) — per-resource quota checks - SLO group tagging (
pkg/middleware/requestmeta/) — tags slow-path endpoints (datasource queries, plugin resources) for differentiated SLO tracking
Authentication#
Authentication is handled by the authn service (pkg/services/authn/) which implements a pluggable client chain. Registered authentication clients (in pkg/services/authn/authnimpl/registration.go):
| Client | Description |
|---|---|
api-key | Grafana API key in Authorization: Bearer header |
session | Grafana session cookie (grafana_session) |
basic | HTTP Basic Auth |
form | Login form (username + password) |
grafana | Internal service-to-service identity |
jwt | Externally-issued JWT tokens |
extended-jwt | Extended JWT with fine-grained claims (Grafana Cloud) |
oauth | OAuth2 / social login (GitHub, Google, Azure AD, GitLab, Okta, Generic OAuth) |
ldap | LDAP / Active Directory |
saml | SAML 2.0 (Enterprise) |
proxy | Auth proxy (reverse-proxy provides identity header) |
render | Internal rendering service identity |
provisioning | Provisioning service identity |
Authorization uses RBAC (pkg/services/accesscontrol/) and optionally Zanzana (OpenFGA-backed, feature-flagged).
Key Legacy API endpoint groups#
All endpoints are under /api/:
| Path group | Description |
|---|---|
/api/user/* | Current user profile, password, preferences, auth tokens, organizations |
/api/users/* | Admin: user list, lookup, update, delete, RBAC |
/api/org/* | Current org settings, users, teams, datasources, RBAC, storage |
/api/orgs/* | Multi-org admin (create, list, update, switch) |
/api/datasources/* | CRUD for datasource definitions, health check, proxy |
/api/dashboards/* | CRUD for dashboards by UID/slug/id, permissions, versions |
/api/folders/* | Folder CRUD, permissions |
/api/search/ | Dashboard/folder search |
/api/ds/query | Core data query endpoint — dispatches queries to datasource plugins |
/api/plugins/* | Plugin list, settings, health, resource proxy (CallResource) |
/api/plugin-proxy/:pluginId/* | Plugin HTTP proxy (app plugins exposing custom HTTP APIs) |
/api/annotations/* | Annotation CRUD |
/api/alerts/* / /api/alert-rules/* | Legacy alerting (deprecated) |
/api/ruler/* | Unified alerting (ngalert) rule CRUD |
/api/alertmanager/* | Alertmanager-compatible API (ngalert) |
/api/admin/* | Grafana admin: settings, stats, server-wide user management, LDAP sync |
/api/admin/users/* | Global user admin CRUD |
/api/live/* | Grafana Live WebSocket push (subscribe, publish) |
/api/snapshots/* | Dashboard snapshot CRUD |
/api/playlists/* | Playlist CRUD |
/api/frontend/settings/ | Frontend bootstrap config |
/api/login/ping | Auth health ping |
/api/user/signup/* | User signup flow |
/api/quota/* | Quota inspection |
/api/preferences/* | User/org preference settings |
Special endpoints at the server level (not under /api/):
/metrics— Prometheus metrics exposition/healthz//api/health— health check/-/ready— readiness probe/debug/pprof/*— Go pprof profiling (if enabled)
REST/HTTP API — Resource API (/apis/...)#
Overview#
The Resource API embeds a Kubernetes-compatible API server (k8s.io/apiserver) into the Grafana process. Routes follow the Kubernetes URL convention:
/apis/<group>/<version>/namespaces/<namespace>/<resource>/<name>All resources support the standard Kubernetes verbs: get, list, create, update, patch, delete, watch.
API Groups#
Resources are organized into API groups, each with a *.grafana.app domain. As of this analysis, the following groups are registered (from apps/ and pkg/registry/apis/):
| API Group | Resource | Status |
|---|---|---|
dashboard.grafana.app | dashboards | v0alpha1, v1beta1, v1, v2alpha1, v2beta1, v2 |
folder.grafana.app | folders | v0alpha1 |
alerting.grafana.app / rules.alerting.grafana.app | alertrules | v0alpha1 |
notifications.alerting.grafana.app | notification resources | v0alpha1, v1beta1 |
historian.alerting.grafana.app | alert history | v0alpha1 |
alertenrichment.grafana.app | alert enrichment | v1beta1 |
datasource.grafana.app | datasource definitions | v0alpha1 |
iam.grafana.app | identity/access resources | v0alpha1 |
playlist.grafana.app | playlists | v0alpha1 |
preferences.grafana.app | user/org preferences | v0alpha1 |
secret.grafana.app | secure values, keepers | v1beta1 |
shorturl.grafana.app | short URL mappings | v1beta1 |
annotation.grafana.app | annotations | v0alpha1 |
correlations.grafana.app | data correlations | v0alpha1 |
collections.grafana.app | resource collections | v1alpha1 |
advisor.grafana.app | health advisor checks | v0alpha1 |
scope.grafana.app | dashboard scopes | v0alpha1 |
plugins.grafana.app | plugin manifests | v0alpha1 |
userstorage.grafana.app | per-user storage blobs | v0alpha1 |
service.grafana.app | service account keys | v0alpha1 |
live.grafana.app | Grafana Live channels | v0alpha1 |
provisioning.grafana.app | provisioning jobs/repos | v0alpha1 |
logsdrilldown.grafana.app | logs drilldown | v1alpha1, v1beta1 |
dashvalidator.grafana.app | dashboard validation | v1alpha1 |
example.grafana.app | example/reference app | v0alpha1 |
ofrep.grafana.app | OpenFeature REST Protocol | (feature flags) |
Route registration pattern#
Each API group is registered via the builder.APIRegistrar interface. Groups call RegisterAPIService(apiregistration builder.APIRegistrar, ...), which invokes apiregistration.RegisterAPI(builder). The embedded kube-apiserver discovers the group via scheme registration and the storage layer (pkg/storage/unified/ or in-memory).
gRPC interceptors (internal)#
The embedded Kubernetes API server flow uses standard k8s.io/apiserver admission, authentication (delegating to Grafana authn), and authorization (delegating to Grafana RBAC/Zanzana) hooks.
gRPC API (internal)#
Grafana runs an internal gRPC server for selected services:
| Service | Proto file | Description |
|---|---|---|
AuthzService | pkg/services/authz/proto/v1/extention.proto + authlib | Zanzana authorization queries |
AuthzExtensionService | same | Extended RBAC queries |
AnnotationStore | pkg/registry/apps/annotation/proto/store.proto | Annotation persistence for the annotation app |
ResourceStore | pkg/storage/unified/proto/resource.proto | Unified storage gRPC backend (for distributed storage mode) |
ResourceSearch | pkg/storage/unified/proto/search.proto | Full-text search over resources |
BlobStore | pkg/storage/unified/proto/blob.proto | Binary blob storage |
Pusher (Loki) | pkg/components/loki/logproto/logproto.proto | Log push endpoint |
RendererV2 | pkg/plugins/backendplugin/pluginextensionv2/rendererv2.proto | Image renderer plugin |
Sanitizer | pkg/plugins/backendplugin/pluginextensionv2/sanitizer.proto | HTML sanitizer plugin |
gRPC server initialization is handled by pkg/server/module_server.go (via modules.GRPCServer). gRPC service registrations happen in pkg/services/authz/zanzana.go (RegisterAuthzServiceServer).
CLI#
Framework#
github.com/urfave/cli/v2
Binary: grafana#
Entry point: pkg/cmd/grafana/main.go
grafana
├── server # Run the Grafana HTTP server
│ └── target # Select which module(s) to run (for component-mode deployment)
└── cli # Admin/plugin management (delegates to grafana-cli commands)
├── plugins # Plugin management
│ ├── install <plugin-id> [version]
│ ├── list-remote
│ ├── list-versions <plugin-id>
│ ├── update / upgrade <plugin-id>
│ ├── update-all / upgrade-all
│ ├── ls
│ └── uninstall / remove <plugin-id>
└── admin # Administrative operations
├── reset-admin-password <new-password>
├── data-migration
│ └── encrypt-datasource-passwords
├── secrets-migration
│ ├── re-encrypt
│ ├── rollback
│ └── re-encrypt-data-keys
├── secrets-consolidation
│ └── consolidate
└── flush-rbac-seed-assignmentFlag patterns#
Global flags for server command (defined in pkg/cmd/grafana-server/commands/flags.go):
--config— path tografana.ini--homepath— Grafana install path--configOverrides— inline config key=value overrides--pidfile— PID file path--packaging— packaging type (deb, rpm, docker, etc.)--profile/--profileAddr/--profilePort— pprof profiling--tracing/--tracingFile— custom tracing
No env-var binding at the CLI level — env vars are consumed through the INI config system (setting.Cfg), not via CLI flags.
Target command (component mode)#
grafana server target <module> allows running Grafana as individual service components (storage server, search server, Zanzana server, operator server, etc.) for scaled-out deployments. This is the Grafana’s path toward loosely-coupled component architecture without full microservices.
Plugin / Extension System#
Mechanism#
Grafana’s plugin system is the primary extensibility mechanism and runs external plugin code in isolated child processes communicating via gRPC using the grafana-plugin-sdk-go protocol (defined in github.com/grafana/grafana-plugin-sdk-go/genproto/pluginv2).
Plugin types#
| Type | String | Description |
|---|---|---|
TypeDataSource | "datasource" | Query backends (Prometheus, MySQL, etc.) |
TypePanel | "panel" | Visualization components (frontend-only or backend) |
TypeApp | "app" | Full applications with their own pages and APIs |
TypeRenderer | "renderer" | Image rendering service (headless Chrome) |
Plugin gRPC protocol (pluginv2)#
The Grafana backend calls into plugin processes via these gRPC methods (from pkg/plugins/backendplugin/grpcplugin/client_proto.go):
| Method | Direction | Description |
|---|---|---|
QueryData | Host → Plugin | Execute data query, return data frames |
QueryChunkedData | Host → Plugin | Streaming query for large results |
CallResource | Host → Plugin | HTTP resource call (plugins expose custom REST APIs) |
CheckHealth | Host → Plugin | Health probe |
CollectMetrics | Host → Plugin | Pull Prometheus metrics from plugin |
SubscribeStream | Host → Plugin | Subscribe to streaming channel |
RunStream | Host → Plugin | Run a streaming data source |
PublishStream | Host → Plugin | Publish to streaming channel |
Extension points for third-party code#
- Data source plugins: Implement
QueryData,CheckHealth,CallResource— most common extension type. Any language with gRPC support can implement a data source. - Panel plugins: Frontend-only (TypeScript/React), no backend requirements unless they add
CallResourcebackend. - App plugins: Full applications — can add their own nav items, pages, and backend HTTP resources via
CallResource. App plugins that implement the Kubernetes-style API register themselves underappplugin.grafana.app/<pluginId>. - Renderer plugin: Exactly one renderer plugin per Grafana instance (typically
grafana-image-renderer). Communicates overRendererV2gRPC service. - Standalone plugins: Some built-in plugins (CloudWatch, Azure Monitor) support running as a separate process accessible over gRPC, allowing independent scaling and updates.
- Plugin resources endpoint:
GET/POST /api/plugins/:pluginId/resources/*— proxies any HTTP requests to a plugin’sCallResourcehandler, enabling plugins to expose arbitrary REST APIs accessible to the Grafana frontend.
Plugin discovery and loading#
- Discovery: filesystem scan of
GF_PATHS_PLUGINS, CDN (enterprise), core plugins bundled in binary - Loading: JSON manifest (
plugin.json) parsed, CUE schema validated (for newer plugins) - Signature verification: Unsigned plugins blocked by default (configurable)
- Backend launch:
hashicorp/go-pluginlaunches child process with gRPC handshake - Registration: Plugin registered in
PluginStore; backend available viaPluginManager
Library API (if applicable)#
Grafana is primarily an application, not a library. However several packages are intentionally designed for external consumption:
| Package | Purpose | Notes |
|---|---|---|
github.com/grafana/grafana-plugin-sdk-go | Plugin SDK | Separate module; the primary external library interface for plugin authors |
pkg/apis/<group>/ | Kubernetes API type definitions | Used by external operators and tools interacting with the Resource API |
apps/<name>/pkg/apis/ | App-specific API types | Each app is a separate Go module, consumable independently |
pkg/apimachinery/ | Shared API machinery utilities | Used by Grafana Labs tooling |
The grafana-plugin-sdk-go is the official library API for Grafana extensibility. It defines the data frame format, gRPC protocol types, and Go SDK for writing backend plugins.
Notable API design observations#
Dual API coexistence: Legacy
/api/...and Resource/apis/...serve the same resources during migration. Feature flags (featuremgmt) gate which API is authoritative per resource. This creates a controlled but complex transition period.Kubernetes URL conventions without Kubernetes: The Resource API uses Kubernetes-style URLs, verbs, and response shapes, but runs embedded in a single Go process over a SQL database — not etcd or a real Kubernetes cluster. This gives Grafana operability benefits (GitOps tooling,
kubectlcompatibility) without the operational overhead of a full Kubernetes control plane.Plugin resources create a meta-API: The
/api/plugins/:pluginId/resources/*endpoint effectively lets each plugin publish its own REST API surface under Grafana’s auth and routing umbrella. App plugins exploit this heavily to build full applications hosted within Grafana.gRPC for internal services, HTTP for external: The internal gRPC bus (Zanzana, annotation store, unified storage) is strictly internal. The external-facing surface is entirely HTTP. This matches the “single binary” design — gRPC is used for decoupling, not distribution.
Versioning via API groups: The Resource API achieves backward compatibility through Kubernetes-style versioned API groups (
v0alpha1→v1beta1→v1→v2). Legacy API has no formal versioning (endpoints may change across Grafana releases with deprecation notices in docs).