---
title: replace_file_upload
description: Point every dashboard that reads one uploaded file at a newer upload of the same file, keeping each dashboard's slug, URL and history.
updated: 2026-09-23
tools: [replace_file_upload]
---

The monthly-spreadsheet call. A file whose numbers change every month is a NEW
upload each time, and this is what moves the dashboards onto it: each one keeps
its slug, its URL and its version history, and asks for the refresh that brings
in the new numbers.

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

## Parameters

| Parameter | Type | Required | Notes |
|---|---|---|---|
| `upload` | string | yes | The id of the upload the dashboards read today: the file being replaced. |
| `replacement` | string | yes | The id of the new upload, from [`create_file_upload`](/reference/mcp-tools/create-file-upload). It must be `ready`. |
| `dry_run` | boolean | no | Default false. Run the check and change nothing. |
| `workspace` | string | no | Workspace slug, only for a legacy connection authorized for no workspace. |

## The order it does things in

1. Both uploads are resolved. They must be in the same workspace and on the same
   uploaded-file source, and the replacement must be `ready`.
2. Every live dashboard that reads the old upload is found. There is nothing to
   do if none does, and past the per-call cap the refusal names the count.
3. Each of those dashboards is checked against the new file, by running its own
   datasets against it, BEFORE any of them is changed.
4. Only if every one of them passes, each is republished with a single edit to
   its spec, `source.upload`.

So a replacement that would break a dashboard changes nothing at all, rather than
moving some dashboards and stopping at the one that broke.

## What it leaves alone

A dashboard is only repointed when its spec BINDS the file in `source.upload`. A
dashboard whose spec merely mentions the upload id somewhere else - in a comment,
in a page body you wrote - is listed in `mentions_only` and left untouched,
because it reads a different file.

## What happens to the schedule

The cadence comes from each dashboard's spec, as it does on any republish. A
frequency or an every-N interval armed with
[`set_refresh_schedule`](/reference/mcp-tools/set-refresh-schedule) or on the
Schedules page is set back to what the document says; the hour, day and timezone
anchor is kept. If a cadence was armed that way, re-arm it after replacing.

## What counts as compatible

A replacement is compatible when every dashboard on the file still publishes
against it. That is the same check a republish by hand would make, so what
decides it is whether the dashboards' SQL can read the new file, not whether the
two files have the same columns:

- A column the new file drops that **no dataset reads** is fine and does not
  refuse.
- A column a dataset **does** read, gone or changed to a type its SQL will not
  take, is refused. The message names the dataset and quotes what the query
  engine said, which names the column.

## Returns

```text
Replaced "sales.csv" with "sales-october.csv" on 2 dashboards. Same slugs, same URLs.
- revenue-monthly https://acme.dashies.ai/revenue-monthly (refreshing now)
- revenue-by-rep https://acme.dashies.ai/revenue-by-rep (refreshing now)

Each one was republished with a single edit to its spec, `source.upload`, so the change is in the document and in the dashboard's version history rather than underneath it.
Each dashboard's cadence comes from its spec, as it does on any republish: a frequency or interval armed with set_refresh_schedule or in the app is set back to what the document says, while the hour, day and timezone anchor is kept. Check set_refresh_schedule if one was armed that way.
The file you replaced (upload 0b6f0c1e-...) is kept, not deleted: each dashboard's previous version still names it, which is what keeps the way back to those numbers open. Nothing here promises when its bytes go.
Poll get_refresh_status with a slug to watch the new numbers land.

BEGIN_JSON
{"replaced":"0b6f0c1e-...","replacement":"7d41a2b8-...","connection":"...","filename":"sales-october.csv","dry_run":false,"dashboards":[{"slug":"revenue-monthly","url":"https://acme.dashies.ai/revenue-monthly","republished":true,"refresh":"extracting_now"}],"mentions_only":[]}
END_JSON
```

`refresh` is what the republish's own first-data step reported for that
dashboard: `extracting_now`, `loaded`, `unchanged`, `no_new_extract` (a refresh
was already running, so no second one started) or `not_started`. Poll
[`get_refresh_status`](/reference/mcp-tools/get-refresh-status) with the slug for
the rest.

## The file that was replaced

It is kept, not deleted. Each dashboard it was on keeps its previous version, and
that version names the upload, so the way back to the earlier numbers stays open.
Nothing here promises when the bytes go.

## Errors

- `No upload with that id in a workspace you belong to.` for an unknown id, an
  upload in another workspace, or one the caller cannot see. All three get the
  same answer.
- The replacement is not `ready`. The message names its status.
- The two uploads are in different workspaces, or on different uploaded-file
  sources. The second happens when the workspace's file source was retired
  between the two uploads; the message says to republish naming both the new
  connection and the new upload.
- No live dashboard reads the upload being replaced. A dashboard that only
  mentions it is named rather than counted as one that does.
- More dashboards read it than one call will republish. The refusal names the
  count and the cap.
- A dashboard that reads the file and whose spec cannot be edited automatically:
  it has no stored spec, its `source` is written on one line, or the line naming
  its upload is not unique in the document. The message names the dashboard, and
  the remedy is to republish that one by hand with
  [`get_dashboard_spec`](/reference/mcp-tools/get-dashboard-spec) and
  [`publish_dashboard`](/reference/mcp-tools/publish-dashboard).
- A dashboard whose refresh manifest reads the file while its spec names a
  different upload. That one is refused with no value prescribed: which file it
  should read next is yours to decide, not the tool's.
- A dashboard that cannot read the new file. Nothing is changed.

## Scope

Which workspace the call acts in comes from how this MCP connection was
authorized. It republishes dashboards, so it needs the same seat a publish does.
