Publish and share
Publishing is the handoff from your harness to the maintained platform: the dashboard stops being an agent's output and becomes something your team can rely on — a stable URL, governed by your access rights, that keeps answering after the session is over.
Draft and main are real git branches
This is not a metaphor. Every dashboard is a git repository, kept as a bare repo in object storage. Your edits — from your agent, from the in-app assistant, from the code editor — are commits on a draft branch. Publishing merges that draft into main.
Three consequences worth planning around:
- You cannot write directly to
main. Writes to it are refused; the only way content reaches the live version is a publish. - Every publish creates a version tag. The tag records the state
mainwas in before the merge — sov1is what your first publish replaced,v2is what your second publish replaced, and the currently-live version ismain, untagged until the next publish. - Concurrent publishes merge rather than clobber. If
mainmoved while your draft was open and the two touched different files, both sets of changes land. If they touched the same file incompatibly, the publish fails with409 PUBLISH_MERGE_CONFLICTand names the conflicting paths. It does not pick a winner silently.
You can read that history:
print(client.viz.list_tags(viz_id))
print(client.viz.get_commit_log(viz_id, "main", max_count=20))
print(client.viz.preview_publish(viz_id)) # diff between draft and main
console.log(await client.viz.listTags(vizId));
console.log(await client.viz.getCommitLog(vizId, 'main', { maxCount: 20 }));
console.log(await client.viz.previewPublish(vizId));
Publish a dashboard
Your agent can do this directly over MCP; in the app it is the Publish button; from code it is one call:
client.viz.publish(viz_id)
await client.viz.publish(vizId);
Publishing runs a health check on the dashboard's last build first. If the bundle is
FAILED or stale, the publish is refused with a 409 rather than promoting something that
does not render — pass force=true to override that deliberately.
The publish then merges, tags, and starts a build. The status only becomes PUBLISHED
when that build succeeds; if it fails, the dashboard lands in ERROR and main is reset.
So publish() returning is not the same fact as "the dashboard is live" — read
publishStatus back before you tell anyone the link works. (Same rule as
refresh returning 202: the call
completing and the work completing are two different things.)
Who can open it — three modes, not two
Publishing decides that the dashboard is live. A separate field, viewMode, decides who
can open it. Getting these confused is the most common mistake here.
viewMode | Who can open it |
|---|---|
public | Anyone with the link. No account required. |
protected | Only a viewer your backend minted an embed token for — with per-viewer row filters. See Embedding. |
private | Nobody outside your account. Published, but not reachable from the public surface. |
A published dashboard's link looks like:
https://cloud.vibedasher.com/v/<slug>
That URL only serves content when the dashboard is both published and public. A
protected dashboard on the same URL needs a token appended.
Going public is gated separately, and an agent cannot do it alone
Making company data world-readable is the one irreversible thing in this whole flow, so it
has its own gate rather than riding along with publish. Two switches, both on the account,
both checked server-side on every route that can write viewMode:
allowForPublicViz— an account-wide kill switch. Turn it off and nothing in the account can be made public, by anyone, through any route.apiKeysMayPublish— defaults tofalse. Even when public sharing is allowed, a caller authenticating with an API key may not be the one to flip a dashboard to public. An admin has to turn this on, and can only do so from a browser session —PUT /v1/accountrefuses to set it from an API key, so the switch cannot enable itself.
That second one is the point. Elsewhere on this platform an API key acts as its creating user with that user's full role (see Who can see what). Publishing to the open internet is the deliberate exception: your agent can build the dashboard, publish it, and share it inside your account, but by default it cannot be the thing that makes it public. A human in a browser has to have said yes once, at the account level.
The code is frozen; the data is not
This is the property that makes a published dashboard worth hosting rather than exporting.
The dashboard code is snapshotted at publish. The bundle is built once and served from storage. Your draft keeps evolving independently and does not leak into the live version until you publish again.
The data is read live at view time. Every chart on a published dashboard queries the current contents of its datasets when someone opens it. A refresh that lands at 3am shows up on the published dashboard at 9am with nothing rebuilt and nobody in the loop. That is the whole reason the data half lives in the platform — see Keep your data fresh.
Unpublish and republish
DELETE /v1/viz/{id}/publish takes the dashboard down: the status returns to
NOT_PUBLISHED and the live bundle is removed. Your draft is untouched.
- The slug is kept and stays reserved, so republishing reuses the same URL.
- Old links fail inconsistently. The viewer page answers
404, the public API answers403, and the cached-data endpoints answer404. If you are handling this programmatically, do not branch on the status code alone. - Renaming the slug breaks every existing link permanently. There is no redirect from an old slug to a new one. Choose the slug before you circulate the URL.
Embed it
Published dashboards render through an embeddable iframe you can drop into any app, docs page, or website — public, or gated per viewer with row-level filters. See Embedding a dashboard.