Skip to content

Reference / Uploads

replace_file_upload

Point every dashboard that reads one uploaded file at a newer upload of the same file, keeping each dashboard's slug, URL and history.

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

ParameterTypeRequiredNotes
uploadstringyesThe id of the upload the dashboards read today: the file being replaced.
replacementstringyesThe id of the new upload, from create_file_upload. It must be ready.
dry_runbooleannoDefault false. Run the check and change nothing.
workspacestringnoWorkspace 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 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

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 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 and 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.