Overview
Dashboards let you create custom visualizations of your call data. Each dashboard contains widgets — individual charts that plot a specific field using filters, chart types, and aggregation functions. Key concepts:- Dashboard — a container that holds widgets and defines shared filters applied to all widgets within it.
- Widget — a single chart that plots one field (e.g. call duration, success rate, metric scores).
- Filters — JSON-based query conditions applied at the dashboard level, widget level, or both.
Using dashboards in the app
Dashboards live under Dashboards in the sidebar. The rest of this guide covers the underlying configuration and API; this section walks through the UI.Creating a dashboard
The first time you open Dashboards you’ll see an empty state. Click Create dashboard, give it a name, and you’ll land on the new (empty) dashboard ready for widgets.Dashboard controls
Every dashboard has a control bar:- Date range — pick the window all widgets plot, up to the last 30 days (see Time range).
- Agent filter — scope every widget to one or more agents, or leave it on All agents.
- Add widget, Refresh, and an Edit toggle.
- A ⋮ menu to rename, duplicate, or delete the dashboard, or include it in the daily report email.
Adding a widget
Click Add widget to open the widget editor:- Name the widget.
- Choose what to plot — a call data field (success, duration,
call_ended_reason, a custom metadata key, …) or a metric. - Pick a chart type (line, bar, pie, list, or stat).
- For time-series charts, choose a time period (hour/day/week/month) and an aggregation (count, sum, avg, min, max, …).
- Optionally group by a dimension and add widget-level filters.
- Save. The widget appears on the grid.
Arranging widgets
Toggle Edit to rearrange the grid: drag widgets to reorder them, edit, duplicate, or remove them, then Save. Undo reverts unsaved changes.Exploring data
Hover any chart for exact values. Click a data point to open a side sheet of the call logs behind it, filtered to that bucket and group — a fast way to go from a spike on the chart to the individual calls that caused it.Creating an alert from a widget
For any widget that plots a metric, you can set up an alert on that metric without leaving the dashboard. Open the widget’s ⋮ menu and choose Create alert on this metric — the New alert drawer opens with the widget’s metric already selected, so you just pick the alert type and Slack delivery and save.This option only appears on metric-based widgets (those plotting
metric_evaluations.value with a metric selected). Widgets built on call-data
fields like success or duration don’t show it.Time range
A dashboard’s date range controls the window every widget plots, and it is capped at 30 days. This limit applies both to the dashboard UI and to the widget data API endpoints (GET /dashboards/widgets/{id}/data/ and
POST /dashboards/widgets/preview_data/):
- You can select any window from the last 5 minutes up to the last 30 days, using the quick ranges (Last 1 hour, Last 24 hours, Last 7 days, Last 30 days, …) or a custom from/to range.
- A custom range cannot span more than 30 days, and its start cannot be
earlier than 30 days ago. Any request whose start timestamp (
timestamp_gte) is older than 30 days returns400 {"detail": "Timestamp filter value is too far in the past. Maximum allowed range is 30 days."}— regardless of the window width. Splitting a longer period into ≤30-day sub-ranges does not bypass the limit if any sub-range’s start is older than 30 days.
This limit is by design: long-range aggregation queries impose significant
server load. It applies to both the UI and the widget data API endpoints —
not just the interactive dashboard view. There is currently no API endpoint
that returns server-side aggregated call metrics (call volume per day, enum
breakdowns, metric counts) for date ranges older than 30 days. For historical
analysis beyond 30 days, use the call logs API
(
GET /observability/v1/call-logs/) with arbitrary timestamp filters and
aggregate client-side.Filters
Filters are used on both dashboards and widgets to scope the data being visualized. Dashboard-level filters apply to all widgets, and widget-level filters apply only to that widget. When both are present, they are combined with AND logic.Filter Structure
A filter is a JSON object. It can be a single condition or a group of conditions combined with a logical operator. Single condition:Logical Operators
Comparison Operators
Supported Filter Fields
Call Log Fields
Related Model Fields
Metadata Fields
You can filter on top-level metadata keys using dot notation:Only top-level metadata keys are supported. Nested keys like
metadata.address.city are not allowed.Metric Evaluation Fields
Relative Datetime Values
Datetime fields support relative values for dynamic time-based filtering:
Supported time units:
s (seconds), m (minutes), h (hours), d (days), w (weeks), M (months), y (years).
Example — calls from the last 7 days:
Widgets
A widget plots a single field as a chart. You configure it with a field, chart type, and optional aggregation and time period.Supported Fields
Chart Types
Aggregation Functions
Used withbar charts to aggregate values within each time bucket.
Time Periods
Used withbar charts to define the time bucket size.
Valid Combinations
Not all field + chart type + aggregation combinations are valid. The rules depend on the field’s data type:The
metric_evaluations.value field is dynamic — its data type and allowed chart types depend on the selected metric’s evaluation type. For example, an ENUM metric only supports pie charts, while a NUMERIC metric supports line, bar, and pie.Chart Output Formats
Line chart — individual data points:call_ended_reason with pie chart):
Widget Data
Use the Get Widget Data endpoint to fetch the plot data for a saved widget. You can optionally override the widget’s filters by passing afilters query parameter as a JSON string.
Use Preview Widget Data to test a widget configuration before saving it — pass the full widget definition in the request body along with optional dashboard_filters to preview what the chart would look like.
How Filters Are Applied
When fetching widget data, filters are merged in this order:- Dashboard filters — applied to all widgets in the dashboard.
- Widget filters — applied to this specific widget only.
- Override filters (optional) — passed at request time via the
filtersparameter.
Metadata in Widgets
You can visualize any top-level metadata key as a widget field using themetadata.* prefix. For example, to chart the distribution of a custom region field you set on your calls:
- Field:
metadata.region - Chart type:
pie
pie and bar chart types with count aggregation.
Only top-level metadata keys are supported for widget fields. Nested metadata keys are not supported.