DEV Community

Alex Spinov
Alex Spinov

Posted on

Grafana Has a Free API: Here's How to Use It for Dashboard Automation

Grafana isn't just a visualization tool — it has a complete REST API that lets you create dashboards, manage alerts, query data sources, and automate your entire observability stack programmatically.

Why Use the Grafana API?

  • Automate dashboard creation for new services
  • Sync dashboards across environments (dev/staging/prod)
  • Manage alerts and notification channels via code
  • Build custom monitoring portals for your team

Getting Started

Generate an API key in Grafana: Configuration > API Keys > Add:

export GRAFANA_URL="http://localhost:3000"
export GRAFANA_TOKEN="your-api-key"

# List all dashboards
curl -s -H "Authorization: Bearer $GRAFANA_TOKEN" \
  "$GRAFANA_URL/api/search?type=dash-db" | jq '.[] | {title: .title, uid: .uid, url: .url}'
Enter fullscreen mode Exit fullscreen mode

Create a Dashboard Programmatically

import requests

GRAFANA_URL = "http://localhost:3000"
HEADERS = {"Authorization": "Bearer your-api-key", "Content-Type": "application/json"}

def create_dashboard(title, panels):
    dashboard = {
        "dashboard": {
            "title": title,
            "panels": panels,
            "refresh": "5s",
            "time": {"from": "now-1h", "to": "now"}
        },
        "overwrite": False
    }
    resp = requests.post(f"{GRAFANA_URL}/api/dashboards/db", json=dashboard, headers=HEADERS)
    return resp.json()

panels = [
    {
        "title": "CPU Usage",
        "type": "timeseries",
        "gridPos": {"h": 8, "w": 12, "x": 0, "y": 0},
        "targets": [{"expr": "rate(process_cpu_seconds_total[5m]) * 100", "refId": "A"}]
    },
    {
        "title": "Memory Usage",
        "type": "timeseries",
        "gridPos": {"h": 8, "w": 12, "x": 12, "y": 0},
        "targets": [{"expr": "process_resident_memory_bytes / 1024 / 1024", "refId": "A"}]
    },
    {
        "title": "Request Rate",
        "type": "stat",
        "gridPos": {"h": 4, "w": 6, "x": 0, "y": 8},
        "targets": [{"expr": "rate(http_requests_total[5m])", "refId": "A"}]
    }
]

result = create_dashboard("My Service Monitoring", panels)
print(f"Dashboard created: {result.get('url')}")
Enter fullscreen mode Exit fullscreen mode

Manage Alerts

def create_alert_rule(name, expr, threshold, for_duration="5m"):
    rule = {
        "name": name,
        "condition": "last()",
        "data": [{"refId": "A", "queryType": "", "model": {"expr": expr}}],
        "noDataState": "NoData",
        "execErrState": "Error",
        "for": for_duration,
        "annotations": {"summary": f"{name} triggered"},
        "labels": {"severity": "warning"}
    }
    resp = requests.post(f"{GRAFANA_URL}/api/v1/provisioning/alert-rules", json=rule, headers=HEADERS)
    return resp.json()

create_alert_rule("High CPU", "rate(process_cpu_seconds_total[5m]) * 100 > 80", 80)
create_alert_rule("High Memory", "process_resident_memory_bytes > 1e9", 1000000000)
Enter fullscreen mode Exit fullscreen mode

Export and Sync Dashboards

import json
import os

def export_all_dashboards(output_dir="dashboards"):
    os.makedirs(output_dir, exist_ok=True)
    search = requests.get(f"{GRAFANA_URL}/api/search?type=dash-db", headers=HEADERS).json()

    for dash in search:
        full = requests.get(f"{GRAFANA_URL}/api/dashboards/uid/{dash['uid']}", headers=HEADERS).json()
        filepath = os.path.join(output_dir, f"{dash['uid']}.json")
        with open(filepath, 'w') as f:
            json.dump(full['dashboard'], f, indent=2)
        print(f"Exported: {dash['title']} -> {filepath}")

def import_dashboards(input_dir="dashboards"):
    for filename in os.listdir(input_dir):
        if filename.endswith('.json'):
            with open(os.path.join(input_dir, filename)) as f:
                dashboard = json.load(f)
            dashboard['id'] = None
            payload = {"dashboard": dashboard, "overwrite": True}
            resp = requests.post(f"{GRAFANA_URL}/api/dashboards/db", json=payload, headers=HEADERS)
            print(f"Imported: {dashboard.get('title')} -> {resp.status_code}")
Enter fullscreen mode Exit fullscreen mode

Query Data Sources

# List all data sources
curl -s -H "Authorization: Bearer $GRAFANA_TOKEN" \
  "$GRAFANA_URL/api/datasources" | jq '.[] | {name: .name, type: .type, url: .url}'

# Query Prometheus via Grafana
curl -s -H "Authorization: Bearer $GRAFANA_TOKEN" \
  "$GRAFANA_URL/api/ds/query" \
  -d '{"queries":[{"refId":"A","expr":"up","datasourceId":1}],"from":"now-1h","to":"now"}'
Enter fullscreen mode Exit fullscreen mode

Real-World Use Case

A platform team automated dashboard creation for every new microservice. When a team deploys a new service, a CI/CD hook calls the Grafana API to create a standard monitoring dashboard — CPU, memory, request rate, error rate, and latency. 200+ services, zero manual dashboard setup.

What You Can Build

  • Dashboard-as-code — version control all your dashboards in Git
  • Multi-tenant monitoring — auto-create dashboards per customer
  • Alert manager — programmatic alert rules based on SLO definitions
  • Observability portal — custom UI that embeds Grafana panels

Need custom monitoring automation? I build observability tools and DevOps pipelines.

Email me: spinov001@gmail.com
Check out my developer tools: https://apify.com/spinov001

Top comments (0)