# Live viewing links and access

> How a Live viewing link is authorized, what stops one, what revoking cannot undo, and what a viewer can never see.

Canonical page: https://anectico.com/docs/manage/live-links-and-access/


A [live screen](/docs/investigate/live-screens) is published as a **viewing link**. This page is what
to understand before you give one to anybody.

Your agent creates a screen and publishes it. You control the links: in the Console, open **Published
links** (`/published-links`) to see every link in the project and to revoke one. See the
[Console guide](/docs/manage/console#published-links).

## Ask your agent

> "Publish the lobby screen with a 30-day link, and show me every panel it will disclose before you
> do."

> "List the viewing links in this project and tell me which ones still work."

| Job | MCP tool or action | CLI command |
| --- | --- | --- |
| Create, read, change or delete a screen | `create_live_screen`, `list_live_screens`, `update_live_screen`, `delete_live_screen` | `anectico live screen create`, `list`, `get <screen-id>`, `update <screen-id>`, `delete <screen-id>` |
| Preview what a link would show | `preview_live_screen` | `anectico live screen preview <screen-id>` |
| Publish a screen and get its link (shown once) | `publish_live_screen` | `anectico live screen publish <screen-id>` |
| List links and see whether each one still works | `list_live_grants`, `get_live_screen_status` | `anectico live grant list`, `anectico live status <screen-id>` |
| Pause, resume, rotate or revoke a link | `pause_live_grant`, `resume_live_grant`, `rotate_live_grant`, `revoke_live_grant` | `anectico live grant pause`, `resume`, `rotate`, `revoke` (each with `<grant-id>`) |

The scopes are in [Scopes](#scopes). The MCP write tools preview first and apply on a second call
with a `confirm_token`; see [MCP tools](/docs/reference/mcp-tools).

## What your agent gets back

A publish or a rotate returns the link **once**, in the response text. A list or a status read never
returns a link or any part of one; it returns each link's name, state, expiry and the revision it
publishes. Ask your agent to hand the link to you, not to repeat it in a chat or a ticket.

## Open the proof

The link itself opens the display, which shows the published screen to anyone who holds it. It is a
separate viewer, not a proof page. The Console page **Published links** lists the links of the project
and their effective state, so you can check that a link you meant to stop has stopped. See
[Proof pages](/docs/agents/proof-pages) for the read-only pages that other agent results link to.

## The link is the credential

The link is unlisted bearer access: whoever holds it sees the published screen, without signing in
and without proving who they are. It is not evidence of a viewer's identity, and it is not a
credential for anything else in your organization.

A link looks like `https://live.example.com/live/SCREEN_ID#SECRET`, on the separate origin your
organization's displays are served from. The secret is in the URL **fragment** — the part after `#`
— which a browser never sends to a server. The display reads it in the page and exchanges it for a
session, so the secret stays out of access logs, proxy logs and referrer headers.

It is returned **once**, when you publish or rotate. No listing, no status read and no API response
can hand it back afterwards. If you lose it, rotate the link; there is no recovery path, by design.

One screen can have several independently named links — a lobby panel and an on-call laptop can hold
different links to the same screen and be stopped separately.

## A link runs on the publishing key, not on you

Every link records the **project API key** that published it, and the display serves whatever that
key may currently read, intersected with the permissions frozen into the publication. That
intersection is re-resolved on **every** read, not cached from publish time.

The consequences are the whole access model:

| Change | Effect on the display |
| --- | --- |
| The publishing key is revoked | Stops, on the next read |
| The publishing key expires | Stops, on the next read |
| The publishing key's scopes are narrowed, or the key is frozen to read-only | Stops, on the next read |
| Your organization is suspended | Stops, on the next read |
| The panel loses one source scope but keeps the others | That panel shows **Denied**; the rest keep serving |
| The person who created the key changes role or leaves | **No effect** — a project key is a project credential, and that is its existing contract |

"Stops, on the next read" covers displays that are already open. A screen that is **not** yet open
is refused earlier still: opening a link asks the publishing key's current state first, so a link
whose key is revoked, expired, narrowed or suspended does not open at all. It is refused exactly the
way an unknown or mistyped link is, because the answer must not tell the holder of a link which of
the two it was.

That last row is the one to plan around. If a display must stop when a particular person leaves, that
is an offboarding step: revoke the link, or revoke the key it publishes on.

This is also why a link is never held by a login. A display outlives any browser session, so its
authority has to be a credential that can still be checked tomorrow.

### The key a link publishes on

Your agent publishes with a project API key that holds `live:publish`. The link records that key.
The key needs the source scopes of every panel the screen names, as the section on scopes explains.
If the key lacks one, the publish is refused by name. Mint the key with the scopes in
[Scope recipes for agent jobs](/docs/agents/scope-recipes#publish-a-live-screen), and keep it for this
job only.

A signed-in member session with the required Live and source scopes can also publish through
MCP or the CLI. It needs `api_key:write` because publication creates a dedicated project key;
the link records that key and keeps running on its authority after the session ends. Both paths
first return the complete server preview and require confirmation with identical arguments.

Revoking the key stops the display on its next read, exactly as revoking the link does. In the
Console, open **Agents and keys** (`/agents`) to revoke a key, or **Published links** (`/published-links`)
to revoke the link. Your own access changing later does not stop a display, because it runs on the
key and not on your login. If a display must stop when you leave, that is the offboarding step above:
revoke the link or revoke its key.

A connected app acting on your behalf can never publish, however it is signed in. A viewing link is
a durable credential, and a delegated grant must not be able to leave one behind after it is revoked.

## Scopes

Three scopes cover Live itself:

| Scope | What it allows |
| --- | --- |
| `live:read` | List and read screens, and list a screen's viewing links |
| `live:write` | Create, edit and delete a screen, and render a preview |
| `live:publish` | Publish a screen, and pause, resume, rotate or revoke its links |

Deleting a screen requires `live:read` and `live:write`. If it has been published, it also requires
`live:publish`. A signed-in member or a project API key of the same project can delete it with those
permissions, including after its links and publishing key have been revoked. Deletion revokes any
remaining links; it does not create another key or require `api_key:write`. Missing permissions are
checked before the screen is removed.

`live:read` and `live:write` disclose nothing outside your organization: editing changes what a
display *would* show. `live:publish` is the separate decision, and it is the one that mints a link.
Give it only to the credential you intend to publish with.

`live:publish` deliberately does not end in `:read`. A key reduced to its read permissions must lose
the ability to keep serving a public display, and because that reduction keeps every `:read` scope, a
publish scope spelled as a read would have survived it.

**The publishing key also needs each panel's own source scope** — `analytics:query`,
`analytics:read`, `insights:read` and `persons:read` for a trend panel, `errors:read` for people
affected, `services:read` for service health, `alerts:read` for alert state, `logs:read` for log
volume. Publishing without one is refused by name, and losing one later turns that panel into
**Denied**. The complete set for an agent that publishes is in
[Scope recipes for agent jobs](/docs/agents/scope-recipes#publish-a-live-screen).

A viewer role can hold `live:read` and never `live:write` or `live:publish`. An agent connected over
OAuth can read live screens and can never publish one, at any role, because a viewing link outlives
the connection that created it.

## Expiry

A link expires **30 days** after it is created unless you choose otherwise. You may also choose no
scheduled expiry, for a monitor that should keep running. A permanent link is still subject to
everything else on this page: the publishing key's current permissions, your plan and retention, data
deletion, and revocation.

Set the lifetime when you publish. There is no way to give a link an absolute end date that the
server cannot verify against its own clock, so choose a duration rather than a date.

## Pause, resume, rotate, revoke

Your agent pauses, resumes, rotates and revokes a link with the tools above. In the Console, open
**Published links** (`/published-links`) to list the links and to revoke one; revoking needs an
owner or an administrator who holds `live:publish`. These actions do not create another API key. The
display continues to run under the key recorded when it was published. A project API key with
`live:publish` can perform the same actions for its project. Connected apps acting through delegated
access cannot manage viewing links.

| Action | What happens | Reversible |
| --- | --- | --- |
| Pause | Every display on that link is denied at its next read and clears itself. The link itself still exists | Yes, with resume |
| Resume | The same link starts working again. Viewers cut off by the pause must reopen it | — |
| Rotate | A new link is issued and returned once. The old link and every session opened from it stop | Only by rotating again |
| Revoke | The link ends permanently. A revoked link cannot be resumed or rotated | No |

All four take effect on the next read a display makes, which is at most one refresh interval away —
seconds, not a cache lifetime. There is no window in which a stopped link keeps serving from a cached
answer: every read re-checks, and so does a conditional read that would otherwise answer "not
modified".

Deleting the screen disables its publication and revokes every link issued for it.

**Publishing again also ends the previous link.** A screen shows one published version at a time,
so each publish issues a new link and ends every earlier one: the old link stops opening, and a
display still running on it is told its access ended at its next read. Hand out the link the
publish returned, and only that one — a listing shows exactly one active link per screen.

**Deleting the project or the organization ends every link in it immediately** — before the
deletion finishes, not on a later cleanup pass. Displays stop at their next read, the links stop
opening, and the keys that published them stop working.

A listing of links shows an **effective state** rather than only the stored one, because a link whose
row says active is not working if its publishing key was revoked an hour ago. The effective state
folds in expiry and the key's current condition, and it is the honest answer to "is this link
working".

### What revocation cannot do

Revoking a link stops future delivery. It does not reach backwards:

- It cannot erase a screenshot, a photograph of a wall panel, or what somebody already read.
- It cannot retract a link that was already copied, pasted into a chat, or synchronized to another
  device by a browser. Clearing the fragment from an address bar does not un-share it.
- It does not remove the screen or its definition. The screen stays; only the link ends.

Treat publishing as a disclosure with the same care as sending the data by mail, because in the
respect that matters it is the same.

## Viewer sessions

Opening a link exchanges its secret, once, for a display session held in a cookie that the browser
cannot read from script. After that the display asks for a fresh reading on a cadence the server
sets.

| Property | Value |
| --- | --- |
| Session idle lifetime | 24 hours, extended by use |
| Session absolute lifetime | 30 days, never extended |
| Re-authorization | Every read, including a read that answers "not modified" |

A display that is denied clears its screen and its session and shows a neutral access-ended state
naming only what happened — never which organization, project or screen the session pointed at. A
display that simply cannot reach the server clears itself too, rather than leaving values on a wall
whose authorization nobody can confirm.

Every refusal at the exchange looks identical. An unknown screen, a wrong secret, and a paused,
revoked or expired link are indistinguishable, so the exchange cannot be used to find out which links
exist. Exchanges and reads are both rate limited, and a link being read far above a display's own
cadence is throttled.

**The display cookie authenticates nothing else.** It is scoped to the display's own routes on the
viewer origin, and the rest of Anectico reads credentials from request headers only — so a request
carrying just that cookie to any other endpoint is unauthenticated. A display session can never widen
into an ordinary API, CLI, MCP, export or ingestion call, and an ordinary session can never widen a
display request either.

Displays are served from their own origin, separate from the Console's, so a shared device holding
a wall display holds no Console session. That origin sends no referrer, allows no embedding in
another site, and marks its responses uncacheable. Every other path on it answers "not found".

## What a viewer can never see

Independent of scopes, and independent of what the publishing key holds:

- **People.** No person, no identifier, no profile property, no account membership. A people-affected
  panel is a count; there is no path from it to who was counted.
- **Raw records.** No log message, no span, no error detail, no recorded session, no export.
- **Definitions.** No query definition, no saved recipe, no cohort provenance, no execution snapshot,
  no alert rule name.
- **Anything not published.** A viewer reads the exact revision the link was published at. Editing
  the screen afterwards changes a draft, and a display never mixes a new definition with old
  authorization.

Investigating any of that is a separate, signed-in path. Viewing a display grants none of it.

## Next

- [Put a project on a live screen](/docs/investigate/live-screens) — publish, preview and manage.
- [Live screen templates and panels](/docs/investigate/live-screen-templates) — exactly what each
  panel kind discloses.
- [Permission scope reference](/docs/reference/permissions) — the complete scope catalog.
- [Authentication and API keys](/docs/reference/authentication) — minting the project key a link
  publishes on.
