> ## 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 new machine



## OpenAPI

````yaml /openapi.yaml post /v1/machines
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:
    post:
      tags:
        - Machines
      summary: Create a new machine
      operationId: createMachine
      parameters:
        - $ref: '#/components/parameters/IdempotencyKeyHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateMachineRequest'
            examples:
              fromTemplate:
                summary: Create from a template
                value:
                  template: base
                  timeout_ms: 300000
                  metadata:
                    purpose: interactive
              fromReusableSnapshot:
                summary: Create from a reusable snapshot
                value:
                  snapshot_id: snap_a1b2c3d4
                  timeout_ms: 300000
                  metadata:
                    run: child-1
      responses:
        '201':
          description: Machine created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateMachineResponse'
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          description: Template artifact is not available for machine launch.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                templateArtifactUnavailable:
                  summary: Exact build artifact is unavailable
                  value:
                    error: artifact retention window has expired
                    code: template_build_artifact_unavailable
                    request_id: req_123
        '429':
          $ref: '#/components/responses/QuotaExceeded'
        '503':
          description: >-
            A required warm-pool checkout could not claim matching ready
            inventory.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Suggested retry delay in seconds.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                warmPoolUnavailable:
                  summary: Required warm pool has no matching ready instance
                  value:
                    error: warm pool unavailable
                    code: warm_pool_unavailable
                    request_id: req_123
components:
  parameters:
    IdempotencyKeyHeader:
      name: Idempotency-Key
      in: header
      required: true
      schema:
        type: string
      description: >-
        Reuse the same key to safely retry the same create, reusable snapshot
        create, fork, upload create/complete, or agent deployment create
        operation without duplicating work.
  schemas:
    CreateMachineRequest:
      type: object
      properties:
        snapshot_id:
          type: string
          description: >-
            Durable reusable snapshot ID to restore into a fresh machine. When
            provided, sizing, template, environment, filesystem, and VM egress
            policy are taken from the snapshot; each create idempotency key
            creates at most one child machine and the snapshot remains reusable
            for additional create requests.
        warm_pool:
          $ref: '#/components/schemas/WarmPoolCheckoutRequest'
        template:
          type: string
          default: base
          description: Template name or Docker image
        vcpus:
          type: integer
          default: 1
          minimum: 1
        memory_mb:
          type: integer
          default: 256
          minimum: 1
          description: >-
            Guest memory in MiB. When omitted, the default is template-aware:
            the heavyweight `code-interpreter` and `desktop` templates default
            to 2048MB (their GUI/kernel stacks exhaust a smaller allocation),
            and all other templates default to 256MB.
        disk_mb:
          type: integer
          minimum: 512
          maximum: 131072
          description: >-
            Minimum rootfs size in MiB. On cold create the rootfs is grown to
            this size before boot. For snapshot-backed templates the disk size
            is fixed at build time, so disk_mb must not exceed the template's
            built-in size (rebuild the template with a larger disk_mb instead).
            Omit to use the default headroom. Not permitted with snapshot_id.
        timeout_ms:
          type: integer
          default: 300000
          description: Machine auto-destroy timeout in milliseconds
        timeout_action:
          $ref: '#/components/schemas/MachineTimeoutAction'
        inactivity_timeout_ms:
          type: integer
          format: int64
          nullable: true
          minimum: 1
          description: >-
            Opt-in idle timeout in milliseconds. When set, the machine runs
            `timeout_action` (hibernate or destroy) once it has been idle this
            long. Activity is edge ingress or exec/file/pty/process traffic;
            guest-internal idle egress does not count. Composes with the
            absolute `timeout_ms` (whichever fires first wins). Omit to keep the
            existing absolute-only behavior. Not a cap — purely opt-in
            ergonomics.
        auto_delete_after_ms:
          type: integer
          format: int64
          nullable: true
          minimum: 1
          description: >-
            Opt-in window in milliseconds after which a hibernated/paused
            machine is destroyed. Acts only on terminal/hibernated machines;
            never deletes a running machine out from under active traffic.
        ephemeral:
          type: boolean
          default: false
          description: >-
            When true the machine is never hibernated/snapshotted on inactivity;
            it is destroyed instead (forces `timeout_action: destroy`). Cannot
            be combined with `auto_resume`.
        auto_resume:
          type: boolean
          default: false
          description: |
            When true, a hibernated machine is automatically resumed when a
            command, file, PTY, desktop, or proxy route targets its original
            machine ID. Requires `timeout_action: hibernate` or
            `lifecycle.on_timeout: pause`.
        envs:
          type: object
          additionalProperties:
            type: string
        metadata:
          type: object
          additionalProperties: true
          description: >-
            Arbitrary user-supplied metadata attached to the machine; stored
            verbatim (any JSON object), deliberately open.
        internet_access:
          type: boolean
          default: true
          description: When false, the machine has no network connectivity.
        cwd:
          type: string
          nullable: true
          description: >-
            Optional default working directory for machine commands. Must be an
            absolute machine path that stays within the machine root. Accepted
            values are normalized before persistence, and reserved runtime paths
            under `/workspace/.nullspace` are rejected. When omitted, commands
            inherit the template default workdir; the standard agent-oriented
            templates default to `/workspace`. Clients may send an explicit
            null, which is treated the same as omitting the field.
        desktop:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/DesktopCreateConfig'
        network:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/NetworkCreateConfig'
        volumes:
          type: array
          nullable: true
          maxItems: 8
          description: >-
            Create-time shared-volume mount requests. `ref` is the canonical
            selector and accepts either an exact volume name or a volume id. On
            snapshot resume and fork, shared mounts are remounted with fresh
            internal leases before the new machine becomes ready; that storage
            remount does not make VM memory or mutable rootfs state portable
            across incompatible runtime hosts.
          items:
            $ref: '#/components/schemas/VolumeMountRequest'
        lifecycle:
          $ref: '#/components/schemas/LifecycleConfig'
    CreateMachineResponse:
      type: object
      required:
        - id
        - status
        - config
        - template
        - created_at
      properties:
        id:
          type: string
          example: mch_a1b2c3d4
        status:
          $ref: '#/components/schemas/MachineStatus'
        config:
          $ref: '#/components/schemas/MachineConfig'
        template:
          type: string
        metadata:
          type: object
          additionalProperties: true
          description: >-
            Machine metadata. Attached volume state is exposed under
            `volume_attachments` in request order. Free-form user-supplied
            object stored verbatim; deliberately open.
        started_at:
          type: string
          format: date-time
        timeout_ms:
          type: integer
          format: int64
        timeout_at:
          type: string
          format: date-time
        expires_at:
          type: string
          format: date-time
          description: >-
            Alias of `timeout_at` for clients that expect an expiry timestamp
            field.
        timeout_action:
          $ref: '#/components/schemas/MachineTimeoutAction'
        created_at:
          type: string
          format: date-time
        cwd:
          type: string
          description: >-
            Normalized default working directory for this machine when one was
            configured.
        traffic_access_token:
          type: string
          description: >-
            Opaque token returned at create time. Send it as
            `x-nullspace-traffic-access-token` when
            `network.allow_public_traffic` is false.
        warm_pool_checkout:
          $ref: '#/components/schemas/WarmPoolCheckoutResult'
    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
    WarmPoolCheckoutRequest:
      type: object
      description: >-
        Optional custom template warm-pool selector for machine create. V1
        requires an explicit id for prefer and require modes; bypass may omit id
        to force cold create.
      properties:
        id:
          type: string
          description: Tenant-owned warm-pool id such as `twp_review_pool`.
        mode:
          type: string
          enum:
            - prefer
            - require
            - bypass
          default: prefer
          description: >-
            `prefer` falls back to cold create on miss, `require` fails with
            `warm_pool_unavailable`, and `bypass` forces cold create.
        wait_ms:
          type: integer
          format: int64
          minimum: 0
          maximum: 30000
          description: >-
            Optional bounded wait for matching ready inventory before applying
            the selected checkout mode fallback.
    MachineTimeoutAction:
      type: string
      enum:
        - destroy
        - hibernate
    DesktopCreateConfig:
      type: object
      properties:
        resolution:
          $ref: '#/components/schemas/DesktopResolution'
        dpi:
          type: integer
          minimum: 1
        display:
          type: string
          pattern: ^:[0-9]+$
          description: >-
            X display identifier for desktop templates, for example `:1` or
            `:3`.
    NetworkCreateConfig:
      type: object
      properties:
        allow_public_traffic:
          type: boolean
          default: true
          description: >-
            When false, public machine URLs require the
            `x-nullspace-traffic-access-token` header returned by machine
            create.
        mask_request_host:
          type: string
          description: >-
            Optional Host header override for proxied machine requests.
            `${PORT}` is substituted per request.
        egress:
          allOf:
            - $ref: '#/components/schemas/NetworkEgressPolicy'
          description: >-
            Typed egress policy. When set, it takes precedence over the legacy
            `deny_out`/`allow_out` fields and is the only path that can express
            an outbound rate limit. Cannot be combined with
            `deny_out`/`allow_out`.
        deny_out:
          type: array
          description: >-
            Legacy: IPv4 CIDRs to deny for outbound traffic. Use `0.0.0.0/0` to
            deny all. Prefer `egress`.
          items:
            type: string
        allow_out:
          type: array
          description: >-
            Legacy: IPv4 CIDRs to allow for outbound traffic when paired with
            `deny_out` rules such as `0.0.0.0/0`. Prefer `egress`.
          items:
            type: string
    VolumeMountRequest:
      type: object
      required:
        - ref
        - mount_path
      description: >-
        Shared-volume mount request. `ref` accepts either an exact volume name
        or a volume id and is resolved server-side.
      properties:
        ref:
          type: string
          description: >-
            Canonical mount selector for machine create. Accepts either an exact
            volume name or a volume id and is resolved server-side.
        mount_path:
          type: string
          description: >-
            Absolute machine mount path for the attached volume. Values are
            normalized before persistence. `/` and reserved runtime paths under
            `/workspace/.nullspace` are rejected.
        subpath:
          type: string
          nullable: true
          description: >-
            Optional volume-internal subdirectory. Values are normalized
            relative to the volume root and may not escape it.
        read_only:
          type: boolean
          default: false
    LifecycleConfig:
      type: object
      properties:
        on_timeout:
          type: string
          enum:
            - destroy
            - pause
          default: destroy
          description: |
            What the reaper does when timeout_ms expires.
            `destroy` tears down the VM (default).
            `pause` hibernates the machine so it can be resumed later.
    MachineStatus:
      type: string
      enum:
        - creating
        - running
        - paused
        - destroyed
        - error
    MachineConfig:
      type: object
      properties:
        vcpus:
          type: integer
        memory_mb:
          type: integer
        disk_mb:
          type: integer
    WarmPoolCheckoutResult:
      type: object
      required:
        - source
        - hit
      description: >-
        Create-time warm-pool checkout result. Omitted when create did not
        consider a warm pool.
      properties:
        source:
          type: string
          enum:
            - ready_instance
            - cold_create
            - bypassed
          description: >-
            `ready_instance` means a parked VM was claimed, `cold_create` means
            create continued with a new VM, and `bypassed` means the request
            explicitly skipped warm pools.
        hit:
          type: boolean
          description: True only when `source` is `ready_instance`.
        id:
          type: string
          description: Warm-pool id that was claimed or attempted when available.
        mode:
          type: string
          enum:
            - prefer
            - require
            - bypass
          description: >-
            Requested checkout mode. Built-in automatic pool hits report
            `prefer`.
    ErrorDetail:
      oneOf:
        - $ref: '#/components/schemas/TemplateFailureDetail'
        - $ref: '#/components/schemas/UploadFailureDetail'
    DesktopResolution:
      type: object
      required:
        - width
        - height
      properties:
        width:
          type: integer
          minimum: 1
        height:
          type: integer
          minimum: 1
    NetworkEgressPolicy:
      type: object
      required:
        - mode
      description: >-
        Typed per-machine egress policy. IPv4 only; no domain/DNS filtering.
        `deny_all` is fail-closed and cannot be weakened by other fields.
      properties:
        mode:
          type: string
          enum:
            - allow_all
            - deny_all
            - custom
          description: >-
            `allow_all` permits all outbound traffic; `deny_all` blocks all
            outbound traffic; `custom` applies the CIDR lists and optional rate
            limit below.
        allow_cidrs:
          type: array
          description: >-
            IPv4 CIDRs allowed outbound (custom mode only). A non-empty list
            makes the policy an allowlist.
          items:
            type: string
        deny_cidrs:
          type: array
          description: IPv4 CIDRs denied outbound (custom mode only).
          items:
            type: string
        rate_limit:
          allOf:
            - $ref: '#/components/schemas/EgressRateLimit'
          description: >-
            Optional best-effort outbound rate limit (custom mode only).
            Best-effort shaping, not a billing/quota boundary.
    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.
    EgressRateLimit:
      type: object
      description: >-
        Best-effort outbound rate limit. Set exactly one of `kbit_per_sec` or
        `pps`.
      properties:
        kbit_per_sec:
          type: integer
          format: int64
          minimum: 1
          description: Throughput ceiling in kilobits per second.
        pps:
          type: integer
          format: int64
          minimum: 1
          description: Packet-per-second ceiling (alternative to `kbit_per_sec`).
        burst:
          type: integer
          format: int64
          minimum: 1
          description: Burst allowance. Kilobytes for `kbit_per_sec`, packets for `pps`.
    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:
    InvalidRequest:
      description: Invalid request parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    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
    QuotaExceeded:
      description: >-
        Account quota, host capacity, or rate limit was exceeded. Capacity
        responses use `capacity_exceeded` and include `Retry-After`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            capacityExceeded:
              summary: Host capacity temporarily exhausted
              value:
                error: Host capacity exceeded
                code: capacity_exceeded
                request_id: req_123
            dailyCreates:
              summary: Daily machine create quota exceeded
              value:
                error: >-
                  Daily machine create quota exceeded (100/100 for 2026-05-02).
                  See https://docs.nullspace.io/account#quotas.
                code: QUOTA_EXCEEDED
                request_id: req_123
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key passed as Bearer token

````