Grafana
Access Grafana dashboards, data sources, folders, annotations, and alerts via managed API authentication.
Quick Start
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/grafana/api/search?type=dash-db')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Base URL
https://gateway.maton.ai/grafana/{native-api-path}
The gateway proxies requests to your Grafana instance and automatically injects authentication.
Authentication
All requests require the Maton API key:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Getting Your API Key
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your Grafana connections at https://ctrl.maton.ai.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=grafana&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Create Connection
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'grafana'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Open the returned url in a browser to complete authentication. You'll need to provide your Grafana service account token.
Delete Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
API Reference
Organization & User
Get Current Organization
GET /grafana/api/org
Response:
{
"id": 1,
"name": "Main Org.",
"address": {
"address1": "",
"address2": "",
"city": "",
"zipCode": "",
"state": "",
"country": ""
}
}
Get Current User
GET /grafana/api/user
Response:
{
"id": 1,
"uid": "abc123",
"email": "user@example.com",
"name": "User Name",
"login": "user",
"orgId": 1,
"isGrafanaAdmin": false
}
Dashboards
Search Dashboards
GET /grafana/api/search?type=dash-db
Query Parameters:
type-dash-dbfor dashboards,dash-folderfor foldersquery- Search query stringtag- Filter by tagfolderIds- Filter by folder IDslimit- Max results (default 1000)
Response:
[
{
"id": 1,
"uid": "abc123",
"title": "My Dashboard",
"uri": "db/my-dashboard",
"url": "/d/abc123/my-dashboard",
"type": "dash-db",
"tags": ["production"],
"isStarred": false
}
]
Get Dashboard by UID
GET /grafana/api/dashboards/uid/{uid}
Response:
{
"meta": {
"type": "db",
"canSave": true,
"canEdit": true,
"canAdmin": true,
"canStar": true,
"slug": "my-dashboard",
"url": "/d/abc123/my-dashboard",
"expires": "0001-01-01T00:00:00Z",
"created": "2024-01-01T00:00:00Z",
"updated": "2024-01-02T00:00:00Z",
"version": 1
},
"dashboard": {
"id": 1,
"uid": "abc123",
"title": "My Dashboard",
"tags": ["production"],
"panels": [...],
"schemaVersion": 30,
"version": 1
}
}
Create/Update Dashboard
POST /grafana/api/dashboards/db
Content-Type: application/json
{
"dashboard": {
"title": "New Dashboard",
"panels": [],
"schemaVersion": 30,
"version": 0
},
"folderUid": "optional-folder-uid",
"overwrite": false
}
Response:
{
"id": 1,
"uid": "abc123",
"url": "/d/abc123/new-dashboard",
"status": "success",
"version": 1,
"slug": "new-dashboard"
}
Delete Dashboard
DELETE /grafana/api/dashboards/uid/{uid}
Response:
{
"title": "My Dashboard",
"message": "Dashboard My Dashboard deleted",
"id": 1
}
Get Home Dashboard
GET /grafana/api/dashboards/home
Folders
List Folders
GET /grafana/api/folders
Response:
[
{
"id": 1,
"uid": "folder123",
"title": "My Folder",
"url": "/dashboards/f/folder123/my-folder",
"hasAcl": false,
"canSave": true,
"canEdit": true,
"canAdmin": true
}
]
Get Folder by UID
GET /grafana/api/folders/{uid}
Create Folder
POST /grafana/api/folders
Content-Type: application/json
{
"title": "New Folder"
}
Response:
{
"id": 1,
"uid": "folder123",
"title": "New Folder",
"url": "/dashboards/f/folder123/new-folder",
"hasAcl": false,
"canSave": true,
"canEdit": true,
"canAdmin": true,
"version": 1
}
Update Folder
PUT /grafana/api/folders/{uid}
Content-Type: application/json
{
"title": "Updated Folder Name",
"version": 1
}
Delete Folder
DELETE /grafana/api/folders/{uid}
Data Sources
List Data Sources
GET /grafana/api/datasources
Response:
[
{
"id": 1,
"uid": "ds123",
"orgId": 1,
"name": "Prometheus",
"type": "prometheus",
"access": "proxy",
"url": "http://prometheus:9090",
"isDefault": true,
"readOnly": false
}
]
Get Data Source by ID
GET /grafana/api/datasources/{id}
Get Data Source by UID
GET /grafana/api/datasources/uid/{uid}
Get Data Source by Name
GET /grafana/api/datasources/name/{name}
Create Data Source
POST /grafana/api/datasources
Content-Type: application/json
{
"name": "New Prometheus",
"type": "prometheus",
"url": "http://prometheus:9090",
"access": "proxy",
"isDefault": false
}
Update Data Source
PUT /grafana/api/datasources/{id}
Content-Type: application/json
{
"name": "Updated Prometheus",
"type": "prometheus",
"url": "http://prometheus:9090",
"access": "proxy"
}
Delete Data Source
DELETE /grafana/api/datasources/{id}
Annotations
List Annotations
GET /grafana/api/annotations
Query Parameters:
from- Epoch timestamp (ms)to- Epoch timestamp (ms)dashboardId- Filter by dashboard IDdashboardUID- Filter by dashboard UIDpanelId- Filter by panel IDtags- Filter by tags (comma-separated)limit- Max results
Create Annotation
POST /grafana/api/annotations
Content-Type: application/json
{
"dashboardUID": "abc123",
"time": 1609459200000,
"text": "Deployment completed",
"tags": ["deployment", "production"]
}
Response:
{
"message": "Annotation added",
"id": 1
}
Update Annotation
PUT /grafana/api/annotations/{id}
Content-Type: application/json
{
"text": "Updated annotation text",
"tags": ["updated"]
}
Delete Annotation
DELETE /grafana/api/annotations/{id}
Teams
Search Teams
GET /grafana/api/teams/search
Query Parameters:
query- Search querypage- Page numberperpage- Results per page
Response:
{
"totalCount": 1,
"teams": [
{
"id": 1,
"orgId": 1,
"name": "Engineering",
"email": "engineering@example.com",
"memberCount": 5
}
],
"page": 1,
"perPage": 1000
}
Get Team by ID
GET /grafana/api/teams/{id}
Create Team
POST /grafana/api/teams
Content-Type: application/json
{
"name": "New Team",
"email": "team@example.com"
}
Update Team
PUT /grafana/api/teams/{id}
Content-Type: application/json
{
"name": "Updated Team Name"
}
Delete Team
DELETE /grafana/api/teams/{id}
Alert Rules (Provisioning API)
List Alert Rules
GET /grafana/api/v1/provisioning/alert-rules
Get Alert Rule
GET /grafana/api/v1/provisioning/alert-rules/{uid}
List Alert Rules by Folder
GET /grafana/api/ruler/grafana/api/v1/rules
Service Accounts
Search Service Accounts
GET /grafana/api/serviceaccounts/search
Response:
{
"totalCount": 1,
"serviceAccounts": [
{
"id": 1,
"name": "api-service",
"login": "sa-api-service",
"orgId": 1,
"isDisabled": false,
"role": "Editor"
}
],
"page": 1,
"perPage": 1000
}
Plugins
List Plugins
GET /grafana/api/plugins
Response:
[
{
"name": "Prometheus",
"type": "datasource",
"id": "prometheus",
"enabled": true,
"pinned": false
}
]
Code Examples
JavaScript
const response = await fetch('https://gateway.maton.ai/grafana/api/search?type=dash-db', {
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
});
const dashboards = await response.json();
console.log(dashboards);
Python
import os
import requests
response = requests.get(
'https://gateway.maton.ai/grafana/api/search?type=dash-db',
headers={
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'
}
)
print(response.json())
Notes
- Dashboard UIDs are unique identifiers used in most operations
- Use
/api/search?type=dash-dbto find dashboard UIDs - Folder operations require folder UIDs
- Some admin operations (list all users, orgs) require elevated permissions
- Alert rules use the provisioning API (
/api/v1/provisioning/...) - Annotations require epoch timestamps in milliseconds
Error Handling
| Status | Meaning |
|---|---|
| 200 | Success |
| 400 | Invalid request |
| 401 | Invalid or missing authentication |
| 403 | Permission denied |
| 404 | Resource not found |
| 409 | Conflict (e.g., duplicate name) |
| 412 | Precondition failed (version mismatch) |
| 422 | Unprocessable entity |