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

# Dashboards as Code

> Create dashboards from versioned JSON definitions through the API, CLI, and MCP instead of clicking through the UI.

Use dashboards as code when you want a repeatable, reviewable way to create metric dashboards from scripts, repos, or agent workflows.

The same definition shape works across:

* the [Dashboards API](/api-reference/dashboards)
* the Squasher CLI
* the hosted [MCP server](/integrations/mcp)

## Definition format

Dashboard definitions are versioned JSON manifests.

### Valid widget query sources

Every widget's `query.source` field must be one of:

| Source      | What it queries                                                                                                                           |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `metrics`   | OTLP metrics (gauge, sum, histogram, exponential histogram)                                                                               |
| `logs`      | Structured logs ingested via SDK or drains                                                                                                |
| `traces`    | OTLP spans — aggregate `duration_ms` by span name across `count`, `avg`, `p50`, `p90`, `p95`, `p99`. Use `metric_name` for the span name. |
| `errors`    | Error groups + occurrences                                                                                                                |
| `vitals`    | Web vitals (LCP, INP, CLS, etc.)                                                                                                          |
| `fixes`     | Hosted fix-run activity                                                                                                                   |
| `ai`        | AI agent observations                                                                                                                     |
| `ingestion` | Ingestion latency and delivery health                                                                                                     |

`traces` is the right choice when the underlying service already records the span (via the Squasher edge SDK or any OTLP client) and you don't want to also emit a duplicate duration metric. Span attributes are queryable via `group_by` and `filters` (`service`, `status`, or any custom span attribute name).

```json theme={null}
{
  "kind": "dashboard_definition",
  "version": "dashboard-definition/v1",
  "definition_id": "service-latency",
  "name": "Service Latency",
  "description": "Track request latency and volume for one service.",
  "widgets": [
    {
      "widget_id": "request-latency",
      "title": "Request latency",
      "chart_type": "line",
      "position": { "x": 0, "y": 0, "w": 6, "h": 4 },
      "query": {
        "source": "metrics",
        "aggregation": "avg",
        "metric_name": "http.server.duration",
        "metric_type": "hist",
        "service_name": "api",
        "time_range": "24h"
      }
    },
    {
      "widget_id": "request-volume",
      "title": "Request volume",
      "chart_type": "bar",
      "position": { "x": 6, "y": 0, "w": 6, "h": 4 },
      "query": {
        "source": "metrics",
        "aggregation": "sum",
        "metric_name": "http.server.request.count",
        "metric_type": "sum",
        "service_name": "api",
        "time_range": "24h"
      }
    }
  ]
}
```

## API

Apply a definition in one request:

```bash theme={null}
curl https://api.squasher.ai/v1/projects/{project_id}/dashboards/apply \
  -H "x-squasher-key: sq_pk_your_key_here" \
  -H "content-type: application/json" \
  -d @dashboard-apply.json
```

Example request body:

```json theme={null}
{
  "definition": {
    "kind": "dashboard_definition",
    "version": "dashboard-definition/v1",
    "definition_id": "service-latency",
    "name": "Service Latency",
    "widgets": [
      {
        "widget_id": "request-latency",
        "title": "Request latency",
        "chart_type": "line",
        "position": { "x": 0, "y": 0, "w": 6, "h": 4 },
        "query": {
          "source": "metrics",
          "aggregation": "avg",
          "metric_name": "http.server.duration",
          "metric_type": "hist",
          "service_name": "api",
          "time_range": "24h"
        }
      }
    ]
  }
}
```

If you want to update an existing dashboard instead of creating a new one, include `dashboard_id` beside `definition`.

## CLI

List dashboards:

```bash theme={null}
squasher dashboards list --project YOUR_PROJECT_ID
```

List templates:

```bash theme={null}
squasher dashboards templates --project YOUR_PROJECT_ID
```

Create from a template:

```bash theme={null}
squasher dashboards from-template \
  --project YOUR_PROJECT_ID \
  --template-id internal-metrics-average
```

Execute a dashboard query directly:

```bash theme={null}
squasher dashboards query \
  --project YOUR_PROJECT_ID \
  --source metrics \
  --aggregation avg \
  --time-range 24h \
  --metric-name http.server.duration \
  --metric-type hist \
  --service-name api
```

Use `--from` and `--to` for absolute query windows:

```bash theme={null}
squasher dashboards query \
  --project YOUR_PROJECT_ID \
  --source logs \
  --aggregation count \
  --time-range 5m \
  --from 2026-04-01T00:00:00.000Z \
  --to 2026-04-01T00:05:00.000Z
```

Filter log/error dashboard queries with search syntax:

```bash theme={null}
squasher dashboards query \
  --project YOUR_PROJECT_ID \
  --source logs \
  --aggregation count \
  --group-by level \
  --time-range 24h \
  --q 'service_name:api "database timeout"'
```

Apply a definition from a file:

```bash theme={null}
squasher dashboards apply --project YOUR_PROJECT_ID ./dashboard-definition.json
```

To update an existing dashboard in place:

```bash theme={null}
squasher dashboards apply \
  --project YOUR_PROJECT_ID \
  --dashboard-id DASHBOARD_ID \
  ./dashboard-definition.json
```

## MCP

The hosted MCP server exposes the same workflows through Code Mode. Agents should call `search` for the operation they need, then `execute` the generated `squasher.request(...)` example.

Useful searches:

* `search("dashboards.list")`
* `search("dashboards.listTemplates")`
* `search("dashboards.executeQuery")`
* `search("dashboards.inspectQuery")`
* `search("dashboards.apply")`

Example prompt:

```text theme={null}
Apply the dashboard definition in this JSON to project 550e8400-e29b-41d4-a716-446655440000 and return the created dashboard.
```

## Agent handoff

Use this prompt when asking an agent to create or update dashboards:

```text theme={null}
Create a Squasher dashboard definition for project <project_id>. Use the documented dashboard-definition/v1 shape, keep widget ids stable, use supported query sources only, validate with the Dashboards API or CLI, and ask before applying it to the project.
```

The manifest format also powers Squasher's built-in operational dashboard templates, so the same apply surface works for custom dashboards instead of a UI-only flow.

## Related docs

* [Dashboards API](/api-reference/dashboards)
* [Metrics API](/api-reference/metrics)
* [MCP](/integrations/mcp)
