// Comprehensive skill for interacting with Grafana's HTTP API to manage dashboards, data sources, folders, alerting, annotations, users, teams, and organizations. Use when Claude needs to (1) Create, read, update, or delete Grafana dashboards, (2) Manage data sources and connections, (3) Configure alerting rules, contact points, and notification policies, (4) Work with folders and permissions, (5) Manage users, teams, and service accounts, (6) Create or query annotations, (7) Execute queries against data sources, or any other Grafana automation task via API.
| name | grafana-http-api |
| description | Comprehensive skill for interacting with Grafana's HTTP API to manage dashboards, data sources, folders, alerting, annotations, users, teams, and organizations. Use when Claude needs to (1) Create, read, update, or delete Grafana dashboards, (2) Manage data sources and connections, (3) Configure alerting rules, contact points, and notification policies, (4) Work with folders and permissions, (5) Manage users, teams, and service accounts, (6) Create or query annotations, (7) Execute queries against data sources, or any other Grafana automation task via API. |
Programmatically manage Grafana resources including dashboards, data sources, alerting, folders, annotations, users, teams, and organizations.
curl -H "Authorization: Bearer <SERVICE_ACCOUNT_TOKEN>" \
-H "Content-Type: application/json" \
https://your-grafana.com/api/dashboards/home
curl -u admin:admin https://your-grafana.com/api/org
Use X-Grafana-Org-Id header to specify target organization:
curl -H "Authorization: Bearer <TOKEN>" \
-H "X-Grafana-Org-Id: 2" \
https://your-grafana.com/api/org
Search dashboards:
GET /api/search?type=dash-db&query=<search_term>&tag=<tag>&folderIds=<folder_id>
Get dashboard by UID:
GET /api/dashboards/uid/<dashboard_uid>
Create/Update dashboard:
POST /api/dashboards/db
{
"dashboard": {
"id": null,
"uid": null,
"title": "Production Overview",
"tags": ["templated"],
"timezone": "browser",
"schemaVersion": 16,
"refresh": "25s"
},
"folderUid": "l3KqBxCMz",
"message": "Made changes to xyz",
"overwrite": false
}
Delete dashboard:
DELETE /api/dashboards/uid/<dashboard_uid>
List all data sources:
GET /api/datasources
Get data source by UID:
GET /api/datasources/uid/<datasource_uid>
Create data source:
POST /api/datasources
{
"name": "Prometheus",
"type": "prometheus",
"url": "http://prometheus:9090",
"access": "proxy",
"basicAuth": false,
"isDefault": true
}
Query data source:
POST /api/ds/query
{
"queries": [
{
"refId": "A",
"datasource": { "uid": "<datasource_uid>" },
"expr": "up",
"intervalMs": 1000,
"maxDataPoints": 43200
}
],
"from": "now-1h",
"to": "now"
}
Health check:
GET /api/datasources/uid/<datasource_uid>/health
List folders:
GET /api/folders
Create folder:
POST /api/folders
{
"title": "My Folder",
"uid": "my-folder-uid"
}
Get folder:
GET /api/folders/<folder_uid>
Update folder:
PUT /api/folders/<folder_uid>
{
"title": "Updated Folder Title",
"version": 1
}
Delete folder:
DELETE /api/folders/<folder_uid>?forceDeleteRules=true
List all alert rules:
GET /api/v1/provisioning/alert-rules
Get alert rule:
GET /api/v1/provisioning/alert-rules/<rule_uid>
Create alert rule:
POST /api/v1/provisioning/alert-rules
{
"title": "High CPU Alert",
"ruleGroup": "CPU Alerts",
"folderUID": "<folder_uid>",
"noDataState": "OK",
"execErrState": "OK",
"for": "5m",
"condition": "B",
"annotations": { "summary": "CPU usage is high" },
"labels": { "severity": "warning" },
"data": [
{
"refId": "A",
"relativeTimeRange": { "from": 600, "to": 0 },
"datasourceUid": "<datasource_uid>",
"model": {
"expr": "100 - (avg(rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)",
"refId": "A"
}
},
{
"refId": "B",
"relativeTimeRange": { "from": 0, "to": 0 },
"datasourceUid": "-100",
"model": {
"type": "classic_conditions",
"refId": "B",
"conditions": [{
"evaluator": { "type": "gt", "params": [80] },
"operator": { "type": "and" },
"query": { "params": ["A"] },
"reducer": { "type": "avg" }
}]
}
}
]
}
List contact points:
GET /api/v1/provisioning/contact-points
List notification policies:
GET /api/v1/provisioning/policies
Get active alerts:
GET /api/alertmanager/grafana/api/v2/alerts
Query annotations:
GET /api/annotations?from=<epoch_ms>&to=<epoch_ms>&tags=tag1&tags=tag2&limit=100
Create annotation:
POST /api/annotations
{
"dashboardUID": "jcIIG-07z",
"panelId": 2,
"time": 1507037197339,
"timeEnd": 1507180805056,
"tags": ["tag1", "tag2"],
"text": "Annotation Description"
}
Update annotation:
PUT /api/annotations/<annotation_id>
{
"time": 1507037197339,
"timeEnd": 1507180805056,
"text": "Updated annotation",
"tags": ["updated-tag"]
}
Delete annotation:
DELETE /api/annotations/<annotation_id>
Search users (admin):
GET /api/users/search?perpage=10&page=1&query=<search_term>
Get current user:
GET /api/user
List teams:
GET /api/teams/search?perpage=50&page=1&name=<team_name>
Create team:
POST /api/teams
{
"name": "MyTeam",
"email": "team@example.com"
}
Add user to team:
POST /api/teams/<team_id>/members
{
"userId": <user_id>
}
Get current organization:
GET /api/org
List all organizations (admin):
GET /api/orgs
Create organization (admin):
POST /api/orgs
{
"name": "New Org"
}
List service accounts:
GET /api/serviceaccounts/search?perpage=10&page=1
Create service account:
POST /api/serviceaccounts
{
"name": "automation-sa",
"role": "Editor"
}
Create service account token:
POST /api/serviceaccounts/<service_account_id>/tokens
{
"name": "token-name",
"secondsToLive": 86400
}
For detailed API documentation by domain:
Use scripts/grafana_api.py for a reusable Python client:
from grafana_api import GrafanaAPI
# Initialize client
grafana = GrafanaAPI(
base_url="https://your-grafana.com",
token="your-service-account-token"
)
# List dashboards
dashboards = grafana.search_dashboards(query="production")
# Get dashboard details
dashboard = grafana.get_dashboard_by_uid("abc123")
# Create annotation
grafana.create_annotation(
dashboard_uid="abc123",
text="Deployment completed",
tags=["deploy", "production"]
)
# Query data source
result = grafana.query_datasource(
datasource_uid="prometheus-uid",
expr="up",
start="now-1h",
end="now"
)
curl -H "Authorization: Bearer <TOKEN>" \
https://your-grafana.com/api/dashboards/uid/<uid> | jq '.dashboard'
curl -X POST -H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d @dashboard.json \
https://your-grafana.com/api/dashboards/db
dashboards = grafana.search_dashboards(tag="deprecated")
for dash in dashboards:
grafana.delete_dashboard(dash['uid'])
source = grafana.get_dashboard_by_uid("source-uid")
source['dashboard']['id'] = None
source['dashboard']['uid'] = None
source['dashboard']['title'] = f"{source['dashboard']['title']} (Copy)"
source['folderUid'] = "target-folder-uid"
grafana.create_or_update_dashboard(source)
Common HTTP status codes:
200: Success400: Bad request (invalid JSON, missing required fields)401: Unauthorized (invalid/missing token)403: Forbidden (insufficient permissions)404: Not found409: Conflict (resource already exists)412: Precondition failed (version mismatch)422: Unprocessable entity (validation error)overwrite: true carefully: Only when you want to force-updatelimit and page parameters