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

# Refresh and freshness

> Re-fetch data, check how stale it is, and explore live values.

Reading cached rows with `get_widget_data` costs nothing and is usually enough. Reach for a refresh only when the user needs data fresher than the last run.

| Tool                                          | What it does            |                   |
| --------------------------------------------- | ----------------------- | ----------------- |
| [`check_freshness`](#check_freshness)         | Check freshness         | Read-only         |
| [`refresh_pipeline`](#refresh_pipeline)       | Refresh widget pipeline | Destructive write |
| [`refresh_stage`](#refresh_stage)             | Refresh pipeline stage  | Destructive write |
| [`refresh_dashboard`](#refresh_dashboard)     | Refresh dashboard       | Destructive write |
| [`explore_dashboard`](#explore_dashboard)     | Explore dashboard       | Additive write    |
| [`set_refresh_cadence`](#set_refresh_cadence) | Set refresh cadence     | Destructive write |

## check\_freshness

`Read-only`

Answer "how stale is this actually?" for a whole dashboard (dashboardId) or one widget (widgetId) — a cheap read that runs no pipelines and publishes nothing. A SUCCESSFUL REFRESH DOES NOT MEAN RECENT DATA, and this tool is the one place both facts sit side by side: per widget it reports lastRefreshedAt (when the fetch last ran) next to latestPeriod (the most recent period actually present in the cached rows, read from the date/year/period column), plus windowPinned — true when the widget's argumentTemplate hard-codes a literal date/year END bound, naming the stage and the argument that pins it. A widget refreshed 5 minutes ago whose latestPeriod is 2020 and whose end\_year is 2020 is not current, and no refresh will ever make it current; unpin the bound (patch\_widget\_pipeline with removeArguments, or point it at a relative parameter default) and refresh. The response also carries the dashboard's scheduled-refresh cadence (enabled, interval, paused/suspended) so "will it stay current?" is answerable in the same call — a schedule keeps the FETCH current, never a pinned WINDOW. Use it before promising a dashboard is up to date, to sweep a large dashboard for which widgets have literal date bounds, and to diagnose a chart that looks frozen. Any dashboard role may read it. latestPeriod is best-effort and simply absent when no row field reads as a time dimension — an absent value is never evidence of freshness.

## refresh\_pipeline

`Destructive write` · `Reaches outside Vistazo`

Refresh one widget's data pipeline now: re-run all its fetch stages in parallel against the live MCP data sources, then re-run the stitch transform. Pass pipelineId (from get\_widget / set\_widget\_pipeline — note re-wiring changes it) OR widgetId. Runs synchronously; the result reports refreshed (successful fetch stages), rowCount (rows the transform produced), errors, and warnings. CONCURRENT REFRESHES OF ONE WIDGET DO NOT STACK: if a refresh of the same pipeline is already in flight, this call skips instead of fetching and billing a second time — it returns skipped:1 alongside ok:true, refreshed:0 and a warning saying so, which is not a failure and not an error to retry past. The in-flight run publishes the rows; read them with get\_widget\_data. ok:true does NOT by itself mean data arrived — a fetch that matched nothing surfaces as rowCount 0 plus a warning; verify rowCount or get\_widget\_data before reporting success. A SUCCESSFUL REFRESH DOES NOT MEAN RECENT DATA: a fetch window pinned by a literal end bound (end\_year 2020) re-fetches the same stale years forever and still reports ok:true. The result therefore also carries latestPeriod — the most recent period found in the rows this run produced — so "refreshed just now" and "data ends in 2020" are visible together; it is best-effort and absent when no row field reads as a time dimension. When the user asks to make a dashboard "current", call check\_freshness FIRST (it reports lastRefreshedAt, latestPeriod, and which arguments pin the window) — refreshing a pinned window and calling the result current is a wrong answer, not a slow one. The result also echoes each stage's resolved arguments (stages\[].toolName + resolvedArguments) — use it to verify what was actually fetched, e.g. which parameter value applied, instead of inferring it from the data. Use after wiring or fixing a widget, or when the user asks for fresh data for a specific chart. Requires edit access — a refresh publishes the result as the shared baseline every viewer sees (it runs on the caller's own MCP credentials at the dashboard's default parameter values).

## refresh\_stage

`Destructive write` · `Reaches outside Vistazo`

Re-run ONE fetch stage of a widget's pipeline, then re-run the stitch transform against the fresh result plus the other stages' stored raw results. Falls back to a full refresh\_pipeline (reported as escalated:true) when a sibling stage's stored raw has expired. Shares refresh\_pipeline's in-flight guard: while a refresh of the same pipeline is running this returns skipped:1 with ok:true and fetches nothing. Use to re-run a single tool while debugging/inspecting a widget without re-fetching everything. Requires edit access (publishes the shared baseline, like refresh\_pipeline).

## refresh\_dashboard

`Destructive write` · `Reaches outside Vistazo`

Refresh every widget pipeline on a dashboard now: re-run all fetch stages against their live MCP data sources and re-run their stitch transforms. Runs synchronously and returns when all widgets are updated. In the result, refreshed counts successful fetch STAGES across all widgets (a multi-stage widget counts each stage), rowCount sums the rows the transforms produced, and pipelines whose fetch matched nothing are reported in warnings. skipped counts widgets a concurrent refresh was ALREADY running — they are deliberately neither refreshed nor errors (nothing was fetched or billed for them, and the run already in flight publishes their rows), so skipped:2 with ok:true means two widgets were left to a refresh that was already under way, not that two failed. The result also echoes each stage's resolved arguments (stages\[].widgetId + toolName + resolvedArguments) — use it to verify what was actually fetched, e.g. which parameter value applied, instead of inferring it from the data. A SUCCESSFUL REFRESH DOES NOT MEAN RECENT DATA: a fetch window pinned by a literal end bound (end\_year 2020) re-fetches the same stale years forever and still succeeds. The result carries latestPeriods — one entry per refreshed widget giving the most recent period actually present in the rows it produced (best-effort; a widget whose rows carry no time dimension is simply absent) — so a run that reports every widget refreshed but every period stuck in 2020 says so. When the user asks to make a dashboard "current", call check\_freshness FIRST: it reports lastRefreshedAt, latestPeriod, and exactly which widgets pin their window with a literal end bound, which is the sweep this question actually needs on a 20-widget dashboard. Requires edit access — a refresh publishes the results as the shared baseline every viewer sees (it runs on the caller's own MCP credentials at the dashboard's default parameter values).

## explore\_dashboard

`Additive write` · `Reaches outside Vistazo`

Run every widget pipeline on a dashboard EPHEMERALLY under your own credentials, optionally overriding parameter values, and return the chart-ready rows in the result. Persists nothing: the published baseline, the stored transform, and the parameter defaults are all untouched — this is the slice-and-dice lane, while refresh\_\* is the publish lane. `params` maps parameter keys to override values (same shapes as set\_parameter\_value, including relative date expressions); omitted keys use the dashboard defaults; unknown/invalid overrides are dropped and reported. Reuses each widget's cached transform only — a data-shape change surfaces as a per-widget stale\_transform error meaning an editor must run a real refresh. Any dashboard role may explore.

## set\_refresh\_cadence

`Destructive write`

Turn a dashboard's scheduled auto-refresh on or off — the 'stay current over time' half of freshness (refresh\_dashboard refreshes once, NOW; this keeps the data fresh going forward). Pass enabled plus an interval: every N minutes | hours | days | weeks (minimum 15 minutes). MATCH THE INTERVAL TO HOW OFTEN THE SOURCE PUBLISHES: an annual indicator (World Bank development data) gains nothing from an hourly or daily schedule — every run re-fetches identical numbers and bills your allowance (daily = 365 fetches a year for one annual update). Annual/quarterly sources: weeks. Daily sources (exchange rates, weather, national debt, filings): a day, or hours if the user needs same-day movement. Minutes only for a genuinely live feed. A SCHEDULE KEEPS THE FETCH CURRENT, NOT THE WINDOW: if a widget's argumentTemplate pins a literal end bound (end\_year 2020), every scheduled run succeeds and re-fetches the same stale years — before promising a dashboard will "stay current", get\_widget and check the argumentTemplate for literal end bounds. Saving a schedule attributes it to YOU — scheduled runs execute on your data-source connections and draw your usage allowance — and re-saving un-pauses a schedule paused by repeated credential failures. enabled:false stops scheduling but keeps the configuration for re-enabling. Calendar-style schedules (specific weekdays/times) are configured in the web app's dashboard settings; toggling enabled here without an interval preserves an existing calendar configuration. The response reports the schedule AS IT NOW STANDS — `nextRunAt` (when it will actually fire; null when it will not), `lastRunAt`, and `pausedReason` — so you can confirm the schedule is running rather than merely configured. get\_dashboard returns the same block. Requires edit access.
