Skip to main content

Working with Grafana API

1. Authenticating API Requests

Authentication Method Description Usage Notes
API Key Generated in Grafana UI for service accounts or users Authorization: Bearer <api_key> Can be scoped to specific permissions
Personal Access Token Generated in user profile settings Authorization: Bearer <token> Scoped to user permissions
Basic Auth Username/password combination Authorization: Basic base64(<username>:<password>) Requires Grafana to have basic auth enabled

Example: Using API Key

curl -H "Authorization: Bearer eyJrIjoi..." \
  http://localhost:3000/api/dashboards/home</code>
</pre>
</div>
</div>
<div class="note">
<strong>Note:</strong> API keys can be generated via the Grafana UI under <code>Configuration > API Keys</code> or <code>Service Accounts</code>.
</div>
<div class="warning">
<strong>Warning:</strong> Never expose API keys in client-side code or version control.
</div>
<h2 id="2-using-dashboard-api">2. Using Dashboard API<a href="#2-using-dashboard-api" class="toc__headingLink" aria-label="Link to this section"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></a></h2>
<table>
<tbody>
<tr>
<th>Endpoint</th>
<th>Method</th>
<th>Description</th>
<th>Notes</th>
</tr>
<tr>
<td class="property">/api/dashboards/db</td>
<td>POST</td>
<td>Create a new dashboard</td>
<td>Requires write permissions</td>
</tr>
<tr>
<td class="property">/api/dashboards/db</td>
<td>PUT</td>
<td>Update an existing dashboard</td>
<td>Overwrites the entire dashboard JSON</td>
</tr>
<tr>
<td class="property">/api/dashboards/uid/{uid}</td>
<td>GET</td>
<td>Get a dashboard by UID</td>
<td>Returns full dashboard JSON</td>
</tr>
<tr>
<td class="property">/api/dashboards/id/{id}</td>
<td>GET</td>
<td>Get a dashboard by ID</td>
<td>Returns full dashboard JSON</td>
</tr>
<tr>
<td class="property">/api/dashboards/id/{id}</td>
<td>DELETE</td>
<td>Delete a dashboard by ID</td>
<td>Deletes the dashboard permanently</td>
</tr>
</tbody>
</table>

<div class="example">
<h2 id="example-create-a-new-dashboard">Example: Create a new dashboard<a href="#example-create-a-new-dashboard" class="toc__headingLink" aria-label="Link to this section"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></a></h2>
<div class="codeBlock" data-language="json">
<pre><code>{
  "dashboard": {
    "title": "My New Dashboard",
    "panels": [
      {
        "id": 1,
        "type": "graph",
        "title": "CPU Usage"
      }
    ]
  },
  "folderId": 0,
  "overwrite": false
}

Example: Update an existing dashboard

{
  "dashboard": {
    "id": 123,
    "title": "Updated Dashboard Title",
    "panels": [
      {
        "id": 1,
        "type": "graph",
        "title": "CPU Usage"
      }
    ]
  },
  "overwrite": true
}
Note: The overwrite parameter controls whether to overwrite an existing dashboard with the same name. If set to false, a new version will be created.

3. Using Data Source API

Endpoint Method Description Notes
/api/datasources GET Get all data sources Returns list of data sources with their IDs and names
/api/datasources POST Create a new data source Requires admin permissions
/api/datasources/:id GET Get a specific data source Fetches details of a single data source by ID
/api/datasources/:id PUT Update a data source Updates configuration of an existing data source
/api/datasources/:id DELETE Delete a data source Removes the specified data source from Grafana

Example: Create a new data source

{
  "name": "Prometheus",
  "type": "prometheus",
  "url": "http://localhost:9090",
  "access": "proxy",
  "isDefault": false
}

Example: Update data source configuration

{
  "id": 1,
  "name": "Prometheus Updated",
  "type": "prometheus",
  "url": "http://localhost:9091",
  "access": "proxy",
  "isDefault": true
}
Note: The access field can be either proxy or direct. Proxy mode is recommended for security reasons.
Warning: When updating a data source, make sure to include all existing fields to avoid overwriting them.

4. Using User API

Endpoint Method Description Notes
/api/users GET Get all users Requires admin permissions
/api/users POST Create a new user Requires admin permissions
/api/users/{id} GET Get a specific user by ID
/api/users/{id} PUT Update a user's details
/api/users/{id} DELETE Delete a user Requires admin permissions

Example: Create a new user

{
  "name": "John Doe",
  "email": "john.doe@example.com",
  "login": "johndoe",
  "password": "securePassword123"
}

Example: Update user permissions

{
  "isGrafanaAdmin": true
}
Note: The password field is only required when creating a new user and will be hashed before storage.
Warning: Ensure that the login and email fields are unique across all users in the Grafana instance.

5. Using Organization API

Endpoint Method Description Notes
/api/org GET Get current organization details
/api/org PUT Update current organization details
/api/org/users GET Get all users in current organization
/api/org/users POST Add a user to current organization
/api/org/users/{userId} DELETE Remove a user from current organization

Example: Get Current Organization Details

curl -H "Authorization: Bearer <API_TOKEN>" \
     -H "Content-Type: application/json" \
     https://grafana.example.com/api/org

Example: Update Organization Name

curl -H "Authorization: Bearer <API_TOKEN>" \
     -H "Content-Type: application/json" \
     -X PUT \
     https://grafana.example.com/api/org \
     -d '{"name": "New Org Name"}'

Example: Add User to Organization

curl -H "Authorization: Bearer <API_TOKEN>" \
     -H "Content-Type: application/json" \
     -X POST \
     https://grafana.example.com/api/org/users \
     -d '{"loginOrEmail": "user@example.com", "role": "Editor"}'

6. Using Search API

Field Description Example
query Search query string to match against dashboard titles, tags, and folder names prod
limit Maximum number of results to return (default: 1000) 50
folderIds Array of folder IDs to search within [1, 2]
tag Tag to filter dashboards by database
type Filter by dashboard type (e.g., dash-db, dash-folder) dash-db

Example: Search for dashboards containing "prod"

curl -H "Authorization: Bearer <API_TOKEN>" \
  "http://localhost:3000/api/search?query=prod&limit=10"

Example: Search in specific folders

const searchParams = {
  query: "db",
  folderIds: [1, 3],
  limit: 20
};

fetch("http://localhost:3000/api/search", {
  method: "GET",
  headers: {
    "Authorization": "Bearer <API_TOKEN>",
    "Content-Type": "application/json"
  },
  params: searchParams
})
Note: The search API supports filtering by tags and folder IDs. Results are returned as an array of dashboard objects with minimal metadata.

7. Using Annotation API

Endpoint Method Description Notes
/api/annotations POST Create a new annotation Requires write permission
/api/annotations GET Fetch annotations Supports filtering by time range, dashboard, and tags
/api/annotations/{id} PUT Update an annotation Update by ID
/api/annotations/{id} DELETE Delete an annotation Deletes by ID

Example: Create Annotation

{
  "dashboardId": 123,
  "panelId": 456,
  "time": 1678886400000,
  "text": "Deployment completed",
  "tags": ["deployment", "prod"]
}

Example: Fetch Annotations

curl -H "Authorization: Bearer <token>" \
  "http://localhost:3000/api/annotations?from=1678886400000&to=1678972800000"
Note: Annotations are stored in the Grafana database and can be used for tracking events or changes in your infrastructure.

8. Using Alert API

Endpoint Method Description Notes
/api/v1/rules GET Retrieve all alert rules Requires admin permissions
/api/v1/rules POST Create a new alert rule Supports JSON payload with rule definition
/api/v1/rules/{ruleUID} PUT Update an existing alert rule Rule UID is required to identify the rule
/api/v1/rules/{ruleUID} DELETE Delete an alert rule Rule UID is required to identify the rule

Example: Create an Alert Rule

{
  "name": "CPU Usage Alert",
  "condition": "A > 80",
  "for": "5m",
  "labels": {
    "severity": "warning"
  },
  "annotations": {
    "summary": "High CPU usage detected"
  }
}

Example: Retrieve Alert Rules

curl -H "Authorization: Bearer <API_TOKEN>" \
     -H "Content-Type: application/json" \
     http://localhost:3000/api/v1/rules
Note: Alert rules are managed via the Grafana API v1 and require appropriate permissions to read or modify.

9. Using Snapshot API

Field Description Example
dashboard The dashboard JSON object to create a snapshot from {"title": "My Dashboard", ...}
expires Expiration time in seconds (default is 2592000 = 30 days) 86400
name Name of the snapshot (optional) "Production Metrics"

Example: Create a Snapshot

const snapshot = {
  dashboard: {
    title: "Production Metrics",
    panels: [],
    ...
  },
  expires: 86400,
  name: "Daily Production Snapshot"
};

fetch("/api/snapshots", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(snapshot)
})
.then(res => res.json())
.then(data => console.log("Snapshot URL:", data.url));
Note: Snapshots are public by default and accessible without authentication. Ensure sensitive dashboards are not shared via snapshots.
Warning: Snapshots are stored in Grafana's database and can consume significant storage if not managed properly.

10. Using Health API

Endpoint Method Description Notes
/api/health GET Check Grafana server health status Returns status of the Grafana instance including version, database status, and uptime

Example: Check Grafana Health

curl -H "Authorization: Bearer <API_TOKEN>" http://localhost:3000/api/health

Example: Health Response

{
  "commit": "abc123",
  "database": "connected",
  "edition": "oss",
  "version": "11.0.0"
}

11. Using Folder API

Endpoint Method Description Notes
/api/folders GET Get all folders Returns list of folders with basic info
/api/folders POST Create a new folder Requires title and UID (optional)
/api/folders/folderUid GET Get folder by UID Returns full folder details
/api/folders/folderUid PUT Update folder Update title or description
/api/folders/folderUid DELETE Delete folder Deletes folder and all dashboards inside

Example: Create a new folder

{
  "title": "Production Dashboards",
  "uid": "prod-dash"
}

Example: Get all folders

curl --request GET \
  --url 'http://localhost:3000/api/folders' \
  --header 'Authorization: Bearer <your_token>'

Example: Update folder title

{
  "title": "Updated Production Dashboards",
  "uid": "prod-dash"
}
Note: Folder UIDs are unique identifiers used to reference folders in API calls.

12. Handling API Errors

Error Code Description Handling Recommendation
400 Bad Request - Invalid syntax or malformed request Validate input parameters and request format before sending
401 Unauthorized - Missing or invalid API key/token Ensure valid authentication credentials are included in the request header
403 Forbidden - Insufficient permissions to access resource Verify user role and permissions in Grafana
404 Not Found - Resource does not exist Check resource ID or path for correctness
429 Rate Limited - Too many requests within time window Implement retry logic with exponential backoff
500 Internal Server Error - Server-side issue Retry after delay or contact Grafana support
503 Service Unavailable - Grafana is temporarily unavailable Implement circuit breaker pattern and retry logic

Example: Error Handling in JavaScript

const response = await fetch("https://grafana.example.com/api/dashboards/uid/my-dashboard", {
  headers: {
    "Authorization": "Bearer <API_TOKEN>"
  }
});

if (!response.ok) {
  switch (response.status) {
    case 400:
      console.error("Invalid request parameters");
      break;
    case 401:
      console.error("Authentication failed");
      break;
    case 403:
      console.error("Access denied");
      break;
    case 404:
      console.error("Dashboard not found");
      break;
    case 429:
      console.error("Rate limit exceeded");
      break;
    default:
      console.error(`Unexpected error: ${response.status}`);
  }
} else {
  const data = await response.json();
  console.log("Dashboard loaded successfully", data);
}
Note: Grafana API responses include a X-Response-Time header that can help identify performance issues related to API errors.
Warning: Always implement retry logic with exponential backoff for 429 (Rate Limited) and 503 (Service Unavailable) errors to prevent overwhelming the server.

Was this article helpful?