Grafana — API Surface#

API types#

Grafana exposes functionality through five distinct API layers:

  1. REST/HTTP — Legacy API (/api/...) — primary operational API for dashboards, datasources, alerting, users, orgs
  2. REST/HTTP — Resource API (/apis/...) — Kubernetes-style versioned resource API (in active migration)
  3. CLIgrafana binary with server and grafana-cli subcommands (urfave/cli v2)
  4. Plugin Extension System — gRPC-based process isolation for data source, panel, and app plugins
  5. 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 of gopkg.in/macaron.v1 internally under pkg/web/macaron.go. The routing.RouteRegisterImpl wraps it and provides the RouteRegister interface used throughout pkg/api/api.go.
  • Route registration: All routes are programmatically registered in pkg/api/api.go:RegisterRoutes() using a RouteRegister fluent API. There are no annotations or reflection-based auto-discovery — every route is an explicit call to r.Get(), r.Post(), r.Group(), etc.

Middleware chain#

Middleware is applied in layers:

  1. Recovery (pkg/middleware/recovery.go) — panic recovery with structured logging
  2. Request tracing (pkg/middleware/request_tracing.go) — OpenTelemetry span injection
  3. Request metrics (pkg/middleware/request_metrics.go) — Prometheus histogram per route
  4. GZIP (pkg/middleware/gziper.go) — response compression
  5. CSRF (pkg/middleware/csrf/) — CSRF token validation for mutating requests
  6. Context handler (pkg/services/contexthandler/) — resolves the request identity and builds a *contextmodel.ReqContext injected into all handlers
  7. Per-route authorizationac.Middleware(hs.AccessControl) wrapping individual routes, evaluated via RBAC (pkg/services/accesscontrol/)
  8. Quota (pkg/middleware/quota.go) — per-resource quota checks
  9. 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):

ClientDescription
api-keyGrafana API key in Authorization: Bearer header
sessionGrafana session cookie (grafana_session)
basicHTTP Basic Auth
formLogin form (username + password)
grafanaInternal service-to-service identity
jwtExternally-issued JWT tokens
extended-jwtExtended JWT with fine-grained claims (Grafana Cloud)
oauthOAuth2 / social login (GitHub, Google, Azure AD, GitLab, Okta, Generic OAuth)
ldapLDAP / Active Directory
samlSAML 2.0 (Enterprise)
proxyAuth proxy (reverse-proxy provides identity header)
renderInternal rendering service identity
provisioningProvisioning 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 groupDescription
/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/queryCore 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/pingAuth 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 GroupResourceStatus
dashboard.grafana.appdashboardsv0alpha1, v1beta1, v1, v2alpha1, v2beta1, v2
folder.grafana.appfoldersv0alpha1
alerting.grafana.app / rules.alerting.grafana.appalertrulesv0alpha1
notifications.alerting.grafana.appnotification resourcesv0alpha1, v1beta1
historian.alerting.grafana.appalert historyv0alpha1
alertenrichment.grafana.appalert enrichmentv1beta1
datasource.grafana.appdatasource definitionsv0alpha1
iam.grafana.appidentity/access resourcesv0alpha1
playlist.grafana.appplaylistsv0alpha1
preferences.grafana.appuser/org preferencesv0alpha1
secret.grafana.appsecure values, keepersv1beta1
shorturl.grafana.appshort URL mappingsv1beta1
annotation.grafana.appannotationsv0alpha1
correlations.grafana.appdata correlationsv0alpha1
collections.grafana.appresource collectionsv1alpha1
advisor.grafana.apphealth advisor checksv0alpha1
scope.grafana.appdashboard scopesv0alpha1
plugins.grafana.appplugin manifestsv0alpha1
userstorage.grafana.appper-user storage blobsv0alpha1
service.grafana.appservice account keysv0alpha1
live.grafana.appGrafana Live channelsv0alpha1
provisioning.grafana.appprovisioning jobs/reposv0alpha1
logsdrilldown.grafana.applogs drilldownv1alpha1, v1beta1
dashvalidator.grafana.appdashboard validationv1alpha1
example.grafana.appexample/reference appv0alpha1
ofrep.grafana.appOpenFeature 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:

ServiceProto fileDescription
AuthzServicepkg/services/authz/proto/v1/extention.proto + authlibZanzana authorization queries
AuthzExtensionServicesameExtended RBAC queries
AnnotationStorepkg/registry/apps/annotation/proto/store.protoAnnotation persistence for the annotation app
ResourceStorepkg/storage/unified/proto/resource.protoUnified storage gRPC backend (for distributed storage mode)
ResourceSearchpkg/storage/unified/proto/search.protoFull-text search over resources
BlobStorepkg/storage/unified/proto/blob.protoBinary blob storage
Pusher (Loki)pkg/components/loki/logproto/logproto.protoLog push endpoint
RendererV2pkg/plugins/backendplugin/pluginextensionv2/rendererv2.protoImage renderer plugin
Sanitizerpkg/plugins/backendplugin/pluginextensionv2/sanitizer.protoHTML 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-assignment

Flag patterns#

Global flags for server command (defined in pkg/cmd/grafana-server/commands/flags.go):

  • --config — path to grafana.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#

TypeStringDescription
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):

MethodDirectionDescription
QueryDataHost → PluginExecute data query, return data frames
QueryChunkedDataHost → PluginStreaming query for large results
CallResourceHost → PluginHTTP resource call (plugins expose custom REST APIs)
CheckHealthHost → PluginHealth probe
CollectMetricsHost → PluginPull Prometheus metrics from plugin
SubscribeStreamHost → PluginSubscribe to streaming channel
RunStreamHost → PluginRun a streaming data source
PublishStreamHost → PluginPublish to streaming channel

Extension points for third-party code#

  1. Data source plugins: Implement QueryData, CheckHealth, CallResource — most common extension type. Any language with gRPC support can implement a data source.
  2. Panel plugins: Frontend-only (TypeScript/React), no backend requirements unless they add CallResource backend.
  3. 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 under appplugin.grafana.app/<pluginId>.
  4. Renderer plugin: Exactly one renderer plugin per Grafana instance (typically grafana-image-renderer). Communicates over RendererV2 gRPC service.
  5. Standalone plugins: Some built-in plugins (CloudWatch, Azure Monitor) support running as a separate process accessible over gRPC, allowing independent scaling and updates.
  6. Plugin resources endpoint: GET/POST /api/plugins/:pluginId/resources/* — proxies any HTTP requests to a plugin’s CallResource handler, enabling plugins to expose arbitrary REST APIs accessible to the Grafana frontend.

Plugin discovery and loading#

  1. Discovery: filesystem scan of GF_PATHS_PLUGINS, CDN (enterprise), core plugins bundled in binary
  2. Loading: JSON manifest (plugin.json) parsed, CUE schema validated (for newer plugins)
  3. Signature verification: Unsigned plugins blocked by default (configurable)
  4. Backend launch: hashicorp/go-plugin launches child process with gRPC handshake
  5. Registration: Plugin registered in PluginStore; backend available via PluginManager

Library API (if applicable)#

Grafana is primarily an application, not a library. However several packages are intentionally designed for external consumption:

PackagePurposeNotes
github.com/grafana/grafana-plugin-sdk-goPlugin SDKSeparate module; the primary external library interface for plugin authors
pkg/apis/<group>/Kubernetes API type definitionsUsed by external operators and tools interacting with the Resource API
apps/<name>/pkg/apis/App-specific API typesEach app is a separate Go module, consumable independently
pkg/apimachinery/Shared API machinery utilitiesUsed 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#

  1. 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.

  2. 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, kubectl compatibility) without the operational overhead of a full Kubernetes control plane.

  3. 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.

  4. 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.

  5. Versioning via API groups: The Resource API achieves backward compatibility through Kubernetes-style versioned API groups (v0alpha1v1beta1v1v2). Legacy API has no formal versioning (endpoints may change across Grafana releases with deprecation notices in docs).