> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ns.rocks/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a custom preview proxy target

> Creates a durable preview proxy grant for a customer-run reverse proxy.
The returned upstream URL(s) use header token transport and include the
non-secret `__ns_preview_transport=header` marker. The proxy must send
the returned token value in `x-nullspace-preview-proxy-token` on every
upstream request. HTTP and WebSocket tokens are kind-scoped and returned
separately when both transports are requested.




## OpenAPI

````yaml /openapi.yaml post /v1/machines/{id}/ports/{port}/preview-proxy-target
openapi: 3.1.0
info:
  title: Nullspace API
  version: 0.1.0
  description: |
    Cloud machine platform for AI agents. Create on-demand microVMs,
    execute commands, manage files, automate desktop environments,
    and stream output over WebSocket.
  license:
    name: Apache-2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
servers:
  - url: https://api.13-215-85-171.sslip.io
    description: Private beta
  - url: https://nullspace.example
    description: Self-hosted single-host owned-domain
  - url: http://localhost
    description: Self-hosted single-host localhost/no-domain via Caddy
  - url: http://localhost:3000
    description: Local development direct API
security:
  - bearerAuth: []
tags:
  - name: Health
    description: Public process-liveness check (no auth required)
  - name: Machines
    description: Machine lifecycle, execution, and process management
  - name: Files
    description: Filesystem operations within a machine
  - name: Git
    description: First-class structured git operations within a machine
  - name: Desktop
    description: Desktop automation (mouse, keyboard, screenshots)
  - name: Recording
    description: Screen recording management
  - name: PTY
    description: Pseudo-terminal session management
  - name: Templates
    description: Machine template management
  - name: Agent Deployments
    description: Named, versioned agent deployment control plane
  - name: Volumes
    description: Persistent volume control plane and attached volume actions
  - name: WebSocket
    description: Streaming execution and PTY over WebSocket
  - name: Monitor
    description: In-repo WebSocket stream for machine health, metrics, and process updates
  - name: API Keys
    description: Runtime API key metadata and dormant self-serve key management
  - name: Account
    description: Dormant Supabase-session account profile, export, and deletion routes
  - name: Admin
    description: Supabase-session operator console APIs for account support
  - name: Auth
    description: Dormant self-serve Auth proxy routes gated by deployment config
  - name: Code
    description: Stateful code execution via Jupyter kernels (Code Interpreter)
  - name: Internal Operations
    description: Operator-only internal API surfaces; not part of the public SDK contract
paths:
  /v1/machines/{id}/ports/{port}/preview-proxy-target:
    parameters:
      - $ref: '#/components/parameters/MachineId'
      - $ref: '#/components/parameters/MachinePort'
    post:
      tags:
        - Machines
      summary: Create a custom preview proxy target
      description: |
        Creates a durable preview proxy grant for a customer-run reverse proxy.
        The returned upstream URL(s) use header token transport and include the
        non-secret `__ns_preview_transport=header` marker. The proxy must send
        the returned token value in `x-nullspace-preview-proxy-token` on every
        upstream request. HTTP and WebSocket tokens are kind-scoped and returned
        separately when both transports are requested.
      operationId: createPreviewProxyTarget
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePreviewProxyTargetRequest'
            examples:
              both:
                summary: HTTP and WebSocket proxy target
                value:
                  expires_in_seconds: 900
                  transports:
                    - http
                    - websocket
                  token_transport: header
                  include_traffic_token_hint: true
              httpOnly:
                summary: HTTP-only proxy target
                value:
                  transports:
                    - http
      responses:
        '200':
          description: Preview proxy target metadata and header token values
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PreviewProxyTargetResponse'
        '400':
          description: Invalid request or unsupported preview port
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                unsupportedPreviewPort:
                  summary: Unsupported preview port
                  value:
                    error: >-
                      preview port 22 is reserved for SSH access; use the SSH
                      relay or choose an application port
                    code: unsupported_preview_port
                    request_id: req_123
                invalidTransport:
                  summary: Invalid proxy transport
                  value:
                    error: 'unsupported preview proxy transport: ftp'
                    code: invalid_request
                    request_id: req_123
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/MachineNotFound'
        '503':
          $ref: '#/components/responses/FeatureUnavailable'
components:
  parameters:
    MachineId:
      name: id
      in: path
      required: true
      schema:
        type: string
      description: Machine ID (e.g. mch_a1b2c3d4)
    MachinePort:
      name: port
      in: path
      required: true
      schema:
        type: integer
        format: uint16
        minimum: 1
        maximum: 65535
      description: >
        Machine guest port to expose through browser preview. Reserved
        generic-preview ports are rejected:

        `22` is SSH-specific and `5900`-`5999` are desktop/VNC-specific.
  schemas:
    CreatePreviewProxyTargetRequest:
      type: object
      properties:
        expires_in_seconds:
          type: integer
          format: uint64
          minimum: 60
          maximum: 86400
          description: >-
            Requested proxy grant lifetime. Defaults to the deployment edge
            token TTL, clamped between 60 seconds and 24 hours.
        transports:
          type: array
          default:
            - http
            - websocket
          minItems: 1
          uniqueItems: true
          description: Proxy upstream transports to authorize.
          items:
            type: string
            enum:
              - http
              - websocket
        token_transport:
          type: string
          default: header
          enum:
            - header
          description: >-
            Token transport used by the customer proxy when forwarding to
            Nullspace edge.
        include_traffic_token_hint:
          type: boolean
          default: true
          description: >-
            When true, include whether private traffic access is required and
            the header name to use.
    PreviewProxyTargetResponse:
      type: object
      required:
        - grant
        - machine_id
        - port
        - token_header_name
        - expires_at
        - token_transport
        - required_forwarded_headers
        - warnings
      properties:
        grant:
          $ref: '#/components/schemas/PreviewGrantInfo'
        machine_id:
          type: string
        port:
          type: integer
          format: uint16
        http_url:
          type: string
          format: uri
          nullable: true
          description: >-
            HTTP upstream target with `__ns_preview_transport=header` and no
            bearer token in the URL.
          example: https://3000-s-public.nullspace.dev/?__ns_preview_transport=header
        websocket_url:
          type: string
          nullable: true
          description: >-
            WebSocket upstream target with `__ns_preview_transport=header` and
            no bearer token in the URL.
          example: wss://3000-s-public.nullspace.dev/?__ns_preview_transport=header
        http_token:
          type: string
          nullable: true
          description: >-
            Header token scoped to HTTP proxy traffic. Send as
            `x-nullspace-preview-proxy-token`.
        websocket_token:
          type: string
          nullable: true
          description: >-
            Header token scoped to WebSocket proxy traffic. Send as
            `x-nullspace-preview-proxy-token`.
        token_header_name:
          type: string
          enum:
            - x-nullspace-preview-proxy-token
        expires_at:
          type: string
          format: date-time
        token_transport:
          type: string
          enum:
            - header
        required_forwarded_headers:
          type: array
          items:
            type: string
            enum:
              - x-forwarded-host
              - x-forwarded-proto
              - x-forwarded-for
          description: >-
            Headers customer proxies should preserve or set when forwarding
            browser requests.
        traffic_access_required:
          type: boolean
          nullable: true
          description: >-
            Whether this machine also requires the private traffic access
            header.
        traffic_access_header_name:
          type: string
          nullable: true
          enum:
            - x-nullspace-traffic-access-token
          description: >-
            Header name for private traffic access when required. The secret
            value is not returned here.
        warnings:
          type: array
          items:
            type: string
    ErrorResponse:
      type: object
      required:
        - error
        - code
      properties:
        error:
          type: string
          description: Human-readable error message
        code:
          type: string
          description: Machine-readable error code
          enum:
            - invalid_request
            - machine_not_found
            - snapshot_not_found
            - template_not_found
            - template_build_not_found
            - template_name_claim_not_found
            - machine_not_ready
            - unauthorized
            - auth_failed
            - auth_locked
            - auth_proxy_error
            - auth_proxy_unavailable
            - invalid_auth_redirect
            - invalid_oauth_provider
            - captcha_required
            - captcha_failed
            - captcha_unavailable
            - disposable_email
            - signup_rate_limited
            - oauth_rate_limited
            - email_action_rate_limited
            - database_error
            - email_not_verified
            - account_deleted
            - operator_required
            - account_not_found
            - account_not_soft_deleted
            - account_hard_delete_active_resources
            - file_upload_error
            - build_error
            - exec_timeout
            - exec_failed
            - file_error
            - not_implemented
            - capacity_exceeded
            - QUOTA_EXCEEDED
            - feature_unavailable
            - snapshot_in_use
            - no_eligible_runtime_host
            - same_host_required
            - incompatible_snapshot
            - rebuild_required
            - rate_limit_exceeded
            - transition_in_progress
            - transition_conflict
            - agent_deployment_not_found
            - agent_deployment_version_not_found
            - agent_run_not_found
            - agent_service_instance_not_found
            - agent_deployment_name_conflict
            - agent_deployment_idempotency_mismatch
            - agent_deployment_invalid_config
            - agent_deployment_invalid_state
            - volume_beta_restriction
            - volume_invalid_mount_path
            - volume_overlapping_mounts
            - volume_backend_capability_unsupported
            - volume_quota_exceeded
            - volume_mount_credential_issue_failed
            - volume_backend_unavailable
            - volume_stale_revision
            - volume_busy
            - volume_read_only
            - volume_limit_exceeded
            - internal_error
        error_detail:
          $ref: '#/components/schemas/ErrorDetail'
        request_id:
          type: string
          description: Request correlation ID returned in the `x-request-id` header
        build_id:
          type: string
          description: Template build ID when the error is associated with a tracked build
    PreviewGrantInfo:
      type: object
      required:
        - id
        - machine_id
        - port
        - status
        - auth_mode
        - bootstrap_transport
        - token_kinds
        - principal_kind
        - issued_at
        - expires_at
        - use_count
        - http_request_count
        - websocket_connection_count
        - bytes_in_count
        - bytes_out_count
        - created_at
        - updated_at
      properties:
        id:
          type: string
          pattern: ^pvg_[0-9a-f]{32}$
          description: Durable preview grant ID. Raw token values are never included.
        machine_id:
          type: string
        port:
          type: integer
          format: uint16
        status:
          type: string
          enum:
            - active
            - expired
            - revoked
            - disabled
          description: Derived grant lifecycle status at response time.
        auth_mode:
          type: string
          enum:
            - direct
            - proxy
        bootstrap_transport:
          type: string
          enum:
            - query
            - header
        token_kinds:
          type: array
          items:
            type: string
            enum:
              - http_port
              - websocket_port
        principal_kind:
          type: string
          enum:
            - user
        principal_id:
          type: string
          nullable: true
        issued_at:
          type: string
          format: date-time
        expires_at:
          type: string
          format: date-time
        revoked_at:
          type: string
          format: date-time
          nullable: true
        first_used_at:
          type: string
          format: date-time
          nullable: true
        last_used_at:
          type: string
          format: date-time
          nullable: true
        use_count:
          type: integer
          format: int64
          description: Count of durable preview grant validation callbacks.
        http_request_count:
          type: integer
          format: int64
          description: Safe aggregate count of HTTP preview requests observed by edge.
        websocket_connection_count:
          type: integer
          format: int64
          description: >-
            Safe aggregate count of WebSocket preview connections observed by
            edge.
        bytes_in_count:
          type: integer
          format: int64
          description: Safe aggregate request/client-to-upstream bytes observed by edge.
        bytes_out_count:
          type: integer
          format: int64
          description: Safe aggregate response/upstream-to-client bytes observed by edge.
        last_error_code:
          type: string
          nullable: true
          description: Most recent edge/control-plane preview error code for this grant.
        last_error_at:
          type: string
          format: date-time
          nullable: true
        disabled_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    ErrorDetail:
      oneOf:
        - $ref: '#/components/schemas/TemplateFailureDetail'
        - $ref: '#/components/schemas/UploadFailureDetail'
    TemplateFailureDetail:
      type: object
      required:
        - code
        - message
        - phase
        - retryable
        - suggested_action
      properties:
        code:
          type: string
          enum:
            - unauthorized
            - file_upload_error
            - build_error
            - internal_error
        message:
          type: string
        phase:
          $ref: '#/components/schemas/TemplateFailurePhase'
        retryable:
          type: boolean
        suggested_action:
          type: string
        step_index:
          type: integer
        attempt:
          type: integer
        max_attempts:
          type: integer
        cache_subject:
          type: string
        build_id:
          type: string
        request_id:
          type: string
          description: >-
            Present on terminal request-originated failures and blocking error
            responses.
        details:
          type: object
          additionalProperties: true
          description: >-
            Stable failure metadata. Includes a `reason` key plus phase-specific
            fields such as `blob_id`, `path`, digest/size mismatch values,
            `command`, or `alias`.
    UploadFailureDetail:
      type: object
      required:
        - reason
        - message
        - retryable
      properties:
        reason:
          $ref: '#/components/schemas/UploadFailureReason'
        message:
          type: string
        retryable:
          type: boolean
        upload_id:
          type: string
        request_id:
          type: string
        path:
          type: string
          description: >-
            Normalized absolute machine path associated with the failed upload
            when available.
        part_number:
          type: integer
          format: uint32
        details:
          type: object
          additionalProperties: true
          description: >-
            Additional failure diagnostics; keys depend on the failure reason,
            deliberately open.
    TemplateFailurePhase:
      type: string
      enum:
        - auth
        - preflight
        - blob_upload
        - prepare
        - build_step
        - readiness
        - snapshot
        - finalize
        - interrupted
    UploadFailureReason:
      type: string
      enum:
        - insufficient_staging_space
        - size_limit_exceeded
        - invalid_part_checksum
        - part_out_of_range
        - part_size_mismatch
        - whole_checksum_mismatch
        - upload_expired
        - upload_aborted
        - upload_already_completed
        - target_conflict
        - directory_extract_invalid_path
        - directory_extract_invalid_symlink
        - directory_extract_unsupported_entry
        - missing_parts
  responses:
    Unauthorized:
      description: Missing or invalid bearer credential
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            unauthorized:
              summary: Missing or invalid bearer credential
              value:
                error: Missing or invalid bearer credential
                code: unauthorized
                request_id: req_123
    MachineNotFound:
      description: Machine not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    FeatureUnavailable:
      description: Feature is unavailable in current deployment mode
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key passed as Bearer token

````