So I have been trying to get a list of the dashboards of different organizations using the API. Using the search endpoint I get a list of dashboards but it is always the same organization. I tried changing the active organization of the user but I still get the dashboards of another organization.
How can I use the search endpoint to return the dashboards of a particular organization?
- What Grafana version and what operating system are you using?
9.5.6
- What are you trying to achieve?
I want to get a list of dashboards of an organization.
- How are you trying to achieve it?
I am using the API endpoint " Folder/Dashboard Search API" and also changing the active organization:
GET https://dashboard.domain.tld/api/search?type=dash-db&limit=5000&sort=name_sort
POST https://dashboard.domain.tld/api/user/using/15
This returns a list of dashboards but it is always the same organization.
This post popped up on a search when I was trying to do this exact thing. What I found through trial and error (and maybe a bit of RTFM), is that one needs to authenticate the dashboard API request(s) using HTTP Basic authentication (using a username and password), not HTTP Bearer authentication (using an API key).
Here’s a simple script I wrote to iterate over all the orgs, getting all the dashboards for each org. Technically this is ZSH, but it should work in Bash. This works when run against Grafana Open Source version 11.1.0 as of July, 2024. Set the first three shell parameters accordingly.
ROOT_DIR='/tmp/grafana'
GRAFHOST='http://localhost:3000/'
GRAFANA_WEB_UI_CRED=$(echo -e 'username:password\c' | base64)"
# Iterate over all organizations.
curl --silent -H "Authorization: Basic ${GRAFANA_WEB_UI_CRED}" "${GRAFHOST}"/api/orgs |
jq 'sort_by(.id) | .[] | "\(.id):\(.name)"' -r | while read -r org_id_name ; do
org_id="${org_id_name%:*}"
org_name="${org_id_name#*:// /_}"
# Switch to this org.
curl --silent -X POST -H "Authorization: Basic ${GRAFANA_WEB_UI_CRED}" "${GRAFHOST}"/api/user/using/${org_id}
# Display the current org name.
printf '%s\n' "${org_name//_/ }"
mkdir -p ${ROOT_DIR}/dashboards/"${org_id_name// /_}"
# Save all the dashboards in the org directory using the dashboard
# UID as the filename.
for dash_uid_uri in $(curl --silent -H "Authorization: Basic ${GRAFANA_WEB_UI_CRED}" "${GRAFHOST}"/api/search | jq 'sort_by(.id) | .[] | "\(.uid):\(.uri)"' -r) ; do
dash_uid=${dash_uid_uri%:*}
dash_name=${dash_uid_uri#*/}
# Get the dashboard contents, saving it in the org_id
# directory.
curl --silent -H "Authorization: Basic ${GRAFANA_WEB_UI_CRED}" "${GRAFHOST}"/api/dashboards/uid/${dash_uid} |
jq . > ${ROOT_DIR}/dashboards/"${org_id_name// /_}"/${dash_name}.json
done
done
Oh thanks for posting this.
We solved the issue as well, if I remember correctly, you need to solect the organization using the header x-grafana-org-id. Here is the code for airflow.
def trigger_dashboard_harvest_dashboards(**context): #grafana
dashboard_authorization = Variable.get("dashboard_authorization")
dashboard_password = Variable.get("dashboard_password")
dashboard_username = Variable.get("dashboard_username")
dashboard_url = Variable.get("dashboard_url")
dashboard_org_nice_name = context['dag_run'].conf['LabName']
dashboard_org_id = context['dag_run'].conf['LabSlug']
dashboard_resource_list = {"DASHBOARD":[]}
# Encodes username
input_string = dashboard_username + ":" + dashboard_password
encoded_bytes = base64.b64encode( input_string.encode('utf-8') )
dashboard_basic_auth = encoded_bytes.decode('utf-8')
payload = {}
headers = {
'Accept': 'application/json',
'Authorization': 'Basic {dashboard_basic_auth}'.format( **{"dashboard_basic_auth":dashboard_basic_auth} )
}
# Get id of organization
url = f"{dashboard_url}/api/orgs/name/{dashboard_org_id}"
response, result = request_handler("GET", url, headers=headers, data=payload, valid_statuses=[200])
org_id = response.json()["id"]
# Needed because of x-grafana-org-id
headers = {
'Accept': 'application/json',
'x-grafana-org-id': '{id}'.format( **{"id":org_id} ),
'Authorization': 'Basic {dashboard_basic_auth}'.format( **{"dashboard_basic_auth":dashboard_basic_auth} )
}
# Get list of dashboards
url = dashboard_url + "/api/search?type=dash-db"
response, result = request_handler("GET", url, headers=headers, data=payload, valid_statuses=[200])
for dashboard in response.json():
resource_name = str(dashboard["title"])
resource_type = "DASHBOARD"
this_dashboard_url = str( dashboard["url"] )
resource_url = f"{dashboard_url}{this_dashboard_url}?orgId={org_id}"
resource_embed_url = ""
resource_original_id = str(dashboard["id"])
# Get more details of dashboard
dashboard_uid = dashboard["uid"]
url = f"{dashboard_url}/api/dashboards/uid/{dashboard_uid}"
response, result = request_handler("GET", url, headers=headers, data=payload, valid_statuses=[200])
# if dashboard is shared get the public link
if response.json()["meta"]["publicDashboardEnabled"] == True:
url = f"{dashboard_url}/api/dashboards/uid/{dashboard_uid}/public-dashboards"
response, result = request_handler("GET", url, headers=headers, data=payload, valid_statuses=[200])
access_token = response.json()["accessToken"]
resource_embed_url = f"{dashboard_url}/public-dashboards/{access_token}"
return