# Dashboards API

Project dashboards let you build persistent, shareable views over normalized telemetry. Each
dashboard is a collection of widgets that query traces, spans, logs, metrics, or conversations.
Queries are executed by the telemetry backend and streamed to the Workbench.

## When To Use It

Use the Dashboards API when you want to:

- create or update dashboards programmatically;
- embed dashboard definitions in project configuration;
- run ad-hoc widget queries outside the Workbench.

For interactive exploration, use the Workbench **Dashboards** view.

## Dashboard Definition

A dashboard contains a list of widgets. Each widget specifies a data source, visualization type,
time range, and query. The exact shape is validated by the dashboard normalizer in
`@provon/observability/dashboards`.

Common widget types include metric charts, trace lists, conversation tables, and value cards. Time
ranges can be absolute or relative, for example `last_24h` or `last_7d`.

## List Dashboards

```bash
curl "$PROVON_API_URL/projects/$PROJECT_ID/dashboards" \
  -H "Authorization: Bearer $PROVON_API_KEY"
```

## Create A Dashboard

```bash
curl -X POST "$PROVON_API_URL/projects/$PROJECT_ID/dashboards" \
  -H "Authorization: Bearer $PROVON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Gateway health",
    "description": "Request volume, errors, and latency",
    "widgets": [
      {
        "id": "requests",
        "type": "metric_chart",
        "title": "Gateway requests",
        "source": "traces",
        "timeRange": "last_24h",
        "query": { ... }
      }
    ]
  }'
```

## Get, Update, And Delete

```bash
# Get
curl "$PROVON_API_URL/projects/$PROJECT_ID/dashboards/$DASHBOARD_ID" \
  -H "Authorization: Bearer $PROVON_API_KEY"

# Update
curl -X PATCH "$PROVON_API_URL/projects/$PROJECT_ID/dashboards/$DASHBOARD_ID" \
  -H "Authorization: Bearer $PROVON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Updated name", "widgets": [ ... ]}'

# Delete
curl -X DELETE "$PROVON_API_URL/projects/$PROJECT_ID/dashboards/$DASHBOARD_ID" \
  -H "Authorization: Bearer $PROVON_API_KEY"
```

## Set The Default Dashboard

```bash
curl -X PUT "$PROVON_API_URL/projects/$PROJECT_ID/default-dashboard" \
  -H "Authorization: Bearer $PROVON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"dashboardId": "<dashboard-id>"}'
```

The default dashboard is shown first when a project opens the Dashboards view.

## Execute A Widget Query

Run a dashboard query and stream results:

```bash
curl -X POST "$PROVON_API_URL/projects/$PROJECT_ID/dashboard-queries" \
  -H "Authorization: Bearer $PROVON_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "widgets": [
      {
        "id": "requests",
        "type": "metric_chart",
        "source": "traces",
        "timeRange": "last_24h",
        "query": { ... }
      }
    ]
  }'
```

The response is a Server-Sent Events stream (`text/event-stream`). Up to 24 widgets can be
requested and up to 3 are executed concurrently.

### Stream Events

| Event         | Purpose                                                                                                            |
| ------------- | ------------------------------------------------------------------------------------------------------------------ |
| `init`        | Sent once with `totalWidgets` and `maxConcurrency`.                                                                |
| `progress`    | Sent when a widget completes, with `completedWidgets`, `totalWidgets`, `percent`, and `durationMs`.                |
| `widget_data` | Sent once per widget with `widgetId`, `status` (`success` or `error`), `rows`, optional `trend`, and `durationMs`. |
| `complete`    | Sent once at the end with `success`, `durationMs`, and `completedWidgets`.                                         |
| `error`       | Sent on stream processing failure.                                                                                 |

Example stream:

```text
event: init
data: {"totalWidgets":2,"maxConcurrency":3}

event: widget_data
data: {"widgetId":"requests","status":"success","rows":[...],"trend":null,"durationMs":120}

event: progress
data: {"completedWidgets":1,"totalWidgets":2,"percent":50,"durationMs":120}

event: widget_data
data: {"widgetId":"errors","status":"error","error":"...","rows":[],"durationMs":45}

event: progress
data: {"completedWidgets":2,"totalWidgets":2,"percent":100,"durationMs":165}

event: complete
data: {"success":true,"durationMs":165,"completedWidgets":2}
```

The client should read events until the stream closes and handle `error` events as failures.

## Capability Requirements

The project API key needs:

- `workspace:read` or `project:read` to list and get dashboards;
- `workspace:write` or `project:update` to create, update, delete, and set the default dashboard;
- `telemetry:read` or `project:data:read` to execute dashboard queries.

## Limitations

- Dashboard definitions are project-scoped; sharing across projects requires copying the definition.
- Widget query syntax is validated by the telemetry backend and may differ slightly between DuckDB
  and Cloudflare R2 SQL deployments.
- The API does not render charts; it returns the query result data and metadata that the Workbench
  visualizes.
