# Share a view without giving access

Save a query as an artifact, hand somebody a read-only link to exactly that query, or have it delivered on a schedule.

Source: https://tokentriage.com/docs/build/dashboard-sharing

---
import Callout from '../../../components/Callout.astro';
import Details from '../../../components/Details.astro';
import NextSteps from '../../../components/NextSteps.astro';
import Screenshot from '../../../components/Screenshot.astro';

Somebody in finance wants last month's spend by team. They do not need an account, they should
not see your routing config, and you do not want to export a CSV by hand every month.

Three mechanisms answer that, and they build on each other: a **saved view** is a query you can
name and re-open, a **share token** turns one saved view into a public read-only link, and a
**schedule** delivers the same view through the export pipeline on a cadence.

<Screenshot
  stem="dashboard-views-share"
  dark={true}
  url="localhost:9090/ui/views"
  alt="The Saved views and share links surface, showing three panels: saved views with a create form taking a name, id, surface, time window, filter text, grouping, sort and columns; share tokens, empty, explaining that a share token is a read-only public link to a frozen query with immediate revocation; and scheduled reports, empty, explaining that a schedule renders a saved view through the export pipeline on a cadence."
  caption="The three mechanisms on one surface. This instance has none of them configured yet (real dashboard, demo mode)."
/>

## Save a view

A saved view is the current query as a durable artifact: the surface it targets, a time
window, filter text, grouping, sort order and the columns you chose. Create one from the
Saved views surface, or from the explorer once you have a query you want to keep.

Two things follow from a view being an artifact rather than a bookmark.

**It is diffable.** Two views can be compared, and a change to one is a change you can see
rather than a URL that quietly means something else.

**It can be promoted.** Pin a view and it appears in your sidebar. Following the pinned entry
applies the whole frozen query, not only its text filter, so the entry reproduces the slice it
is named for.

The id must be a slug, and the surface picks it up from the name unless you set it yourself.

## Mint a share token

A share token is a read-only bearer credential frozen to exactly one target. Use **Share…** on
a view to mint one; the token is shown once and only its SHA-256 hash is kept.

The recipient opens `/share/{token}` and gets that query and nothing else. Not a stripped-down
dashboard: there is no navigation at all, because the token grants one target rather than a
narrower version of your instance.

<Callout type="key">
A share token freezes exactly one target: a saved view, an inline query, or a governance
subtree. Never a combination, and never a target that can later be widened. Minting one with
two targets is rejected at mint time rather than resolved in favour of one.
</Callout>

Three properties worth knowing before you hand one out.

**Revocation is immediate.** Confirm the revoke and the link stops working on the next
request. A revoked or expired token resolves to `404`, which tells a recipient nothing about
whether it ever existed.

**It can expire on its own.** Give a token a lifetime when the need has one. A quarterly
review does not need a link that works forever.

**Minting is admin work.** The `share:admin` scope sits in the privileged set, alongside
minting bearer tokens, because a share link is access.

For a tenant rather than a query, a governance share token freezes a node subtree instead: the
recipient sees spend, limits, keys and refusals for their own subtree, and a read of a node
above or beside it is refused rather than silently widened. [Tenant
self-service](/docs/build/governance-self-serve) covers that shape.

## Schedule a report

A schedule binds a saved view to a cadence and a delivery channel. It renders through the same
exporter a manual export uses, so a delivered report carries the same provenance stamp: the
pricing snapshot, the row counts, and the unpriced rows excluded and disclosed.

That last point is the reason to prefer a schedule over a hand-built pipeline. A CSV somebody
assembles from the API loses the disclosure line, and a spend total without its exclusions is
the figure most likely to be forwarded to somebody with a budget.

Save the view first. The surface says so rather than offering a schedule with nothing to
render.

## Or just export

For a one-off, every query surface has an export. An export is a read, so a viewer can do it
without any of the above.

```text
Unpriced rows export as UNPRICED (never a fabricated zero).
```

That line sits above the export control on the Cost surface, and it describes the file you
get: an unpriced row appears in the export marked as unpriced rather than as `0`. The same
holds for the OTLP export, where an unpriced row carries a flag and carries **no** cost
attribute at all, rather than a zero somebody's dashboard would happily sum.

[Cost exports](/docs/build/cost-exports) covers the file formats and their columns.

<Details summary="Which mechanism to use">

| You want | Use |
|---|---|
| to come back to this query yourself | a saved view |
| the same slice in your sidebar | a pinned saved view |
| to send it to a colleague who has an account | the URL — filters live in the query string |
| to send it to somebody with no account | a share token |
| it to arrive every Monday | a schedule |
| a file, once | an export |
| a tenant to see their own spend and limits | a governance share token |

</Details>

## What can go wrong

**The share link works for longer than you meant.** A token with no expiry has none. Revoke it
when the need ends, or mint with a lifetime in the first place.

**A recipient asks why they cannot navigate.** That is the design: the token carries one
frozen target. If they need to explore, they need an account with the viewer role.

**A scheduled report stops arriving.** Delivery failures are recorded and shown on the Alerts
surface alongside rule state, because a schedule delivers through the same channels.

**Someone rebuilds a total from an export and it disagrees with the screen.** Check the
disclosure line. A total over priced rows and a total over all rows are different figures, and
the export says which one it is.

<NextSteps items={[
  {title: "Roles and permissions", href: "/docs/build/dashboard-roles", description: "Why minting a share token is admin work, and what a viewer can already do."},
  {title: "Cost exports", href: "/docs/build/cost-exports", description: "The file formats a view or a schedule renders through, and what each column means."},
  {title: "Tenant self-service", href: "/docs/build/governance-self-serve", description: "The governance-scoped share token, for a tenant reading their own subtree."},
  {title: "Surface index", href: "/docs/build/dashboard-surfaces", description: "Every screen a view can target, and the question each one answers."}
]} />
