通过认证 API 查询并受控执行 Kibana 资源操作。
文档
Grafana
试用通过托管 API 代理,对 Grafana 仪表板、数据源、文件夹、注解、告警和团队进行读写操作。
它能做什么
通过托管代理访问已绑定的 Grafana 实例,使用 Bearer 令牌完成鉴权。可对仪表板、文件夹、数据源、注解、团队执行完整的增删改查;告警规则、服务账号、插件仅提供只读接口。所有写入操作在执行前必须向用户展示具体资源标识符并获得明确确认,默认先调用列表接口核对标识符,再发起修改。
什么时候用它
- 跨环境程序化管理 Grafana 仪表板
- 在部署事件触发时自动写入注解
- 重构前审计现有数据源与文件夹清单
- 为新组织单元批量创建 Grafana 团队
技能文档
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://api.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://api.maton.ai/grafana/{native-api-path}
Maton 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://api.maton.ai.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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://api.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. Use a dedicated, least-privilege service account token for this integration — limit it to the specific organization, folders, and resources needed for the task. Avoid admin-role tokens unless specifically required. Rotate the token periodically and revoke it immediately when the connection is no longer needed.
Delete Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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
Security & Permissions
- Access is scoped to dashboards, data sources, folders, annotations, alerts, and teams within the connected Grafana instance. The integration inherits the permissions of the service account token used during connection setup — use least-privilege tokens scoped to the needed organization and folders. Prefer a non-production instance for exploratory work. Remove the connection when no longer needed.
- Default to read-only operations. Always start by listing or retrieving resources to confirm identifiers before proposing any changes.
- All write operations require explicit user approval with specific identifiers. Before executing any POST, PUT, PATCH, or DELETE call:
- Retrieve and display the target resource (dashboard title/UID, folder name, data source name, alert rule) so the user can verify.
- Clearly describe the intended effect (e.g., "This will delete dashboard 'Production Overview' (UID: abc-123) from the 'Ops' folder").
- Wait for explicit user confirmation before proceeding.
- High-impact operations require extra caution. Deleting dashboards, modifying alert rules, changing data source configurations, and reorganizing folders can affect monitoring and observability workflows. These actions must include a summary of consequences and require confirmation.
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://api.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://api.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 |
Resources
常见问题
- 支持创建仪表板吗?
- 支持。通过 POST /api/dashboards/db 可新建或更新仪表板,但需要先向用户展示目标标识符并获得明确确认后才执行。
- 哪些功能不在覆盖范围内?
- 实例管理、成员变更、服务账号令牌签发以及插件安装均不在支持范围内。
- 身份认证如何处理?
- 请求通过 MATON_API_KEY 环境变量携带 Bearer 令牌,由代理转发至已连接的 Grafana 实例,复用连接时配置的服务账号令牌权限。
相关技能
Grafana (grafana.com). Use this skill for ANY Grafana request — reading, creating, updating, and deleting data. Whenever a task involves Grafana, use this skill instead of calling the API directly.
通过托管 OAuth 连接访问 Google Analytics,运行报表并管理分析资源配置。
通过托管 OAuth 认证访问 Sentry,管理错误、Issue、项目、团队和发布。
通过 OAuth 网关读写 Netlify 的站点、部署、构建、DNS 与环境变量。
通过托管 OAuth 调用 Confluence Cloud API,管理页面、空间、博客、评论与附件。