Skip to main content
Custom preview proxies let you serve a sandbox preview through your own domain, session model, headers, and application proxy while keeping Nullspace edge credentials out of browser-visible URLs.

Custom domains

The customer-run preview proxy is the supported custom-domain path for the current launch. Put your own domain, authentication, branding, and browser session policy in front of the marker-only upstream URL returned by Nullspace. No managed custom preview domain inventory, DNS verification or TLS issuance workflow is exposed by Nullspace yet. The API surface remains the preview proxy target plus durable preview grant inventory and revocation.

Create a proxy target

from nullspace import Sandbox

sandbox = Sandbox.connect("sb_123")
target = sandbox.create_preview_proxy_target(
    8080,
    expires_in_seconds=900,
    transports=["http", "websocket"],
)

print(target.http_url)
print(target.websocket_url)
print(target.token_header_name)
print(target.required_forwarded_headers)
The returned http_url and websocket_url include __ns_preview_transport=header. That marker is not a secret. The secret is the transport-specific token value:
FieldUse
http_urlUpstream HTTP target for your proxy.
websocket_urlUpstream WebSocket target for your proxy.
http_tokenSend as x-nullspace-preview-proxy-token for HTTP upstream requests.
websocket_tokenSend as x-nullspace-preview-proxy-token for WebSocket upstream requests.
expires_atExpiration for the proxy grant and returned tokens.
traffic_access_requiredWhether private traffic access also requires a traffic token header.

Forward upstream

Your proxy should authenticate the browser request using your own app controls, then forward to the Nullspace upstream target with the preview proxy token:
curl -fsS \
  -H "x-nullspace-preview-proxy-token: ${NULLSPACE_PREVIEW_PROXY_HTTP_TOKEN}" \
  -H "x-forwarded-host: app.example.com" \
  -H "x-forwarded-proto: https" \
  -H "x-forwarded-for: 203.0.113.10" \
  "${NULLSPACE_PREVIEW_PROXY_HTTP_URL}"
Forward the headers listed in required_forwarded_headers. Use http_token only for HTTP upstream requests and websocket_token only for WebSocket upgrades; tokens are scoped to the sandbox, port, grant, principal, expiry, and transport. Nullspace preserves X-Forwarded-Host, X-Forwarded-Proto, and X-Forwarded-For exactly as your proxy sends them. It does not add missing forwarded headers or append to an existing X-Forwarded-For chain. If the sandbox service also needs a different upstream Host, configure network.mask_request_host; that setting changes only the Host header sent to the sandbox service and does not rewrite X-Forwarded-* metadata. HTTP responses are returned to the browser as sandbox services emit them, including redirects with relative Location values. For WebSocket routes, use the returned websocket_url and websocket_token; HTTP proxy tokens are not valid for WebSocket upgrades. See the custom preview proxy example for minimal Node/Express and Python/FastAPI proxy apps that forward HTTP, WebSocket, private traffic, and required forwarded headers.

Private traffic tokens

When a sandbox is created with network={"allow_public_traffic": False}, the proxy target response reports traffic_access_required: true and the traffic access header name. It does not return the traffic token value. Store the sandbox.traffic_access_token returned at sandbox create time and send it upstream as a separate secret:
-H "x-nullspace-traffic-access-token: ${NULLSPACE_TRAFFIC_ACCESS_TOKEN}"
Preview proxy tokens and traffic access tokens are not interchangeable. Edge validates them independently, and Nullspace strips both headers before the request reaches the sandbox service.

Rotation and revocation

Create a fresh proxy target before expires_at when your proxy needs continued access. Proxy targets use durable preview grants, so sandbox.list_preview_urls() includes them and sandbox.revoke_preview_url(grant_id) revokes them.