Skip to main content

Dashboards

The CubeAPM Dashboard APIs allow you to programmatically create, read, update, and delete dashboards and their panels.

Accessing Dashboard APIs

The Dashboard APIs are available on the Admin Port (default: 3199).

Example Endpoints:

  • http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/dashboards
  • http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/panels?dashboard_id=1

Supported HTTP APIs

API EndpointMethodDescription
/api/dashboards/api/v1/dashboardsGET, POST, PUT, DELETEManage dashboards.
/api/dashboards/api/v1/panels?dashboard_id={id}POST, PUT, DELETEManage panels on an existing dashboard.

There is no separate GET endpoint for panels. To read panels, use Get Dashboards with ?id={dashboard_id} — the response includes the full panels array.

Authentication

These APIs can be accessed programmatically using the Admin Port 3199.

Headers Required:

  • (Optional) Authorization: Bearer <ADMIN_TOKEN>
  • Content-Type: application/json
info

When http-token-admin is set in CubeAPM's config.properties, all Dashboard API requests (including GET) must include the corresponding token in the Authorization header. If http-token-admin is empty, the header can be omitted.


Dashboards

Create Dashboard

Endpoint: POST http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/dashboards

Creates a new dashboard. Panels can be included in the same request.

Request Parameters

ParameterTypeDescription
titlestringRequired. Display name of the dashboard.
variablesarrayDashboard template variables. Pass [] if none. See Variables.
panelsarrayList of panel objects to create with the dashboard. See Panel Type Examples.
permissionsarrayAccess control. Pass [] for default role-based access. See Permissions.

Curl Example

curl -X POST "http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/dashboards" \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"title": "Service Overview",
"variables": [],
"panels": [
{
"type": "linechart",
"title": "Request Rate",
"layout": { "x": 0, "y": 0, "w": 6, "h": 4 },
"config": {
"query": "",
"unit": "number",
"queries": [
{
"title": "Requests",
"query": "sum(rate(cube_apm_calls_total[5m]))",
"unit": "number",
"formula": "last"
}
],
"legend": { "label": "", "formula": "last", "pos": "bottom" }
}
}
],
"permissions": []
}'

Response Format

Returns the created dashboard object:

FieldTypeDescription
idintegerUnique identifier for the dashboard.
titlestringDashboard title.
variablesarrayDashboard variables.
panelsarrayCreated panels with assigned IDs.
permissionsarrayPermission entries applied to the dashboard.

Example:

{
"id": 1,
"title": "Service Overview",
"variables": [],
"panels": [
{
"id": 1,
"type": "linechart",
"title": "Request Rate",
"layout": { "x": 0, "y": 0, "w": 6, "h": 4 },
"config": {
"query": "",
"unit": "number",
"queries": [
{
"title": "Requests",
"query": "sum(rate(cube_apm_calls_total[5m]))",
"unit": "number",
"formula": "last"
}
],
"legend": { "label": "", "formula": "last", "pos": "bottom" }
},
"dashboardId": 1
}
],
"permissions": []
}

Get Dashboards

Endpoint: GET http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/dashboards

Curl Examples & Response Format

Request:

curl -X GET "http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/dashboards?id=1" \
-H "Authorization: Bearer <ADMIN_TOKEN>"

Response:

Returns a single dashboard object with its panels:

{
"id": 1,
"title": "Service Overview",
"variables": [],
"panels": [
{
"id": 1,
"type": "linechart",
"title": "Request Rate",
"layout": { "x": 0, "y": 0, "w": 6, "h": 4 },
"config": {
"query": "",
"unit": "number",
"queries": [
{
"title": "Requests",
"query": "sum(rate(cube_apm_calls_total[5m]))",
"unit": "number",
"formula": "last"
}
],
"legend": { "label": "", "formula": "last", "pos": "bottom" }
},
"dashboardId": 1
}
],
"permission": "admin"
}
FieldTypeDescription
idintegerUnique identifier for the dashboard.
titlestringDashboard title.
variablesarrayDashboard template variables.
panelsarrayPanels on the dashboard (populated only in single-dashboard GET).
permissionstringEffective access level of the requesting user (viewer, editor, admin).

Update Dashboard

Endpoint: PUT http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/dashboards

Updates dashboard metadata (title, variables) and panel layouts. To add, update, or remove panel content, use the Panels API.

ParameterTypeDescription
idintegerRequired. Dashboard ID to update.
titlestringRequired. Display name.
variablesarrayReplaces the dashboard's variables.
panelsarrayExisting panels by id; only layout is applied.
permissionsarrayReplaces custom access control. Pass [] for role-based.
warning

The PUT request updates the dashboard's title, variables, and permissions. For panels included in the payload, only the layout field is updated on existing panels — panel type, title, and config are not changed via this endpoint.

Curl Example

curl -X PUT "http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/dashboards" \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"id": 1,
"title": "Service Overview (Updated)",
"variables": [],
"panels": [
{
"id": 1,
"layout": { "x": 0, "y": 0, "w": 12, "h": 4 }
}
],
"permissions": []
}'

Returns 204 No Content on success.

Delete Dashboard

Endpoint: DELETE http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/dashboards?id={id}

Deletes a dashboard and its associated resource permissions.

curl -X DELETE "http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/dashboards?id=1" \
-H "Authorization: Bearer <ADMIN_TOKEN>"

Returns 204 No Content on success.


Panels

Panels can be managed individually after a dashboard is created. To read existing panels, use Get Dashboards with a dashboard id — there is no separate panels GET endpoint.

Panel Object

FieldTypeDescription
idintegerPanel ID (required for PUT/DELETE, omit for POST).
typestringPanel type. See Panel Types.
titlestringRequired. Display title for the panel.
layoutobjectGrid position: x, y, w, h.
configobjectPanel-specific configuration (queries, legend, etc.).

Panel Types

TypeDescription
linechartTime-series line chart
scorecardSingle-value metric display
tableTabular data
logsLog viewer panel
markdownStatic markdown text
bar_horizontalHorizontal bar chart
piePie chart
treemapTreemap visualization

Panel Config

Each panel has a config object. Most query-based panels use a queries array (preferred) or a top-level query field. Common fields:

FieldTypeDescription
queriesarrayList of query objects. Each item supports title, query, unit, formula (last, avg, sum), and optional datasource.
querystringLegacy single-query fallback (used only when queries is empty). Prefer queries.
unitstringnumber or time.
legendobjectlabel (string or array), formula (last, avg, sum), pos (none, bottom, right).
stackboolean(linechart) Stack series.
showSearchboolean(table, logs) Show search bar.
defaultSortColinteger(table) Column index to sort by default.
logsobject(logs) Display options — showFieldsSelector, showAllFields, showMenu, showText, showStream, loadOnScroll.
markdownobject(markdown) text and optional fontSize.

Panel Type Examples

{
"type": "linechart",
"title": "Request Rate",
"layout": { "x": 0, "y": 0, "w": 6, "h": 4 },
"config": {
"query": "",
"unit": "number",
"queries": [
{
"title": "Requests",
"query": "sum(rate(cube_apm_calls_total[5m]))",
"unit": "number",
"formula": "last"
}
],
"legend": { "label": "", "formula": "last", "pos": "bottom" },
"stack": false
}
}

Layout Object

FieldTypeDescription
xintegerColumn position in the grid.
yintegerRow position in the grid.
wintegerWidth in grid units.
hintegerHeight in grid units.

Create Panel

Endpoint: POST http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/panels?dashboard_id={id}

curl -X POST "http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/panels?dashboard_id=1" \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"type": "scorecard",
"title": "Error Rate",
"layout": { "x": 6, "y": 0, "w": 3, "h": 2 },
"config": {
"query": "",
"unit": "number",
"queries": [
{
"title": "Errors",
"query": "sum(rate(cube_apm_errors_total[5m]))",
"unit": "number",
"formula": "last"
}
],
"legend": { "label": "", "formula": "last", "pos": "none" }
}
}'

Response Format

Returns the created panel object:

{
"id": 2,
"type": "scorecard",
"title": "Error Rate",
"layout": { "x": 6, "y": 0, "w": 3, "h": 2 },
"config": {
"query": "",
"unit": "number",
"queries": [
{
"title": "Errors",
"query": "sum(rate(cube_apm_errors_total[5m]))",
"unit": "number",
"formula": "last"
}
],
"legend": { "label": "", "formula": "last", "pos": "none" }
},
"dashboardId": 1
}

Update Panel

Endpoint: PUT http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/panels?dashboard_id={id}

warning

Panel type cannot be changed after creation. Include the full panel object with the existing id and type.

curl -X PUT "http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/panels?dashboard_id=1" \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"id": 2,
"type": "scorecard",
"title": "Error Rate (Updated)",
"layout": { "x": 6, "y": 0, "w": 4, "h": 2 },
"config": {
"query": "",
"unit": "number",
"queries": [
{
"title": "Errors",
"query": "sum(rate(cube_apm_errors_total[5m]))",
"unit": "number",
"formula": "last"
}
],
"legend": { "label": "", "formula": "last", "pos": "none" }
}
}'

Returns 204 No Content on success.

Delete Panel

Endpoint: DELETE http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/panels?dashboard_id={dashboard_id}&id={panel_id}

curl -X DELETE "http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/panels?dashboard_id=1&id=2" \
-H "Authorization: Bearer <ADMIN_TOKEN>"

Returns 204 No Content on success.


Dashboard Variables

Variables let dashboards accept dynamic filters (e.g., environment, service name). Reference them in panel queries using {{variable_name}} syntax — CubeAPM substitutes the user's selected value at query time.

FieldTypeDescription
namestringVariable identifier. Referenced in queries as {{name}}.
optionsarraySelectable values for static variables. Leave empty ([]) for dynamic variables.
labelstring(Optional) Metric label or log/trace field whose values are auto-discovered for the dropdown. Used only for dynamic variables. Example: service, env, service.name.
matchstring(Optional) Series selector used only to discover dropdown values for label — not what panels query. For metrics: a PromQL selector (e.g. cube_apm_calls_total or cube_apm_calls_total{env="production"}). For logs/traces: a query filter (empty defaults to *).
datasourcestring(Optional) Where to discover values: prometheus (metric labels), vlogs (log fields), or traces (span fields). Required when label is set. Maps to the UI “Source of options” choices other than “Static list”.
selectionstringsingle or multiple. Use multiple for PromQL label matchers like env{{env}} (inserts ="value" / =~"..."). Use single only when you want the raw value (e.g. env="{{env}}").
initialValueobject(Optional) Default selection. Shape: { "items": ["value"] }. For multiple, you may also set "all": true (match all label values) or "exclude": true (negate the selection).

Static vs dynamic variables

ModeConfigure withDropdown options come from
Staticoptions only (do not set label)The fixed list you provide
Dynamiclabel + datasource (+ optional match)Live discovery from metrics, logs, or traces

When both label and match are set:

  1. CubeAPM uses match to narrow which series/logs/traces to look at.
  2. From that subset, it collects distinct values of the field/label named in label.

Example: label: "service" with match: "cube_apm_calls_total" lists services that appear on that metric. Omit match to list every distinct service value across all metrics in the time range.

info
  • Use {{env}} in queries to refer to the built-in environment picker (cube:env variable).
  • Use {[label]} in queries to refer to a chart label value (e.g., {[service]}).
  • PromQL label matchers (env{{env}}) require selection: "multiple". Substitution then inserts the operator and quotes: one value → ="order", several → =~"order|payment" (or in(...) for logs/traces).
  • selection: "single" inserts the raw value only (no = / quotes). Use that for non-matcher contexts (e.g. env="{{env}}" or URL path segments), not with the env{{env}} pattern.

Example: Static variables

curl -X POST "http://<cubeapm-admin-host>:3199/api/dashboards/api/v1/dashboards" \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"title": "Service Dashboard",
"variables": [
{
"name": "env",
"options": ["production", "staging"],
"selection": "multiple",
"initialValue": { "items": ["production"] }
},
{
"name": "service",
"options": ["order", "payment"],
"selection": "multiple",
"initialValue": { "items": ["order"] }
}
],
"panels": [
{
"type": "linechart",
"title": "Request Rate",
"layout": { "x": 0, "y": 0, "w": 6, "h": 4 },
"config": {
"query": "",
"unit": "number",
"queries": [
{
"title": "Requests",
"query": "sum(rate(cube_apm_calls_total{env{{env}},service{{service}}}[5m]))",
"unit": "number",
"formula": "last"
}
],
"legend": { "label": "", "formula": "last", "pos": "bottom" }
}
}
],
"permissions": []
}'

When env is production and service is order, the query above resolves to:

sum(rate(cube_apm_calls_total{env="production",service="order"}[5m]))
warning

Do not use selection: "single" with the env{{env}} matcher pattern. With no value selected, {{env}} becomes empty and the query turns into invalid PromQL like cube_apm_calls_total{env,service} (VictoriaMetrics then errors with cannot find WITH template for "env").

Example: Dynamic variables (label + match)

{
"variables": [
{
"name": "service",
"options": [],
"label": "service",
"match": "cube_apm_calls_total",
"datasource": "prometheus",
"selection": "multiple",
"initialValue": { "items": ["order"] }
}
]
}

How to Configure Role Based and Custom Permissions

The permissions array in the JSON payload controls who can view and edit a dashboard.

For global roles, teams, and how permissions work in the UI, see Roles and Permissions and Teams.

1. Role Based (Default)

When role-based access is used, the dashboard inherits the user's global workspace role (viewers can view, editors can edit).

Pass an empty array:

{
"...": "...",
"permissions": []
}

2. Custom

Grant specific roles (viewer, editor, or admin) to individual users (by email) or teams (by ID):

{
"...": "...",
"permissions": [
{
"entity_type": "user",
"entity_id": "john.doe@company.com",
"permission": "editor"
},
{
"entity_type": "team",
"entity_id": "4",
"permission": "viewer"
}
]
}
info

Custom permissions form an allowlist in the CubeAPM UI. Only listed users and teams can access the resource there. Effective permission is capped at the user's global role — a global viewer cannot edit even if granted editor on the resource.

info

Admin Port APIs (port 3199) bypass per-resource ACL. They can list, get, update, and delete all dashboards regardless of Custom permissions.

Error Responses

Common failure cases:

StatusWhen
401 Unauthorizedhttp-token-admin is set and the Authorization header is missing or invalid.
400 Bad RequestRequired fields are missing or the request body is invalid (for example, unknown panel type).
404 Not FoundThe dashboard or panel ID does not exist.