Skip to content
Raster
Esc
navigateopen⌘Jpreview
On this page

Published ports

A guest port at its own https hostname — private by default, and the credential shown once.

A published port answers at its own https hostname, which reaches exactly that one port on exactly that one machine. There is no path, query or header a caller can send that reaches a different port, a different machine, or the host underneath: the hostname is the whole routing decision, and it is resolved server-side.

GET    /v1/machines/{id}/ports                published ports on a machine
POST   /v1/machines/{id}/ports                publish one
GET    /v1/machines/{id}/ports/{preview_id}
DELETE /v1/machines/{id}/ports/{preview_id}   stop publishing
GET    /v1/ports                              every published port in the organization

Publishing

const preview = await machine.ports.expose(3000, { name: "dev-server" });
preview.url; // https://k3f9x2q7m1.preview.example.com
preview.access_url; // the one-shot credentialed link
preview.secret; // the raw secret

port is the port inside the machine, not a host port. Nothing has to be listening yet: exposing before starting the server is the ordinary order, and the URL reports the machine as unavailable until something answers.

Exposing a port that is already published returns the preview that exists rather than a second hostname for one service, so a retry converges.

Private by default

access is private unless you say otherwise, and public is a deliberate act with a deliberate name. An agent that exposes a port so a person can look at it should have to say that is what it meant, and someone reading a list should be able to see which of their services are on the open internet without opening each one.

await machine.ports.expose(3000, { access: "public" }); // no credential at all

The secret is shown once

secret and access_url are present only in the response to the call that created the preview. There is no route that returns them afterwards — a value the product can hand back on request is a value that lives in every log and cache the response passes through, exactly like an API key.

access_url is a one-shot link that trades the secret for a host-scoped cookie. That is what makes a private preview openable in a browser at all: a person cannot set an Authorization header on an address bar, and putting the secret in the preview’s own query string would leave it in browser history, in referers, and in the guest application’s own access log.

Unpublishing

await machine.ports.unexpose(preview.id);

The URL stops answering immediately, and that hostname is never issued again. A hostname that came back would resurrect every link and bookmark pointing at it, aimed at whatever that port serves next.

Fields

Field Meaning
port the port inside the machine
name your label, or null
access private or public
url the https URL it answers on
secret at creation only; null on every later read
access_url at creation only; null on every later read
last_request_at when it was last reached, or null

Deployment requirement

Publishing needs the deployment to have a preview domain configured, with a wildcard DNS record and a wildcard certificate under it. Without one the API refuses with unsupported_operation rather than handing back a URL that resolves nowhere — a far better failure than a customer debugging a dev server that was never reachable.

Bytes served through a preview count as egress. See billing.

Was this page helpful?