statsig-dashboard
Create Statsig Dashboard
Build valid dashboard API requests for the console v1 dashboards API and execute them with the bundled scripts.
Read references/dashboard-api.md for the exact field-level schema, supported values, and ready-to-edit examples.
The command examples below assume you are running from this skill directory.
Quick Start
- Export the API key:
export STATSIG_CONSOLE_API_KEY="..." - Save the request body to a JSON file.
- Run the matching script:
python3 scripts/create_dashboard.py \
--body-file /tmp/dashboard.json
Companion Scripts
scripts/create_dashboard.py: create a new dashboard withPOST /console/v1/dashboardsscripts/read_dashboard.py: fetch a dashboard and print a create-compatible shape by default usingGET /console/v1/dashboards/{id}scripts/add_dashboard_widgets.py: append widgets withPOST /console/v1/dashboards/{id}/widgetsscripts/replace_dashboard_widgets.py: replace all widgets withPUT /console/v1/dashboards/{id}/widgets
Workflow
- Choose the correct endpoint:
- create a dashboard:
create_dashboard.py - read a dashboard in create-compatible shape:
read_dashboard.py - append widgets:
add_dashboard_widgets.py - replace all widgets:
replace_dashboard_widgets.py
- create a dashboard:
- Build the matching request body for the chosen endpoint.
- Include only supported fields:
namedescriptiondefaultswidgets
- Map each requested widget to one of the supported widget types:
headertexttimeseries- each widget may include optional
widthandheight
- For
timeseries, enforce the query contract exactly:- include exactly one of
sourceorsources - use
type: "event"for each source - include
aggregation - only use supported filter operators and chart types
- if the user wants to group by or filter by event value, use
!statsig_valuerather thanvalue
- include exactly one of
- Execute the matching script.
- Return the API response, or summarize the created dashboard ID or widget IDs if that is all the user needs.
Service Filters
When a widget needs to scope to a Statsig service, prefer filtering on:
{
"property": {
"key": "custom.service",
"column": "user_object"
},
"operator": "EQ",
"values": ["service-name"]
}
Do not default to bare service when building dashboard widgets. In Statsig event payloads this is commonly nested under user_object.custom, so custom.service is the safer default.
OTEL Aggregations
When a widget targets a metric that may come from OTEL, sample the metric first and inspect company_metadata.__metric_type.
- If
__metric_typeis present, treat the metric as OTEL-backed and prefer the matching OTEL aggregation family instead of the plain aggregation. - If
__metric_typeis absent on a representative sample, treat it as a non-OTEL metric and use the normal aggregation types.
Preferred mapping:
__metric_type = "gauge": useOTEL_GAUGE__AVG,OTEL_GAUGE__MAX,OTEL_GAUGE__MIN, orOTEL_GAUGE__SUM__metric_type = "counter": useOTEL_COUNTER__SUM,OTEL_COUNTER__AVG,OTEL_COUNTER__MIN, orOTEL_COUNTER__MAX__metric_type = "histogram": use the OTEL histogram aggregations documented inreferences/dashboard-api.md
Keep the aggregation intent the same when converting:
- average-style widgets should become
OTEL_GAUGE__AVGinstead ofAVG - max-style widgets should become
OTEL_GAUGE__MAXinstead ofMAX
Guardrails
- Do not invent unsupported widget types such as tables.
- Do not include layout fields when creating a dashboard. The create endpoint does not accept widget positions.
- Do not include
roworcolumn. The API currently supports widget sizing viawidthandheight, not explicit placement. - Do not include
idin the create request body. - If the user gives you a dashboard from
GET /console/v1/dashboards/{id}, reuse that create-compatible shape but removeid. - Do not use the create endpoint when the user wants to mutate an existing dashboard.
- Prefer markdown formatting in text widgets so the content is readable and structured.
Examples
Minimal dashboard:
cat > /tmp/dashboard.json <<'JSON'
{
"name": "Checkout Overview"
}
JSON
python3 scripts/create_dashboard.py \
--body-file /tmp/dashboard.json
Read an existing dashboard into a reusable create payload:
python3 scripts/read_dashboard.py \
--dashboard-id dash_123
Append widgets to an existing dashboard:
python3 scripts/add_dashboard_widgets.py \
--dashboard-id dash_123 \
--body-file /tmp/add-widgets.json
Replace all widgets on an existing dashboard:
python3 scripts/replace_dashboard_widgets.py \
--dashboard-id dash_123 \
--body-file /tmp/replace-widgets.json
Script Notes
- All scripts read
STATSIG_CONSOLE_API_KEYfrom the environment. - All scripts default
STATSIG_API_VERSIONto20240601. - Pass
--api-versionor setSTATSIG_API_VERSIONto override that default. - All scripts default to
https://api.statsig.com/console/v1/dashboards. - All scripts send the Console API key in the
statsig-api-keyheader. - All scripts send the configured
statsig-api-versionheader. create_dashboard.py,add_dashboard_widgets.py, andreplace_dashboard_widgets.pyaccept:--body-file--body- stdin
read_dashboard.py,add_dashboard_widgets.py, andreplace_dashboard_widgets.pyrequire--dashboard-id.- All scripts support
--dry-run. - All scripts support
--raw. read_dashboard.pyprints the raw GET response only when--rawis set. Otherwise it unwrapsdataand removesid.