Grafana guide
This guide walks through wiring Polaris into Grafana — from data source setup to common dashboard recipes. It assumes you already have a Grafana instance (Cloud or self-hosted) and an API token from Settings → API Tokens.
Choosing a data source
Polaris is a JSON-over-HTTPS API. Any Grafana plugin that can read paginated REST endpoints works. The recommended option is Infinity (yesoreyeram-infinity-datasource) — it handles JSON, query parameters, and authentication headers without custom code.
Other plugins such as JSON API or HTTP work too. The recipes below use Infinity's UI terms; the equivalent settings exist in those plugins.
Add Polaris as a data source
- Open Connections → Data sources → Add data source, pick Infinity.
- Under URL, Headers & Params:
- Add a header
Authorizationwith the valueBearer {token}(use Grafana's secret field).
- Add a header
- (Optional) Pin the Base URL to
https://polaris.revlv.com/v1so per-query URLs can be relative paths like/devices. - Save & test.
Querying Polaris
Each panel uses one query per endpoint. The minimum:
| Setting | Value |
|---|---|
| Type | JSON |
| Source | URL |
| Format | Table (or Time series for telemetry) |
| URL | https://polaris.revlv.com/v1/<endpoint> |
| Parser | Backend (recommended) |
| Root selector | data |
Infinity will auto-detect columns from the first row of data. Override types if it picks the wrong one (e.g. force time to timestamp, clientCount to number).
Pagination
/v1/devices, /v1/clients, and /v1/telemetries are paginated via pageToken. Infinity supports cursor pagination:
- Pagination mode:
Cursor - Cursor parameter:
pageToken - Cursor extraction path:
pageInfo.nextPageToken - Max pages: bound it (e.g.
10) so a misconfigured panel can't sweep your entire fleet.
Dashboard recipes
Live client counts per site (enrichment join)
/v1/connected_clients is intentionally compact — gateway, name, count, timestamp. To plot client counts on a site map or table with project / location columns, join it against /v1/devices on the gateway serial.
Step 1. Add two queries on the same panel:
- Query A —
GET /v1/devices?pageSize=500 - Query B —
GET /v1/connected_clients
Step 2. Align the join column. Add a Rename fields transformation on Query B mapping gatewayId → serialNumber. Both frames now share a serialNumber column.
Step 3. Add a Join by field (or Outer join) transformation with the join field set to serialNumber.
Step 4. Use Organize fields to drop columns you don't need and reorder the rest.
The merged row looks like:
{
"serialNumber": "G1U0471028214",
"deviceName": "AP 2 - Infront of Barangay Hall",
"projectName": "PICS MIS GIDA PH 2",
"siteCode": "DICT_CALABARZON_Pagsangahan-BH",
"administrativeArea": "Calabarzon",
"locality": "San Francisco (Aurora)",
"longitude": 122.6456272,
"latitude": 13.2016695,
"clientCount": 42,
"lastUpdatedAt": "2026-05-12T05:43:02.034328Z"
}
Fleet map
A Geomap panel keyed on the merged frame above gives you a live map of every site, colored by client count or any other field.
- Location mode:
Coords - Latitude field:
latitude - Longitude field:
longitude - Style → Color: by
clientCount(oruptime,alerts, etc.)
Throughput, ping, and signal
/v1/telemetries returns 5-minute samples for every Starlink terminal accessible by your token. Use it for Time series panels.
GET https://polaris.revlv.com/v1/telemetries
- Format:
Time series - Time field:
time - Value fields:
downlinkThroughput,uplinkThroughput,pingLatencyAvg,pingDropRateAvg,snr - Group by
siteCodeto overlay multiple terminals.
Connected client device list
/v1/clients returns individual client devices observed in the last 5 minutes — MAC, IP, hostname, gateway. Use it for a Table panel:
GET https://polaris.revlv.com/v1/clients?pageSize=500
Columns you'll typically keep: time, deviceName (gateway), hostname, mac, ipAddress.
Variables and templating
You can drive panel queries from dashboard variables instead of hard-coded URLs.
Project filter — query /v1/devices once with Infinity in Variable mode, root selector data, value field projectName, regex-deduplicate. Then reference $project in a transformation's filter step.
Site filter — same pattern with siteCode.
Polaris itself doesn't take filter query parameters today, so filtering happens client-side via Grafana transformations.
Alerts
Grafana alerts run on the transformed frame, so the join recipe above gives you everything you need.
A few patterns that work well:
- Gateway offline — alert when
clientCountis0for a gateway that normally has clients, sustained over N evaluation periods. - Drop-rate spike — alert when
pingDropRateAvgfrom/v1/telemetriesexceeds a threshold persiteCode. - Lapsed Starlink — alert when a row in
/v1/devicesis missing for aserialNumberthat was present yesterday (use Grafana's$__rangeor a snapshot transformation).
Caching and rate limits
- Successful responses are cached for 5 minutes per workspace + URL. Panel refresh intervals shorter than 5 minutes will return the cached frame.
- Rate limit: 200 requests / 30 seconds per workspace, shared across all tokens. A typical dashboard with 6–8 panels refreshing every minute fits comfortably; long pageSize sweeps with low cache hit rate can blow through the limit fast — use the Max pages setting on Infinity to cap.
- All timestamps are UTC (ISO 8601). Grafana converts to your browser timezone in the display layer.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Empty table with HTTP 200 | Token has no workspace assigned, or data field key not selected as Root selector. |
401 Unauthorized | Token missing, expired, or revoked. Re-issue from Settings → API Tokens. |
429 Too Many Requests | Sharing the workspace's limit with other clients. Bump panel refresh interval or add Max pages cap. |
| Stale numbers | 5-minute response cache. Wait for TTL or extend dashboard refresh interval to 5 min+. |
| Map shows wrong locations | Network gear (APs, switches) inherits address from its uplink Starlink terminal. Devices not attached to a terminal will have null coordinates. |