sandbox.get_url(port) and sandbox.get_websocket_url(port). They return
preview URLs. Older docs and scripts may call this surface “public URLs”; the
current product name is Preview URLs.
Start a server
Host information
sandbox.get_url(port) returns info.url when a signed HTTP URL is present
and otherwise falls back to the bare host with the API scheme. get_websocket_url
does the same for WebSocket URLs.
WebSocket URL for exposed ports
websocket_url returned by the SDK or CLI. For SSH, use SSH Access
instead of preview URL routing. Only older port-22 fallback deployments use SSH
as an exposed WebSocket service.
Behavior
The returned URL includes a signed edge token. Treat it as a bearer credential and rotate by requesting a fresh preview URL when needed. After a browser opens the signed HTTP URL, Nullspace edge can use a scoped HTTP-only continuation cookie so normal navigation, refreshes, relative links, redirects, and assets do not need to preserve the query token. The service inside the sandbox must bind to0.0.0.0, not only 127.0.0.1.
Self-hosted ingress
The single-host OSS appliance uses API-compatible ingress, notapps/edge.
In localhost/no-domain mode, the appliance leaves
NULLSPACE_PUBLIC_HOSTNAME unset. Caddy serves the console at /console and
proxies API/WebSocket routes to the local API, but signed public preview
hostnames are not available. Use sandbox.get_host(port) or
sandbox.get_host_info(port) for direct local port mappings in private
operator-only environments.
In owned-domain mode, operators set NULLSPACE_PUBLIC_HOSTNAME to a DNS name
they control and configure wildcard DNS so preview subdomains resolve to the
single host. Signed preview URLs use
https://{PORT}-{SANDBOX_ID}.${NULLSPACE_PUBLIC_HOSTNAME}/?edge_token=... for
HTTP and the matching wss:// URL for WebSocket. Caddy obtains exact-host
preview certificates on demand through a loopback-only API ask endpoint, then
proxies those hosts to nullspace-api while preserving the original Host and
forwarded client/proto headers so the API can parse the sandbox and port without
apps/edge.
The launch gate records the difference explicitly. In --mode localhost, it
asserts direct get_host/get_host_info mappings and no signed URL metadata.
In --mode owned-domain, it asserts signed HTTP and WebSocket preview URL
metadata and Caddy routing without apps/edge.
Embedding
Direct preview links are not iframe targets. Their browser continuation cookie is host-scoped and usesSameSite=Lax. No SameSite=None direct preview cookie
mode is available for third-party iframe embedding. Customer-run preview
proxies are the supported path for embedding, custom browser sessions, and
custom-domain presentation.
Warnings and CORS
Nullspace does not add a preview warning or interstitial before serving direct preview traffic. Treat signed preview URLs as bearer credentials and share them only with trusted recipients. Preview CORS and browser response headers come from the sandbox service or the customer-run proxy in front of it. Nullspace preview edge does not inject a separate CORS policy for direct preview links.Expiry, inventory, and revocation
Usesandbox.create_signed_preview_url(port, expires_in_seconds=...) or
nullspace sandbox preview-url create <id> <port> --expires 15m when you need a
durable grant with an explicit expiry. Use sandbox.list_preview_urls() or
nullspace sandbox preview-url list <id> to inspect active and recent grants,
and sandbox.revoke_preview_url(grant_id) or
nullspace sandbox preview-url revoke <id> <grant-id> to revoke a grant before
it expires.
Grant inventory is token-redacted. It includes status, expiry, first and last
use, validation use count, HTTP request count, WebSocket connection count,
byte-in and byte-out counters, last error code/time, and disabled time when an
operator has temporarily disabled a grant. Operator audit records use the same
safe identifiers and never store raw preview tokens.
Direct preview URLs use query-token bootstrap auth for HTTP and WebSocket URLs.
Custom preview proxy targets use header-token auth instead, so customer-run
proxies can keep Nullspace bearer credentials out of browser-visible URLs.
Agent service deployments reuse the same ingress path. nullspace agent url
and the SDK service URL helper return a dynamic URL only after the service is
ready and permissions.public_url is enabled. Edge environments return either
a host-style or path-style URL depending on operator configuration; both forms
can include a short-lived edge_token query parameter. Do not store these URLs
in deployment config, logs, or source files. If service permissions disable
public traffic, ingress may also require the x-nullspace-traffic-access-token
header documented in Access control.
The Console Preview tab exposes the same workflow for a sandbox: create a
direct preview link, open it in a new browser tab, copy raw secret values only
after confirmation, create a custom preview proxy target, inspect grant
inventory, revoke grants, and run readiness diagnostics.
Port policy
Preview URLs support normal application ports in the1-65535 range,
including privileged HTTP ports such as 80 and 443. Generic preview URLs do
not expose platform-owned guest ports:
| Port | Use |
|---|---|
22 | SSH access; use SSH Access instead of preview URLs. |
5900-5999 | Desktop/VNC traffic; use the managed desktop viewer. |
3000 and 8080 remain valid sandbox preview ports.
Readiness
Creating or resolving a preview URL confirms that routing exists; it does not wait for the server process inside the sandbox to listen. Use the SDK or CLI wait helpers when startup is asynchronous:0.0.0.0 inside the sandbox rather than only 127.0.0.1.
Use Custom Preview Proxy when you need your own domain, app session checks, or
proxy middleware in front of a sandbox preview. That flow returns a marker-only
upstream URL and a header token for your proxy to send to Nullspace edge, so
browser-visible URLs do not contain Nullspace bearer credentials. A managed
custom preview domain workflow is not part of the current launch.
If the sandbox was created with on_timeout="pause", auto_resume=True, HTTP
and WebSocket requests to signed preview URLs can wake a paused sandbox. When
auto-resume is disabled or the wake cannot finish in time, callers receive
503 Service Unavailable with Retry-After: 5 and JSON fields for code,
retryable, and suggested_action.
Troubleshooting
| Code or symptom | What to do |
|---|---|
unsupported_preview_port | Use an application port in 1-65535 except 22 and 5900-5999. |
preview_service_not_ready | Confirm the server is running on that port and binding to 0.0.0.0; use sandbox.wait_for_preview(port) while it starts. |
edge_token_missing | Use the full signed URL returned by sandbox.get_url(port) or request a fresh signed preview URL. |
edge_token_expired, preview_grant_revoked | Request a fresh preview URL before retrying the direct browser request. |
preview_grant_disabled, preview_proxy_token_disabled, preview_sandbox_disabled | Preview access was disabled by an operator control. Use another route or ask an operator to re-enable preview traffic before retrying. |
preview_proxy_token_missing | Forward the x-nullspace-preview-proxy-token header returned by create_preview_proxy_target. |
preview_proxy_token_expired, preview_proxy_token_revoked | Create a fresh preview proxy target and update the proxy header token. |
rate_limit_exceeded | Wait for the Retry-After window before retrying. Repeated 429s usually mean too many requests from the same preview grant, port, transport, and client address. |
edge_runtime_host_unreachable | Check readiness with sandbox.wait_for_preview(port), nullspace sandbox preview-url create <id> <port> --wait, or nullspace sandbox url <id> <port> --wait, then retry. |
sandbox_paused_auto_resume_disabled | Resume the sandbox manually or recreate it with on_timeout="pause", auto_resume=True. |
| Localhost self-host returns no signed URL metadata | Expected when NULLSPACE_PUBLIC_HOSTNAME is unset. Use direct get_host_info() mappings or configure owned-domain mode. |
| Owned-domain self-host returns direct mappings | Confirm NULLSPACE_PUBLIC_HOSTNAME, NULLSPACE_EDGE_PUBLIC_BASE_URL, NULLSPACE_EDGE_ACCESS_TOKEN_SIGNING_KEY, and NULLSPACE_PUBLIC_INGRESS_MODE=api_compat, then rerun nullspace-host launch-gate --mode owned-domain. |
| Auto-resume timeout or control-plane unreachable | Retry after Retry-After; if it repeats, check runtime capacity and sandbox startup logs. |
Create-time network controls
Sandbox create accepts anetwork dictionary for deployment-supported network
policy controls and an internet_access flag for outbound internet access:
Access control for private preview URLs, traffic
tokens, outbound network policy, and Host header masking.
Use Token model for the difference between API keys, edge
preview tokens, preview continuation cookies, proxy tokens, and private traffic
tokens.