Building dashboards one by one in Grafana can quickly become tedious. Clicking through the UI for every change isn’t exactly efficient. There’s a better way.
The Grafana API lets you automate repetitive tasks and extend Grafana’s capabilities beyond the UI. If you're new to monitoring or managing a complex observability setup, understanding the API can make your workflow more efficient and scalable.
What Is the Grafana API (And Why Should You Care?)
The Grafana API isn't just another technical checkbox – it's the backdoor to everything that makes Grafana powerful. At its core, it's a RESTful interface that lets you programmatically control nearly every aspect of your Grafana instance.
Here's the deal: anything you can click in the UI, you can automate with the API. Creating dashboards? Check. Managing users? Yep. Setting up data sources? Absolutely. But that's just scratching the surface.
For developers and DevOps engineers, this means:
- Automation at scale – Create hundreds of dashboards in seconds, not days
- Version control for your monitoring – Git-ify your dashboards and roll back when needed
- Consistent dashboard design – Enforce standards across your organization
- Dynamic dashboards – Generate dashboards that respond to changing infrastructure
The best part? It's all available through simple HTTP requests – no special plugins or tools required.
Getting Started with the Grafana API
Before jumping into the code, you'll need to grab an API key. Think of it as your VIP pass to the Grafana backend.
3 Authentication Options to Get API Key
You've got three ways to authenticate:
- API Keys – Simple but being deprecated in newer versions
- Service Accounts – The recommended approach for automation
- Basic Auth – For when you're testing or in a pinch
For most automation tasks, service accounts are your best bet. Here's how to set one up:
- Navigate to Administration → Service Accounts
- Create a new service account
- Assign appropriate permissions (Viewer, Editor, or Admin)
- Generate and securely store your token
Now you're ready to make your first API call. Let's start with something simple – checking the health of your Grafana instance:
curl -H "Authorization: Bearer your-token-here" https://your-grafana-instance/api/health
If everything's working, you'll get back a simple JSON response:
{
"database": "ok",
"version": "9.5.2"
}
You've just made your first Grafana API call!
3 Essential Grafana API Endpoints for Everyday Use
Let's talk practicality. These are the endpoints you'll find yourself reaching for constantly:
Dashboard Management
Creating and managing dashboards is where the API really shines. Here's how to get all dashboards:
curl -H "Authorization: Bearer your-token-here" https://your-grafana-instance/api/search
To grab a specific dashboard:
curl -H "Authorization: Bearer your-token-here" https://your-grafana-instance/api/dashboards/uid/your-dashboard-uid
And the crown jewel – creating a dashboard:
curl -X POST \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{"dashboard": {"title": "API Created Dashboard", "panels": [...]}, "overwrite": true, "message": "Created via API"}' \
https://your-grafana-instance/api/dashboards/db
Data Source Operations
Data sources are essential for Grafana dashboards, as they provide the metrics and logs that power your visualizations. The Grafana API allows you to manage data sources programmatically instead of configuring them manually through the UI.
1. Listing All Data Sources
curl -H "Authorization: Bearer your-token-here" https://your-grafana-instance/api/datasources
What this does:
- Sends a GET request to the Grafana API to retrieve a list of all configured data sources.
- Uses an Authorization header with a Bearer token (
your-token-here
) to authenticate the request. - The response will return details about each data source, such as their names, types, and connection settings.
2. Creating a New Prometheus Data Source
curl -X POST \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{"name":"My Prometheus","type":"prometheus","url":"http://prometheus:9090","access":"proxy"}' \
https://your-grafana-instance/api/datasources
Breaking it down:
-X POST
→ Specifies that this is a POST request, which is used to create new resources.-H "Authorization: Bearer your-token-here"
→ Authenticates the request using your API token.-H "Content-Type: application/json"
→ Tells Grafana that the request body contains JSON data.-d '{...}'
→ The JSON payload defining the new data source:"name": "My Prometheus"
→ The name of the data source."type": "prometheus"
→ The type of data source (in this case, Prometheus)."url": "http://prometheus:9090"
→ The URL where Prometheus is running."access": "proxy"
→ Defines how Grafana connects to the data source."proxy"
means Grafana will route requests through its backend instead of the user's browser.
- The API endpoint
https://your-grafana-instance/api/datasources
is where Grafana manages data sources.
What happens next?
If the request is successful, Grafana will return a response confirming the creation of the new Prometheus data source. You can now use it in your dashboards without manually configuring it in the UI.
User and Team Management
For those of you managing Grafana at scale:
# List all users
curl -H "Authorization: Bearer your-token-here" https://your-grafana-instance/api/users
# Create a new team
curl -X POST \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{"name":"DevOps Team"}' \
https://your-grafana-instance/api/teams
Breaking it down:
-X POST
→ Specifies that this is a POST request, used to create new resources.-H "Authorization: Bearer your-token-here"
→ Authenticates the request using your API token.-H "Content-Type: application/json"
→ Tells Grafana that the request body contains JSON data.-d '{"name":"DevOps Team"}'
→ The JSON payload that defines the new team:"name": "DevOps Team"
→ Sets the name of the team.
- The API endpoint
https://your-grafana-instance/api/teams
is where Grafana manages team creation.
What happens next?
If successful, the API will return a response with details about the newly created team. You can then assign users to the team, manage permissions, and integrate it with other Grafana features like dashboard access controls.
How to Automate Dashboard Creation with Python
Manually creating and updating dashboards in Grafana can be time-consuming, especially when managing multiple services.
Instead of relying on Bash scripts for simple API calls, Python provides more flexibility and scalability.
The requests
library makes it easy to interact with Grafana’s API and automate dashboard creation.
1. Setting Up API Credentials
import requests
import json
GRAFANA_URL = "https://your-grafana-instance"
API_TOKEN = "your-token-here"
HEADERS = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json"
}
- Imports
requests
andjson
to handle API calls and data processing. - Defines the
GRAFANA_URL
(your Grafana instance URL) andAPI_TOKEN
(your API key for authentication). - Sets up the
HEADERS
, which include authorization and content type (JSON).
2. Loading a Dashboard Template
# Load dashboard template from file
with open('dashboard_template.json', 'r') as f:
dashboard = json.load(f)
- Reads a dashboard template JSON file, which contains the structure of a Grafana dashboard.
- Loads the JSON data into the
dashboard
variable for further modifications.
3. Customizing the Dashboard for Each Service
services = ["auth", "payments", "inventory", "shipping"]
for service in services:
# Customize dashboard for this service
dashboard["dashboard"]["title"] = f"{service.capitalize()} Service Dashboard"
- Defines a list of services (
auth
,payments
,inventory
,shipping
). - Loops through each service and updates the dashboard title to match the service name.
4. Updating Dashboard Panels with Service-Specific Metrics
# Update variables and panel targets
for panel in dashboard["dashboard"]["panels"]:
panel["targets"][0]["expr"] = panel["targets"][0]["expr"].replace("${service}", service)
- Loops through the panels in the dashboard and updates the PromQL expressions to reflect the specific service.
- Uses
.replace("${service}", service)
to dynamically modify queries.
5. Sending the Dashboard to Grafana
# Create the dashboard
response = requests.post(
f"{GRAFANA_URL}/api/dashboards/db",
headers=HEADERS,
json={
"dashboard": dashboard["dashboard"],
"overwrite": True,
"message": f"Updated {service} dashboard via API"
}
)
- Makes a POST request to the Grafana API (
/api/dashboards/db
) to create or update the dashboard. - Includes:
"dashboard": dashboard["dashboard"]
→ The modified dashboard JSON."overwrite": True
→ Ensures existing dashboards with the same name are updated."message"
→ Adds a commit-style message for tracking changes.
6. Handling the API Response
if response.status_code == 200:
print(f"Successfully created dashboard for {service}")
else:
print(f"Failed to create dashboard for {service}: {response.text}")
- Checks the HTTP status code to determine if the request was successful.
- If
200 OK
, prints a success message; otherwise, prints the error response.
Advanced Techniques: Dynamic Dashboards & Alerting
Now that you've got the basics down, let's level up your Grafana API knowledge.
Generating Dashboards Based on Infrastructure Changes
One of the most powerful applications is generating dashboards automatically when your infrastructure changes.
Here's how you might hook this into your Terraform workflow:
def update_dashboards_from_terraform_output(tf_output_file):
"""Create or update dashboards based on Terraform outputs"""
with open(tf_output_file, 'r') as f:
infrastructure = json.load(f)
# For each new service discovered in Terraform output
for service in infrastructure['services']['value']:
# Check if dashboard exists
search_response = requests.get(
f"{GRAFANA_URL}/api/search?query={service['name']}",
headers=HEADERS
)
if len(search_response.json()) == 0:
# No dashboard exists, create from template
create_dashboard_for_service(service)
else:
# Update existing dashboard
update_dashboard_for_service(service, search_response.json()[0]['uid'])
Breaking down the code:
This function automates the creation and updating of Grafana dashboards based on Terraform outputs.
- Read Terraform Output File
- The function opens and loads a JSON file (
tf_output_file
) containing Terraform output data. - This file includes infrastructure details, such as deployed services.
- The function opens and loads a JSON file (
- Iterate Over Services
- It loops through the services listed in the Terraform output (
infrastructure['services']['value']
). - Each service is processed to determine whether a dashboard already exists in Grafana.
- It loops through the services listed in the Terraform output (
- Check for Existing Dashboards
- Sends a GET request to Grafana’s API (
/api/search
) to check if a dashboard already exists for the service. - The
query
parameter filters dashboards by the service name. - If the response is empty (
len(search_response.json()) == 0
), it means no dashboard exists.
- Sends a GET request to Grafana’s API (
- Create or Update Dashboards
- If no dashboard exists, it calls
create_dashboard_for_service(service)
to generate a new dashboard from a template. - If a dashboard already exists, it updates it using
update_dashboard_for_service(service, search_response.json()[0]['uid'])
, passing the existing dashboard’s unique ID (uid
).
- If no dashboard exists, it calls
This ensures that dashboards stay aligned with the current infrastructure state, avoiding manual intervention.
Programmatic Alert Management
Alerts are critical but often overlooked for API automation. Here's how to manage them:
# Create a new alert rule
alert_rule = {
"name": "High Error Rate",
"condition": "C",
"data": [
{"refId": "A", "queryType": "range", "datasourceUid": "prometheus",
"model": {"expr": "sum(rate(http_requests_total{status=~\"5..\"}[5m])) / sum(rate(http_requests_total[5m])) > 0.05"}},
{"refId": "B", "queryType": "range", "datasourceUid": "prometheus",
"model": {"expr": "sum(rate(http_requests_total[5m]))"}},
{"refId": "C", "queryType": "reduce", "reducer": "last", "datasourceUid": "__expr__",
"model": {"expression": "$A > 0.05", "type": "math"}}
],
"noDataState": "OK",
"execErrState": "Error",
"for": "5m",
"labels": {"severity": "warning"},
"annotations": {"summary": "High error rate detected"}
}
response = requests.post(
f"{GRAFANA_URL}/api/ruler/grafana/api/v1/rules/default",
headers=HEADERS,
json=[{
"name": "Error Rates",
"interval": "1m",
"rules": [alert_rule]
}]
)
Breaking down the Code:
This script defines and creates an alert rule in Grafana using its API. The alert rule monitors HTTP request error rates and triggers a warning if the error rate exceeds 5%.
- Define the Alert Rule (
alert_rule
)- The rule is named "High Error Rate" and evaluates conditions using three query steps (
A
,B
, andC
). - Query A: Calculates the error rate by summing HTTP 5xx status requests over a 5-minute window and dividing it by the total request count.
- Query B: Retrieves the total number of HTTP requests in the last 5 minutes.
- Query C: Uses a mathematical expression (
$A > 0.05
) to determine if the error rate exceeds 5%.
- The rule is named "High Error Rate" and evaluates conditions using three query steps (
- Alert Conditions
noDataState: "OK"
→ If no data is available, the system assumes everything is fine.execErrState: "Error"
→ If an execution error occurs, the alert enters an error state.for: "5m"
→ The condition must persist for 5 minutes before triggering the alert.- Labels and Annotations help categorize the alert (
severity: warning
) and provide a summary.
- Send the Alert Rule to Grafana
- A POST request is made to Grafana’s
/api/ruler/grafana/api/v1/rules/default
endpoint. - The rule is grouped under "Error Rates", with a 1-minute evaluation interval.
- The request payload includes the alert rule as a list inside
"rules"
.
- A POST request is made to Grafana’s
Outcome
If the error rate exceeds 5% for more than 5 minutes, Grafana triggers an alert, helping teams detect and respond to high failure rates in real-time.
Grafana API Limitations and Workarounds
Like any tool, the Grafana API has its rough edges. Here are some common challenges and how to handle them:
Version Compatibility Issues
The API changes between versions. To maintain compatibility:
- Use feature detection when possible
- Include version checks in your scripts
- Test automation against staging environments before production
Rate Limiting
For large operations, you might hit rate limits. Solution:
- Implement backoff strategies in your code
- Batch operations where possible
- Run intensive operations during off-hours
Working with Provisioning
Sometimes the API conflicts with provisioning. To handle this:
- Use tags to identify API-managed resources
- Implement safeguards to prevent overwrites
- Consider a hybrid approach for critical components
Practical Use Case: Integrating Grafana API with Last9
Last9 takes your observability to the next level, and combining it with Grafana's API creates a powerful workflow. Here's how to connect these tools:
Setting Up the Last9 Integration
First, establish the connection between Grafana and Last9:
- Create a dedicated service account in Grafana for Last9
- Generate an API key with appropriate permissions
- Configure the Last9 integration with your Grafana URL and API key
Syncing Dashboards with Last9
Once connected, you can sync your dashboards:
import requests
# Last9 API details
LAST9_API_URL = "https://api.last9.io"
LAST9_API_KEY = "your-last9-api-key"
# Get dashboards from Grafana
grafana_dashboards = requests.get(
f"{GRAFANA_URL}/api/search?type=dash-db",
headers=GRAFANA_HEADERS
).json()
# Sync with Last9
for dashboard in grafana_dashboards:
dashboard_details = requests.get(
f"{GRAFANA_URL}/api/dashboards/uid/{dashboard['uid']}",
headers=GRAFANA_HEADERS
).json()
# Send to Last9
requests.post(
f"{LAST9_API_URL}/v1/dashboards/import",
headers={"Authorization": f"Bearer {LAST9_API_KEY}"},
json={
"source": "grafana",
"dashboard": dashboard_details["dashboard"]
}
)
Using Last9's Advanced Features
With this integration, you can now:
- Create service maps that correlate with your Grafana dashboards
- Implement cross-dashboard dependencies
- Set up advanced SLO tracking that complements Grafana's visualizations
The real power comes from automating this entire workflow – keeping Last9 and Grafana in perfect sync as your infrastructure evolves.
Wrapping Up
We've covered a lot of ground, from basic authentication to advanced integrations. Here's how to develop your API strategy:
- Start small – Automate one repetitive task first
- Build a library – Create reusable functions for common operations
- Version control everything – Store your scripts in Git alongside your infrastructure code
- Implement testing – Verify your API interactions before they hit production
- Document your approach – Make sure your team understands the automation
FAQs
What's the difference between Grafana's API v1 and v2?
The main difference is in authentication and endpoint structure. V1 used API keys exclusively, while v2 introduced service account tokens which are more secure and flexible. V2 also reorganized many endpoints for better consistency and added new capabilities for alerting, library panels, and annotations. If you're starting fresh, always go with v2.
Can I use the Grafana API with the cloud-hosted version?
Absolutely. The Grafana Cloud API works essentially the same way as self-hosted instances. The main difference is in authentication – you'll need to use Grafana Cloud API keys or tokens. Also, some enterprise features might have slightly different endpoints, so check the docs for your specific Grafana Cloud tier.
How do I handle API rate limiting?
Grafana implements rate limiting to prevent abuse, but the specifics vary by deployment. For heavy automation:
- Implement exponential backoff in your scripts
- Batch operations where possible (create multiple items in one request)
- Schedule large operations during off-hours
- Monitor HTTP 429 responses and adjust accordingly
Is there an official Grafana API client library?
Grafana doesn't maintain official client libraries, but there are excellent community options:
- For Python:
grafana-client
orgrafanalib
- For Go:
grafana-api-golang-client
- For JavaScript:
grafana-api-js-client
These libraries handle authentication, serialization, and common operations, saving you from writing boilerplate code.
How do I version control my Grafana dashboards?
The API makes this straightforward:
- Export dashboards using the
/api/dashboards/uid/{uid}
endpoint - Store the JSON in your Git repository
- Use CI/CD to deploy changes back to Grafana
- Consider tools like
grafana-dash-gen
to make the process even easier
This approach gives you rollbacks, change history, and proper peer reviews for your monitoring configuration.
Can I migrate dashboards between Grafana instances with the API?
Yes, and it's a common use case:
- Export from the source using GET
/api/dashboards/uid/{uid}
- Modify the result (change data source references if needed)
- Remove the
id
field from the dashboard object - POST to the target instance's
/api/dashboards/db
endpoint
Just be aware that you'll need to handle data source mappings if the instances use different data sources.
How do I debug API issues?
When things go wrong:
- Check HTTP response codes and body content
- Enable debug headers with
X-Grafana-Debug: true
- Verify your authentication token hasn't expired
- Try the operation in the Grafana UI to see if it's an API issue or underlying problem
- Check Grafana server logs for more details