# How to rotate a preview token Call `sbx.previews.rotate(port)`: every token issued for that port stops working, and the call returns a new one. **On Runtime a preview is private from the moment you create it, and one call revokes every link you have handed out.** The address stays the same, so a bookmark keeps working for anyone you give the new token. Previews live under `runtimehost.com`, never under `withruntime.com`, so what a sandbox serves never shares an origin with your account. A fresh sandbox to serve from ran its first command 351 ms after the request at the median on 24 September 2026 ([speed](/docs/speed)). ## Rotate the token ```ts check import { Sandbox } from "withruntime"; await using sbx = await Sandbox.create(); await sbx.spawn("python3 -m http.server 3000"); const first = await sbx.previews.create(3000); const fresh = await sbx.previews.rotate(3000); // first.token is refused from now on const page = await fetch(fresh.url, { headers: { "x-runtime-preview-token": fresh.token! }, }); console.log(fresh.url === first.url, page.status); ``` ```python check from withruntime import Sandbox with Sandbox.create() as sbx: sbx.spawn("python3 -m http.server 3000") first = sbx.previews.create(3000) fresh = sbx.previews.rotate(3000) # first["token"] is refused from now on print(fresh["url"] == first["url"], fresh["token"] is not None) ``` Over plain HTTPS the same call is a `POST` to the preview's `:rotate` route ([API reference](/docs/api)): ```bash no-run curl -sS -X POST "https://api.withruntime.com/v1/sandboxes/${ID}/previews/3000:rotate" \ -H "Authorization: Bearer ${RUNTIME_API_KEY}" ``` The answer carries the new `token` and a new one-time `urlWithToken` for a browser. Send the token as the `x-runtime-preview-token` header from code. ## When to rotate - **A link went somewhere it should not:** a public chat, a ticket, a screenshot, a log. - **Someone who had access leaves the project.** Rotation cuts off every holder at once, whoever they forwarded the link to. - **A demo or review is over** but the sandbox keeps running for you. - **On a schedule,** for a preview that stays up for days, so no token stays useful for long. ## Rotate, delete or leave public | Call | What happens | | ----------------------------------------------------- | ------------------------------------------------------------------------ | | `sbx.previews.create(3000)` | Shares the port, private: a request needs the token | | `sbx.previews.rotate(3000)` | Refuses every token issued for the port so far and returns a new one | | `sbx.previews.delete(3000)` | Stops sharing the port; `runtime sandbox unshare 3000` from the CLI | | `sbx.previews.create(3000, { visibility: "public" })` | Anyone with the address can open it; no token to rotate | | `runtime sandbox previews ` | Lists the sandbox's shared ports | Rotating keeps the port shared and the server running. Deleting stops the sharing altogether. Choose rotate when the right people still need the page and delete when nobody does. MCP agents create, list and delete previews with `runtime_sandbox_previews_create`, `_list` and `_delete` ([MCP](/docs/mcp)). ## Mistakes and how Runtime handles them - **Forwarding `urlWithToken`.** That link carries its token once, for one browser. Give each person their own, or send the token in the header from code. - **Expecting a public preview to be protected.** A public address needs no token, so rotating protects nothing. Keep previews that show private data private. - **The page stops answering after a rotate.** Old tokens are refused by design. Hand out the new one; the server inside the sandbox was not touched. - **The server dies with its command.** Start it with `spawn`, not `exec`, and have it listen on `0.0.0.0` or `localhost` inside the sandbox ([the sandbox environment](/docs/sandbox-environment#the-network)). - **A paused sandbox.** A visit to a shared port wakes it; the browser sees a short "Waking up" page that reloads itself ([wake on request](/docs/javascript#wake-on-request)). Every answer from a preview carries an `X-Runtime-Report` header, through which anyone can report it, and Runtime can turn a reported preview off ([custom domains](/docs/networking#custom-domains) work the same way). ## For your own hostname A preview address is Runtime's. To serve the same port at a name you own, with HTTPS, add a [custom domain](/how-to/add-a-custom-domain). To reach the port from your own machine only, with no link at all, use [port forwarding](/how-to/port-forward-a-database). ## Related - [Share a port](/docs/javascript#share-a-port) in the JavaScript guide. - [Network access](/docs/security#network-access): what can reach a sandbox. - [Preview agent-built apps](/use-cases/preview-agent-built-apps). Facts on this page were checked on 25 September 2026.