> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreflux.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Grafana

> Client-mode REST API connector for a curated Grafana slice: health check, create/list annotations from MQTT alarms, search dashboards, and list Grafana Alertmanager alerts

Technical Preview

## Overview

A client-mode connector for a **curated observability / ITSM** slice of the [Grafana HTTP API](https://grafana.com/docs/grafana/latest/developer-resources/api-reference/http-api/):

| Catalog connector event | Entity / path | Notes |
| - | - | - |
| GET health | `GET /api/health` | Typically **unauthenticated**; expect `"database":"ok"` |
| POST annotations from MQTT | `POST /api/annotations` | Bearer service account token; `text` required; `annotations:create` |
| GET annotations | `GET /api/annotations` | Bearer; query `from` / `to` / `limit` (epoch ms) |
| GET search | `GET /api/search` | Bearer; dashboards / folders (`type=dash-db` or `dash-folder`) |
| GET Alertmanager alerts | `GET /api/alertmanager/grafana/api/v2/alerts` | Bearer; Grafana-managed Alertmanager API v2 |

Default `BASE_ADDRESS` is `https://grafana.example.com` (replace with your OSS / Enterprise host or Grafana Cloud stack URL). Topics use `itsm/grafana/<object>/<verb>`.

> [!NOTE]
>
> Self-hosted and Grafana Cloud share the same `/api/…` path layout. Cloud stacks use a host like `https://&lt;stack&gt;.grafana.net`. Do not put a trailing slash on `BASE_ADDRESS`.

> [!NOTE]
>
> Prefer Hub secrets for the service account token. Create annotation (write) needs a token with `annotations:create`. Public [play.grafana.org](https://play.grafana.org) allows anonymous health and many reads, but POST annotations returned **403** without permissions — not a substitute for your own lab token. Status remains blocked until an authenticated create (or owned-instance smoke) succeeds.

## Basic Syntax

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
# Coreflux REST_API template — Grafana (health, annotations, search, alerts curated slice)
# Auth: Authorization: Bearer {value.json.token} (service account)
# BASE_ADDRESS: https://grafana.example.com  (or Cloud stack URL)
# GetHealth: no Authorization header

DEFINE ROUTE GrafanaRestApi WITH TYPE REST_API
    ADD REST_API_CONFIG
        WITH BASE_ADDRESS "https://grafana.example.com"
        WITH ENABLE_CLIENT "true"
        WITH USE_SSL "true"
        WITH REQUEST_TIMEOUT '60'
        WITH DEFAULT_CONTENT_TYPE "application/json"
    ADD EVENT Gethealth
        WITH SOURCE_TOPIC "itsm/grafana/health/get"
        WITH DESTINATION_TOPIC "itsm/grafana/health/get/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/health"
        WITH HEADERS
            ADD "Accept" "application/json"
    ADD EVENT Createannotation
        WITH SOURCE_TOPIC "itsm/grafana/annotation/create"
        WITH DESTINATION_TOPIC "itsm/grafana/annotation/create/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/api/annotations"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "Authorization" "Bearer {value.json.token}"
        WITH BODY "{payload}"
    ADD EVENT Listannotations
        WITH SOURCE_TOPIC "itsm/grafana/annotation/list"
        WITH DESTINATION_TOPIC "itsm/grafana/annotation/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/annotations?from={value.json.from}&to={value.json.to}&limit={value.json.limit}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "Bearer {value.json.token}"
    ADD EVENT Searchdashboards
        WITH SOURCE_TOPIC "itsm/grafana/dashboard/search"
        WITH DESTINATION_TOPIC "itsm/grafana/dashboard/search/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/search?query={value.json.query}&type={value.json.type}&limit={value.json.limit}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "Bearer {value.json.token}"
    ADD EVENT Listalerts
        WITH SOURCE_TOPIC "itsm/grafana/alert/list"
        WITH DESTINATION_TOPIC "itsm/grafana/alert/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/alertmanager/grafana/api/v2/alerts"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "Bearer {value.json.token}"
```

## Events

| Event | Method | Endpoint | Request topic | Response topic |
| - | - | - | - | - |
| Gethealth | GET | `/api/health` | `itsm/grafana/health/get` | `itsm/grafana/health/get/response` |
| Createannotation | POST | `/api/annotations` | `itsm/grafana/annotation/create` | `itsm/grafana/annotation/create/response` |
| Listannotations | GET | `/api/annotations?from=&to=&limit=` | `itsm/grafana/annotation/list` | `itsm/grafana/annotation/list/response` |
| Searchdashboards | GET | `/api/search?query=&type=&limit=` | `itsm/grafana/dashboard/search` | `itsm/grafana/dashboard/search/response` |
| Listalerts | GET | `/api/alertmanager/grafana/api/v2/alerts` | `itsm/grafana/alert/list` | `itsm/grafana/alert/list/response` |

## Auth

**Service account token (preferred):**

1. Create a Grafana [service account](https://grafana.com/docs/grafana/latest/administration/service-accounts/) and token with roles covering annotation create/read, folder/dashboard search, and alerting read as needed.
2. Set connector `BASE_ADDRESS` to your Grafana host (no trailing slash).
3. Pass `token` on the MQTT request payload so headers resolve:
   * `Authorization: Bearer {value.json.token}`
4. Store the token in Hub secrets / `GET SECRET "GRAFANA_TOKEN"`. Never commit real credentials.

**Basic auth (alternative):**

1. Use a Grafana user (or service account) password / token.
2. Configure `WITH USERNAME` / `WITH PASSWORD GET SECRET "GRAFANA_PASSWORD"` and remove Bearer headers from the events.

**Legacy API keys:** historically sent as Bearer; prefer service accounts.

**GetHealth:** omit Authorization — most installs expose `/api/health` publicly.

## Example payloads

**Health:**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{}
```

**Create annotation from alarm:**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "token": "YOUR_SERVICE_ACCOUNT_TOKEN",
  "text": "Vibration above threshold — Zone A",
  "tags": ["coreflux", "ot", "vibration"],
  "time": 1728000000000
}
```

**List annotations:**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "token": "YOUR_SERVICE_ACCOUNT_TOKEN",
  "from": "1727913600000",
  "to": "1728000000000",
  "limit": "50"
}
```

**Search dashboards:**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "token": "YOUR_SERVICE_ACCOUNT_TOKEN",
  "query": "plant",
  "type": "dash-db",
  "limit": "25"
}
```

**List alerts:**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "token": "YOUR_SERVICE_ACCOUNT_TOKEN"
}
```

## Deploy notes

* Deploy **`GrafanaRestApi.lot` only** (`-addRoute`). Do **not** deploy `hub-metadata.lot` as a connector — it exists for Hub / `-listTemplates` (`ADD METADATA` + `WITH IMAGE` base64).
* Hub category: **REST API Connectors**.
* Doc link: [https://docs.coreflux.org/latest/lot-language/routes/rest-api-apps/grafana](https://docs.coreflux.org/latest/lot-language/routes/rest-api-apps/grafana)

## Related

* [REST API Connectors](/latest/lot-language/routes/rest-api-routes)
* [REST API Apps catalog](/latest/lot-language/routes/rest-api-apps)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.