CrowNest
API reference

Previews

Expose an HTTP service running in a sandbox through an authenticated preview URL.

A preview exposes an HTTP service listening on a port inside a sandbox at a stable HTTPS URL. In v1, all previews are authenticated — there are no public preview URLs.

The Preview object

FieldTypeDescription
idstringPreview ID, prefixed prv_
slugstringDNS-safe slug, such as p-a1b2c3
urlstringhttps://p-a1b2c3.preview.crownest.dev
orgIdstringOwning organization, prefixed org_
projectIdstringOwning project, prefixed prj_
sandboxIdstringSandbox the service runs in, prefixed sbx_
portintegerPort the sandbox service listens on
authModestringauthenticated (the only mode in v1)
createdAtstringISO 8601 creation timestamp
expiresAtstringISO 8601 expiry, when set
revokedAtstringISO 8601 revocation timestamp, once revoked

The preview URL has the shape https://<slug>.preview.crownest.dev, where slug is generated by CrowNest.

[!NOTE] Preview access requires authentication in v1. CrowNest strips its own cookies and Authorization header before proxying the request to your sandbox app, so platform credentials never reach your code.

Create a preview

POST /v1/sandboxes/{sandboxId}/previews — requires scope preview:create.

Exposes a port on the sandbox. Creating a preview for the same sandbox and port returns the existing active preview instead of a duplicate.

FieldTypeRequiredDefaultConstraints
portintegerYes1–65535
authModestringNo"authenticated"authenticated is the only v1 value
sourceCommandIdstringNocmd_ ID of the command serving the port
Terminal
curl -X POST https://api.crownest.dev/v1/sandboxes/sbx_abc123/previews \
  -H "Authorization: Bearer $CROWNEST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "port": 3000, "sourceCommandId": "cmd_abc123" }'

Returns 201 with the preview:

{
  "preview": {
    "id": "prv_abc123",
    "slug": "p-a1b2c3",
    "url": "https://p-a1b2c3.preview.crownest.dev",
    "orgId": "org_abc123",
    "projectId": "prj_abc123",
    "sandboxId": "sbx_abc123",
    "port": 3000,
    "authMode": "authenticated",
    "createdAt": "2026-06-11T13:00:00.000Z"
  }
}

Errors: invalid_request, unsupported_preview_auth_mode, forbidden, not_found, sandbox_destroyed. If the port stops responding later, requests to the preview URL fail with preview_unavailable (502).

List previews

GET /v1/sandboxes/{sandboxId}/previews — requires scope preview:read.

Returns a paginated list of the sandbox's previews, newest first. Standard limit and cursor parameters apply.

Terminal
curl https://api.crownest.dev/v1/sandboxes/sbx_abc123/previews \
  -H "Authorization: Bearer $CROWNEST_API_KEY"
{
  "data": [
    {
      "id": "prv_abc123",
      "url": "https://p-a1b2c3.preview.crownest.dev",
      "port": 3000,
      "authMode": "authenticated"
    }
  ],
  "hasMore": false
}

Get a preview

GET /v1/previews/{previewId} — requires scope preview:read.

Returns one preview by ID.

Terminal
curl https://api.crownest.dev/v1/previews/prv_abc123 \
  -H "Authorization: Bearer $CROWNEST_API_KEY"

Returns 200 with { "preview": { ... } }. Errors: forbidden, not_found.

Revoke a preview

DELETE /v1/previews/{previewId} — requires scope preview:revoke.

Revokes the preview so its URL stops routing to the sandbox. The operation is idempotent — revoking an already-revoked preview returns the revoked record.

Terminal
curl -X DELETE https://api.crownest.dev/v1/previews/prv_abc123 \
  -H "Authorization: Bearer $CROWNEST_API_KEY"

Returns 200 with { "preview": { ... } } including revokedAt. Errors: forbidden, not_found.

Next steps

On this page