---
title: set_refresh_schedule
description: Set a dashboard's cadence, every-N interval and day/time anchor. Parameters, the per-cadence caps, every validation error and scope.
updated: 2026-08-04
tools: [set_refresh_schedule]
---

Sets a dashboard's full refresh schedule: the cadence, the every-N interval, and
for a day or time cadence the day, hour and timezone. It re-anchors the next run
immediately and returns the new cadence and next run time.

The dashboard must already be refreshable, meaning it has a connected data
source, for any non-manual cadence.

Behaviour hints for clients: not read-only, not open-world.

## Parameters

| Parameter | Type | Required | Notes |
|---|---|---|---|
| `slug` | string | yes | Canonical slug of the dashboard to schedule. |
| `frequency` | string | yes | `manual`, `hourly`, `daily`, `weekly` or `monthly`. `manual` disables automatic refresh. |
| `every_n` | integer | no | Repeat the cadence every N units. Default 1. Per-cadence caps below. |
| `hour` | integer | no | Local hour, 0 to 23. A `timezone` is required once an hour is set. |
| `dow` | integer | no | Day of week for a weekly cadence, 0 to 6, with 0 = Sunday. |
| `dom` | integer | no | Day of month for a monthly cadence, 1 to 28. |
| `timezone` | string | no | IANA timezone name the day and hour anchor is interpreted in. |
| `workspace` | string | no | Workspace slug. |

`dom` stops at 28 rather than 31 so a monthly schedule lands in every month.

## Cadences and their caps

| Cadence | Allowed `every_n` | Anchors it takes |
|---|---|---|
| `manual` | 1 only | none |
| `hourly` | 1, 2, 3, 4, 6, 8 or 12 | optional `hour` (with `timezone`) |
| `daily` | 1 to 30 | optional `hour` (with `timezone`) |
| `weekly` | 1 to 4 | `dow` plus `hour` plus `timezone` |
| `monthly` | 1 to 12 | `dom` plus `hour` plus `timezone` |

Hourly `every_n` is restricted to divisors of 24 so the runs stay evenly spaced
across a day. Without an anchor a cadence runs unanchored: the top of the next
hour, or a fixed offset.

## Returns

```text
Schedule updated for "revenue-overview":
- Cadence: daily at 07:00 America/Los_Angeles
- Interval: every 2 days
- Next refresh: 2026-07-31T14:00:00Z
You (or the dashboard owner) can change this any time on the Schedules page.

BEGIN_JSON
{"slug":"revenue-overview","dashboard_id":"...","name":"Revenue Overview","frequency":"daily","refresh_every_n":2,"next_run_at":"2026-07-31T14:00:00Z","schedule":{"timezone":"America/Los_Angeles","hour":7,"dow":null,"dom":null}}
END_JSON
```

The `- Interval:` line appears only when `every_n` is greater than 1. For a
manual cadence `next_run_at` is `null` and renders as `not scheduled`.

## Errors

### Validation, before anything is written

| Condition | Text |
|---|---|
| Unknown cadence | `frequency must be one of manual, hourly, daily, weekly, monthly` |
| Non-integer anchors | `hour must be an integer`, `dow must be an integer`, `dom must be an integer` |
| Non-integer interval | `every_n must be an integer` |
| Bad timezone | `timezone must be a non-empty IANA timezone name (e.g. America/New_York)` |

Then one refusal per cadence-and-anchor mismatch, each verbatim:

```text
a manual schedule does not take a day, time, or timezone
a manual schedule does not take a refresh interval
an hourly schedule does not take dow or dom
an hourly interval (every_n) must be one of 1, 2, 3, 4, 6, 8, or 12
an hourly schedule needs an hour when a timezone is given
a daily schedule does not take dow or dom
a daily interval (every_n) must be between 1 and 30
a daily schedule needs an hour when a timezone is given
a weekly schedule does not take dom
a weekly interval (every_n) must be between 1 and 4
a weekly schedule needs both a dow (0-6) and an hour
a monthly schedule does not take dow
a monthly interval (every_n) must be between 1 and 12
a monthly schedule needs both a dom (1-28) and an hour
```

### Runtime

| Condition | Text |
|---|---|
| The lookup or write failed | `schedule update failed: <err>` |
| No such dashboard | `No dashboard named "<slug>" in that workspace.` |
| Not signed in | `not authenticated (sign in again and retry)` |
| Not permitted | `you do not have permission to change this dashboard's schedule` |
| Unknown dashboard id | `no dashboard with that id in that workspace` |
| A workspace was named but not routed | `workspace target not resolved: this request names a workspace but was not routed to one (the caller must resolve the workspace and wire workspace-scoped deps)` |

A dashboard with no connected data source is refused when you ask for a
non-manual cadence, and the database's own sentence is surfaced verbatim rather
than reworded.

:::note{title="This refusal is no longer unique to this tool"}
`No dashboard named "<slug>" in that workspace.` used to be this tool's alone, and five
other readers said `in your account` on a workspace target even though their lookups were
equally workspace-aware. Six tools share this sentence now: `get_refresh_status`, `get_source_config`, `get_dashboard_spec`,
`set_refresh_schedule`, `verify_dashboard` and `derive_dashboard_spec`. Tools outside that
list still word it their own way; see
[Conventions](/reference/mcp-tools/conventions).
:::

## Scope

Any member of the workspace may schedule its dashboards,
which is the same set of people who can republish the body.

## Check it worked

Read it back with
[`get_refresh_status`](/reference/mcp-tools/get-refresh-status) and confirm the
`Schedule:` line and `Next refresh` match what you asked for. Then wait for that
time to pass and confirm a run appears in the history. A `Next refresh` in the
past means the schedule never re-anchored.
