# Previews (/docs/concepts/previews)



A preview exposes an HTTP service running inside a sandbox at a private
URL. Start a server in the sandbox, create a preview for its port, and
CrowNest proxies requests to it — without making the sandbox publicly
reachable.

## Private access in v1 [#private-access-in-v1]

All previews require authentication in v1. `authMode` defaults to
`authenticated`, which requires an API key permitted for the sandbox's
project. Use `authMode: "token"` to create a private link you can open in a
browser: CrowNest returns a one-time `previewToken`, and appending it as
`cn_token=<token>` exchanges it for an HttpOnly preview cookie.

Unauthenticated public previews aren't available; `authMode: "public"`
returns `unsupported_preview_auth_mode`, and any other unrecognized value
returns `invalid_request`.

## Preview URLs [#preview-urls]

Creating a preview returns a `slug` (DNS-safe, like `p-a1b2c3d4e5f6`) and a
`url` of the form:

```text
https://p-a1b2c3d4e5f6.crownest.dev
```

Requests to that hostname are proxied to the chosen port inside the
sandbox. If the port isn't responding, the proxy returns
`preview_unavailable`.

## One preview per sandbox and port [#one-preview-per-sandbox-and-port]

Each sandbox can have one active preview per port. Create one with
`POST /v1/sandboxes/{id}/previews` and a body containing `port` (an integer
from 1 to 65535) and an optional `authMode`. Creating a preview
for a sandbox and port that already has an active preview with the same auth
mode returns the existing preview rather than an error, so creation is safe
to retry.

A sandbox can hold up to 3 active previews, and an organization up to 10
across all its sandboxes. Creating a preview beyond either cap returns
`quota_exceeded`. Revoking a preview frees a slot.

## What CrowNest strips [#what-crownest-strips]

Before proxying a request to your app, CrowNest removes its own
credentials:

* CrowNest's own cookies.
* The `Authorization` header.
* `Referer`, so token links are not forwarded to your app.

Your app behind the preview never sees the caller's CrowNest credentials.
If your app needs authentication of its own, use a separate mechanism such
as your own header or cookie.

## Revocation and lifecycle [#revocation-and-lifecycle]

Revoke a preview with `DELETE /v1/previews/{previewId}`; the operation is
idempotent, and the preview records a `revokedAt` timestamp. Previews are
tied to their sandbox: when the sandbox is destroyed — killed, expired, or
otherwise — its previews stop working. Creating a preview on a destroyed
sandbox returns `sandbox_destroyed`.

## Next steps [#next-steps]

* [Sandboxes](/docs/concepts/sandboxes) — the lifecycle previews are tied
  to.
* [Commands](/docs/concepts/commands) — start the server a preview points
  at.
* [API keys and scopes](/docs/concepts/api-keys) — the `preview:*` scopes
  and project restrictions that govern access.
* [Previews API reference](/docs/api/previews)
