---
title: "Preview Widget"
method: POST
path: "/api/v1/dashboards/widgets/preview"
tags: ["dashboards"]
---

# Preview Widget

`POST /api/v1/dashboards/widgets/preview`

Run a widget config without saving it (Agent-Native PR 3).

The metric layer has had ``POST /metrics/preview`` since the Metrics Composition
program; an assembled widget had no equivalent, so the only way to learn whether
a report produced numbers was to persist it and look. For an agent that is the
wrong order — it should verify before a human sees anything.

The config is validated with the same gate the write path uses, then composed and
executed through ``run_widget_query``. There is no second execution path, and
nothing is persisted.

## Request body

- WidgetPreviewRequest — Run a widget config WITHOUT saving it (Agent-Native PR 3). The metric layer has had a dry run since the Metrics Composition program (``POST /metrics/preview``); an assembled widget had none, so the only way to find out whether a report produced numbers was to persist it and look. That is the wrong order for an agent, which should verify before it shows a human anything.
  - `config` WidgetConfig, required — The query half of a persisted ``Widget.config``. A widget embeds a ``ReportQuery`` rather than naming one, so this is that same query MINUS its identity (``key``/``version``) and minus ``time_dimension`` (which the referenced measures own and import validation pins — a widget never restates it). Same field TYPES throughout, so the two cannot describe different vocabularies. ``extra="allow"`` is deliberate and is the line this model draws: * The QUERY half is strict. A bad ``group_by`` or an unresolvable ref produces a wrong number silently, on a human's screen, inside a report an agent said was correct. That must fail at the boundary. * PRESENTATION keys (``show_na``, ``table_orientation``, ``bar_mode``, ``row_groups``, ``column_colors``, ``group_colors``, ``sticky_first_column``, ``legendPosition`` — note the one camelCase legacy key) ride along unmodelled. Locking them down would 422 real stored configs to protect against a wrong COLOUR, which is not the failure mode worth guarding. Near-miss metric keys (``metric_ref`` for ``metric_refs``) and catalog-shaped entries are coerced by :func:`coerce_widget_config_metric_refs` before the query half is validated, so a find_metric hit pasted verbatim is accepted. Nested ``config.metric_refs`` / ``spec.metric_refs`` hoist the same way (#2457). A config that still has no metrics after that rewrite is rejected.
    - `metric_refs` MetricRef[]
      - `key` string, required
      - `category` 'standard' | 'custom' | 'formula', required
      - `outcome` 'pass' | 'fail', nullable
      - `label` string, nullable
      - `is_after_hours` boolean, nullable
      - `population_filters` string[], nullable
      - `buckets` AttributionBucket[], nullable
    - `aggregation` AggregationSpec — How to aggregate the metric values.
      - `type` 'count' | 'sum' | 'avg' | 'pass_rate' | 'breakdown'
      - `period` 'minute' | 'hour' | 'day' | 'week' | 'month' | 'total' | 'auto'
    - `group_by` string[]
    - `filters` WidgetIntrinsicFilters — The filters a saved query OWNS — ``WidgetFilters`` minus the globals and the date range. Widget-intrinsic filters describe what the widget *is* ("bookings only", "AI-handled conversations"); global dimensions describe what the viewer is currently looking at. Only the first kind may be persisted. Field-for-field equality with ``WidgetFilters`` (minus ``GLOBAL_DIM_KEYS`` and ``TIME_RESOLUTION_KEYS``) is asserted by ``test_intrinsic_filters_match_widget_filters`` — written out explicitly rather than derived with ``create_model`` because a dynamically built model is not statically typeable, and this file is the contract an agent reads out of the OpenAPI schema. ``extra="forbid"`` is the point of the model, not a detail. Pydantic's default would IGNORE a global dimension passed here — silently dropping it, which is the same failure mode as the client's ``console.warn`` strip: the caller believes the filter was saved and it was not. An agent especially must be told, so it learns the rule instead of re-sending it.
      - `matrix_agent_refs` string[], nullable
      - `buckets` AttributionBucket[], nullable
      - `dispositions` string[], nullable
      - `was_transferred` boolean, nullable
      - `transfer_failed` boolean, nullable
      - `was_missed` boolean, nullable
      - `was_answered` boolean, nullable
      - `is_after_hours` boolean, nullable
      - `population_filters` string[], nullable
      - `is_voicemail` boolean, nullable
      - `has_first_response` boolean, nullable
      - `has_ended` boolean, nullable
      - `transfer_destination` string, nullable
      - `country` string, nullable
      - `outcome` string, nullable
      - `has_booking_intent` boolean, nullable
      - `has_booking` boolean, nullable
      - `booking_made` boolean, nullable
      - `local_hour_of_day` integer, nullable
      - `local_day_of_week` integer, nullable
      - `tag_ids` string[], nullable
      - `attribution_tiers` string[], nullable
      - `metric_filters` MetricFilter[], nullable
        - `metric_id` string, required
        - `outcome` 'pass' | 'fail' | 'any' | 'na', nullable
        - `categorical_value` string, nullable
      - `standard_filters` StandardColumnFilter[], nullable
        - `field` string, required
        - `value` string, required
    - `result_shape` 'scalar' | 'timeseries' | 'breakdown' | 'pivot' | 'matrix' | 'records', nullable
    - `metric_filters` MetricFilter[]
      - `metric_id` string, required
      - `outcome` 'pass' | 'fail' | 'any' | 'na', nullable
      - `categorical_value` string, nullable
    - `matrix_agent_refs` string[]
    - `column_rollups` ColumnRollup[]
      - `label` string, required
      - `buckets` AttributionBucket[], required
  - `viz_type` 'line' | 'bar' | 'pie' | 'number' | 'pivot' | 'logs_table' | 'heatmap', required
  - `start_date` string, date, required
  - `end_date` string, date, required
  - `category_id` string, uuid, nullable
  - `property_ids` string[], nullable
  - `property_ids_exclude` string[], nullable

## Response `200`

Successful Response

- WidgetPreviewResponse — What the config produced, AND what it was understood to mean. Returning the composed ``spec`` is the point of the second field: an agent that gets an unexpected number needs to see the query its config turned into — which grouping was defaulted, which filters survived — rather than guessing at the translation.
  - `spec` WidgetQuerySpecOutput, required — Input spec for run_widget_query. ACL context (PR3, all optional/additive — the "then required" tightening is a later frontend migration): ``dashboard_id`` + ``widget_id`` identify a placed widget so the endpoint authorizes ``can_view`` against that dashboard's category; ``category_id`` is the target tab for a live preview, authorized against ``can_edit``. When none are set the spec is a free-form query with no category ACL (documented limitation — see access.py).
    - `dashboard_id` string, uuid, nullable
    - `widget_id` string, uuid, nullable
    - `category_id` string, uuid, nullable
    - `metric_refs` MetricRef[], required
      - `key` string, required
      - `category` 'standard' | 'custom' | 'formula', required
      - `outcome` 'pass' | 'fail', nullable
      - `label` string, nullable
      - `is_after_hours` boolean, nullable
      - `population_filters` string[], nullable
      - `buckets` AttributionBucket[], nullable
    - `aggregation` AggregationSpec — How to aggregate the metric values.
      - `type` 'count' | 'sum' | 'avg' | 'pass_rate' | 'breakdown'
      - `period` 'minute' | 'hour' | 'day' | 'week' | 'month' | 'total' | 'auto'
    - `group_by` string[]
    - `filters` WidgetFilters, required — Filter vocabulary — mirrors useLogsFilters PARAM_MAP exactly. The drill output uses the same snake_case keys so the frontend can deep-link to the logs page with these as URL search params.
      - `start_date` string, date, required
      - `end_date` string, date, required
      - `start_datetime` string, date-time, nullable
      - `end_datetime` string, date-time, nullable
      - `agent_id` string, nullable
      - `outcome_agent_ref` string, nullable
      - `outcome_agent_refs` string[], nullable
      - `matrix_agent_refs` string[], nullable
      - `outcome_agent_kind` 'ai_voice' | 'ai_text' | 'human', nullable
      - `interaction_types` string[], nullable
      - `booking_sources` string[], nullable
      - `property_ids_exclude` string[], nullable
      - `outcome_agent_refs_exclude` string[], nullable
      - `interaction_types_exclude` string[], nullable
      - `booking_sources_exclude` string[], nullable
      - `buckets` AttributionBucket[], nullable
      - `dispositions` string[], nullable
      - `was_transferred` boolean, nullable
      - `transfer_failed` boolean, nullable
      - `was_missed` boolean, nullable
      - `was_answered` boolean, nullable
      - `is_after_hours` boolean, nullable
      - `population_filters` string[], nullable
      - `is_voicemail` boolean, nullable
      - `has_first_response` boolean, nullable
      - `has_ended` boolean, nullable
      - `transfer_destination` string, nullable
      - `country` string, nullable
      - `outcome` string, nullable
      - `has_booking_intent` boolean, nullable
      - `has_booking` boolean, nullable
      - `booking_made` boolean, nullable
      - `local_hour_of_day` integer, nullable
      - `local_day_of_week` integer, nullable
      - `tag_ids` string[], nullable
      - `property_ids` string[], nullable
      - `include_considered_hotels` boolean, nullable
      - `attribution_tiers` string[], nullable
      - `metric_filters` MetricFilter[], nullable
        - `metric_id` string, required
        - `outcome` 'pass' | 'fail' | 'any' | 'na', nullable
        - `categorical_value` string, nullable
      - `standard_filters` StandardColumnFilter[], nullable
        - `field` string, required
        - `value` string, required
    - `filter_clauses` FilterClause[], nullable
      - `field` string, required
      - `value` unknown, required
      - `mode` 'include' | 'exclude'
      - `origin` 'global' | 'widget' | 'metric' | 'drill' | 'component', required
    - `result_shape` 'scalar' | 'timeseries' | 'breakdown' | 'pivot' | 'matrix' | 'records', nullable
    - `comparison` 'previous_period' | 'previous_week' | 'previous_month' | 'previous_year', nullable
    - `records_subject` 'voice' | 'text' | 'email' | 'booking', nullable
    - `column_rollups` ColumnRollup[], nullable
      - `label` string, required
      - `buckets` AttributionBucket[], required
  - `result` WidgetQueryResult, required — Response from the query engine.
    - `data` DataPoint[], required
      - `label` string, nullable
      - `sublabel` string, nullable
      - `value` number, nullable
      - `breakdown` object, nullable
      - `drill` DrillFilter — Typed drill-through filter spec — same keys as useLogsFilters PARAM_MAP. Exposes a concrete schema so the generated TS SDK produces typed access (not Record<string, unknown>).
        - `start_date` string, required
        - `end_date` string, required
        - `agent_id` string, nullable
        - `outcome_agent_ref` string, nullable
        - `outcome_agent_refs` string[], nullable
        - `outcome_agent_kind` string, nullable
        - `channels` string[], nullable
        - `buckets` string[], nullable
        - `dispositions` string[], nullable
        - `property_ids_exclude` string[], nullable
        - `outcome_agent_refs_exclude` string[], nullable
        - `standard_filters` StandardColumnFilter[], nullable
          - `field` string, required
          - `value` string, required
        - `was_transferred` string, nullable
        - `transfer_failed` string, nullable
        - `was_missed` string, nullable
        - `was_answered` string, nullable
        - `is_after_hours` string, nullable
        - `population_filters` string[], nullable
        - `is_voicemail` string, nullable
        - `has_first_response` string, nullable
        - `has_ended` string, nullable
        - `transfer_destination` string, nullable
        - `transfer_failure_reason` string, nullable
        - `country` string, nullable
        - `contact_source` string, nullable
        - `outcome` string, nullable
        - `has_booking_intent` string, nullable
        - `has_booking` string, nullable
        - `booking_made` string, nullable
        - `local_hour_of_day` string, nullable
        - `local_day_of_week` string, nullable
        - `tag_ids` string[], nullable
        - `property_ids` string[], nullable
        - `include_considered_hotels` boolean, nullable
        - `failed_transfer_destination` string, nullable
        - `failed_transfer_tool_name` string, nullable
        - `attempted_transfer_destination` string, nullable
        - `attempted_transfer_tool_name` string, nullable
        - `succeeded_transfer_destination` string, nullable
        - `succeeded_transfer_tool_name` string, nullable
        - `unresolved_transfer_destination` string, nullable
        - `unresolved_transfer_tool_name` string, nullable
        - `metric_filters` MetricFilter[], nullable
          - `metric_id` string, required
          - `outcome` 'pass' | 'fail' | 'any' | 'na', nullable
          - `categorical_value` string, nullable
      - `cell_drills` object, nullable
      - `booking_drill` BookingDrillScope — Drill envelope for canonical booking measures (Direct Bookings PR 9). The filter fields mirror the ``GET /bookings`` query params VERBATIM (pinned by test against the route signature), so a widget cell deep-links to exactly the bookings it aggregated — the same ``apply_booking_list_filters`` predicate serves both sides. The scope fields disclose the full metric definition (date axis + semantics, tz, status and attribution rules, currency, snapshot time) so the /bookings scoped drill mode can label precisely what was measured.
        - `property` string[], nullable
        - `originating_channel` string[], nullable
        - `property_exclude` string[], nullable
        - `originating_channel_exclude` string[], nullable
        - `outcome_agent_refs` string[], nullable
        - `outcome_agent_refs_exclude` string[], nullable
        - `outcome_agent_kind` string, nullable
        - `attribution_tier` string[], nullable
        - `status_code` string[], nullable
        - `booked_from` string, nullable
        - `booked_to` string, nullable
        - `stay_from` string, nullable
        - `stay_to` string, nullable
        - `cancelled_from` string, nullable
        - `cancelled_to` string, nullable
        - `wh_source_id` string, nullable
        - `unknown_commission` boolean, nullable
        - `measure` string, required
        - `date_axis` 'booked' | 'stay' | 'cancelled', required
        - `date_axis_timezone` string
        - `status_rule` string
        - `attribution_rule` string
        - `currency` string, nullable
        - `snapshot_at` string, required
      - `booking_cell_drills` object, nullable
      - `provenance` string, nullable
      - `cell_provenance` object, nullable
      - `comparison_value` number, nullable
      - `delta` number, nullable
      - `delta_pct` number, nullable
    - `records` WidgetRecordRow[], nullable
      - `interaction_id` string, required
      - `subject` 'voice' | 'text' | 'email' | 'booking', required
      - `started_at` string, date-time, nullable
      - `guest` string, nullable
      - `country` string, nullable
      - `value_cents` integer, nullable
      - `value_amount` string, nullable
      - `currency` string, nullable
      - `provenance` string, nullable
    - `records_total` integer, nullable
    - `filter_applicability` object, nullable
    - `empty` EmptyState — Why a widget has nothing to show (design §5a R4). ``None`` on the result means the widget has data; set means the frontend renders a typed empty state (KPI → 0, ratio → —, chart/table → frame kept) with the right caption. - ``intrinsic_conflict``: a specific predicate PROVABLY contradicts the measure's own domain (e.g. a text-sessions measure under ``channel=voice``). ``predicate`` names the conflicting dimension (e.g. ``"channel"``). Derived from the spec, never by a counterfactual query. - ``no_matching_rows``: the active filter set matched nothing and no single filter is provably responsible — generic, with the active filter chips + Clear/Broaden on the frontend. No counterfactual guessing of a culprit. - ``no_tenant_data``: nothing is shown and no narrowing filter is active — the warm fresh-account onboarding state.
      - `kind` 'intrinsic_conflict' | 'no_matching_rows' | 'no_tenant_data', required
      - `predicate` string, nullable
    - `drill` DrillFilter, required — Typed drill-through filter spec — same keys as useLogsFilters PARAM_MAP. Exposes a concrete schema so the generated TS SDK produces typed access (not Record<string, unknown>).
      - `start_date` string, required
      - `end_date` string, required
      - `agent_id` string, nullable
      - `outcome_agent_ref` string, nullable
      - `outcome_agent_refs` string[], nullable
      - `outcome_agent_kind` string, nullable
      - `channels` string[], nullable
      - `buckets` string[], nullable
      - `dispositions` string[], nullable
      - `property_ids_exclude` string[], nullable
      - `outcome_agent_refs_exclude` string[], nullable
      - `standard_filters` StandardColumnFilter[], nullable
        - `field` string, required
        - `value` string, required
      - `was_transferred` string, nullable
      - `transfer_failed` string, nullable
      - `was_missed` string, nullable
      - `was_answered` string, nullable
      - `is_after_hours` string, nullable
      - `population_filters` string[], nullable
      - `is_voicemail` string, nullable
      - `has_first_response` string, nullable
      - `has_ended` string, nullable
      - `transfer_destination` string, nullable
      - `transfer_failure_reason` string, nullable
      - `country` string, nullable
      - `contact_source` string, nullable
      - `outcome` string, nullable
      - `has_booking_intent` string, nullable
      - `has_booking` string, nullable
      - `booking_made` string, nullable
      - `local_hour_of_day` string, nullable
      - `local_day_of_week` string, nullable
      - `tag_ids` string[], nullable
      - `property_ids` string[], nullable
      - `include_considered_hotels` boolean, nullable
      - `failed_transfer_destination` string, nullable
      - `failed_transfer_tool_name` string, nullable
      - `attempted_transfer_destination` string, nullable
      - `attempted_transfer_tool_name` string, nullable
      - `succeeded_transfer_destination` string, nullable
      - `succeeded_transfer_tool_name` string, nullable
      - `unresolved_transfer_destination` string, nullable
      - `unresolved_transfer_tool_name` string, nullable
      - `metric_filters` MetricFilter[], nullable
        - `metric_id` string, required
        - `outcome` 'pass' | 'fail' | 'any' | 'na', nullable
        - `categorical_value` string, nullable
    - `booking_drill` BookingDrillScope — Drill envelope for canonical booking measures (Direct Bookings PR 9). The filter fields mirror the ``GET /bookings`` query params VERBATIM (pinned by test against the route signature), so a widget cell deep-links to exactly the bookings it aggregated — the same ``apply_booking_list_filters`` predicate serves both sides. The scope fields disclose the full metric definition (date axis + semantics, tz, status and attribution rules, currency, snapshot time) so the /bookings scoped drill mode can label precisely what was measured.
      - `property` string[], nullable
      - `originating_channel` string[], nullable
      - `property_exclude` string[], nullable
      - `originating_channel_exclude` string[], nullable
      - `outcome_agent_refs` string[], nullable
      - `outcome_agent_refs_exclude` string[], nullable
      - `outcome_agent_kind` string, nullable
      - `attribution_tier` string[], nullable
      - `status_code` string[], nullable
      - `booked_from` string, nullable
      - `booked_to` string, nullable
      - `stay_from` string, nullable
      - `stay_to` string, nullable
      - `cancelled_from` string, nullable
      - `cancelled_to` string, nullable
      - `wh_source_id` string, nullable
      - `unknown_commission` boolean, nullable
      - `measure` string, required
      - `date_axis` 'booked' | 'stay' | 'cancelled', required
      - `date_axis_timezone` string
      - `status_rule` string
      - `attribution_rule` string
      - `currency` string, nullable
      - `snapshot_at` string, required
    - `bucket_labels` object, nullable
    - `currency` string, nullable
    - `execution` QueryExecution — The per-request provenance header, serialized from the accumulated traces. ``executed_spec`` is the normalized specification that actually executed and ``canonical_query_hash`` is the SHA-256 over it (decision 8) — together the authoritative identity of this execution. ``time_axes`` maps each resolved metric/component to the timestamp column it ranged over, since a ratio may mix axes (PR 23).
      - `executed_at` string, date-time, required
      - `app_release` string, required
      - `schema_version` integer
      - `executed_spec` object
      - `canonical_query_hash` string, required
      - `filter_clauses` FilterClause[]
        - `field` string, required
        - `value` unknown, required
        - `mode` 'include' | 'exclude'
        - `origin` 'global' | 'widget' | 'metric' | 'drill' | 'component', required
      - `time_resolution` TimeResolution — How one execution's local date range resolved to an absolute UTC window. ``workspace_timezone`` is the IANA identifier and the ONLY timezone fact ever stored, traced or compared (an abbreviation like EET/EEST is presentation-only and derived per range). ``tz_rules_version`` names the DST ruleset in effect so a later reader can tell whether a historical rule has since moved.
        - `workspace_timezone` string, required
        - `local_start_date` string, date, required
        - `local_end_date` string, date, required
        - `resolved_start_utc` string, date-time, required
        - `resolved_end_utc_exclusive` string, date-time, required
        - `tz_rules_version` string, required
      - `comparison_time_resolution` TimeResolution — How one execution's local date range resolved to an absolute UTC window. ``workspace_timezone`` is the IANA identifier and the ONLY timezone fact ever stored, traced or compared (an abbreviation like EET/EEST is presentation-only and derived per range). ``tz_rules_version`` names the DST ruleset in effect so a later reader can tell whether a historical rule has since moved.
        - `workspace_timezone` string, required
        - `local_start_date` string, date, required
        - `local_end_date` string, date, required
        - `resolved_start_utc` string, date-time, required
        - `resolved_end_utc_exclusive` string, date-time, required
        - `tz_rules_version` string, required
      - `time_axes` object
      - `widget_ref` WidgetRef — Which widget this execution ran for, and a fingerprint of its config. ``config_fingerprint`` is the sha256 of the widget's canonical-JSON config, so a later audit reader can tell whether the widget definition moved without adding a version column to the ``Widget`` row. All fields are ``None`` for an ad-hoc query (a preview or a spec with no ``widget_id``).
        - `id` string, nullable
        - `source_ref` string, nullable
        - `config_fingerprint` string, nullable
        - `updated_at` string, date-time, nullable
      - `template_provenance` TemplateProvenance — Optional: which library template a system widget was instantiated from. **Not execution truth.** A widget's numbers come from its own config and the metric definitions, not from the template it started as — this only records the lineage and whether the widget still matches that template (``matches_template`` = the shared "Customized" test). Absent for user/ad-hoc widgets.
        - `report_query_key` string, required
        - `report_query_version` integer, required
        - `matches_template` boolean, required
      - `metrics` MetricExecutionInfo[]
        - `ref` string, required
        - `definition_version` integer, nullable
        - `implementation_digest` string, nullable
        - `calculation_kind` string, nullable
        - `executor_key` string, nullable
        - `unit` UnitSpecOutput — A unit as a ``dimension → exponent`` vector plus an optional currency code. ``currency_code`` is meaningful only when a ``currency`` dimension is present. Two DIFFERENT codes are incompatible, and ``currency_code=None`` (unknown / resolved per query scope) is incompatible with EVERY coded currency — the mechanism that blocks summing an unknown-currency value into a known one (PR 14 leans on it).
          - `dimensions` object
          - `currency_code` string, nullable
          - `display_label` string, required — ``to_display_label()``, serialized (Agent-Native PR 12). Every surface that shows a raw value needs to say what unit it is IN — the audit panel prints an exact ``12,150`` directly beneath a formatted ``3.4 h``, and unlabelled that reads as hours and is wrong by a factor of 3,600. The renderer already exists here; exposing it means the client, the agent tools and the disclosures all say ``conversations · seconds`` rather than each inventing a name for the same vector from raw dimension keys.
        - `entity` string, nullable
        - `drill_kind` string, nullable
        - `component_observations` ComponentObservation[]
          - `node_path` string, required
          - `role` 'result' | 'numerator' | 'denominator' | 'component', required
          - `metric_ref` string, nullable
          - `value` string, nullable
          - `canonical_value` string, nullable
          - `unit` UnitSpecOutput — A unit as a ``dimension → exponent`` vector plus an optional currency code. ``currency_code`` is meaningful only when a ``currency`` dimension is present. Two DIFFERENT codes are incompatible, and ``currency_code=None`` (unknown / resolved per query scope) is incompatible with EVERY coded currency — the mechanism that blocks summing an unknown-currency value into a known one (PR 14 leans on it).
            - `dimensions` object
            - `currency_code` string, nullable
            - `display_label` string, required — ``to_display_label()``, serialized (Agent-Native PR 12). Every surface that shows a raw value needs to say what unit it is IN — the audit panel prints an exact ``12,150`` directly beneath a formatted ``3.4 h``, and unlabelled that reads as hours and is wrong by a factor of 3,600. The renderer already exists here; exposing it means the client, the agent tools and the disclosures all say ``conversations · seconds`` rather than each inventing a name for the same vector from raw dimension keys.
          - `provenance` string, nullable
        - `change_lineage` ChangeLineage — PR 29 — which definition version + author produced an evaluated/calculated metric. ``prompt_ref`` is an IDENTIFIER, never the prompt text (the text is fetched by reference behind the metric's own gate). ``override_count`` and ``expansion_ref`` are population-scoped audit facts surfaced lazily by the audit panel / contributor expansion (PR 28/30), not on the hot widget-data path — they stay ``None`` here.
          - `revision_id` string, uuid, nullable
          - `revision_number` integer, nullable
          - `model_used` string, nullable
          - `prompt_ref` string, nullable
          - `override_count` integer, nullable
          - `expansion_ref` string, nullable
          - `authored_by_conversation_id` string, uuid, nullable
      - `source_consistency` 'snapshot' | 'single_statement' | 'best_effort', nullable
      - `source_as_of` string, date-time, nullable
      - `advisories` string[]

## Other responses

- `403` — No access to the tab, or missing report permission
- `404` — Dashboard not found
- `422` — Invalid request body (array-shaped detail), or a semantically invalid widget configuration (string detail).

---

[API](https://skmtc.dev/getanana/apis/cleon-api.md) · [All operations](https://skmtc.dev/getanana/apis/cleon-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/getanana/cleon-api/revisions/3ad158624c53/schema)
