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

# Create a sandbox

> Creates a sandbox from a `template_id`.

Compute resources (CPU / memory / disk / architecture) are inherited from the snapshot of the selected Template Build. They are fixed when the Template is built and cannot be overridden at creation time.

Idempotency: pass an explicit `Idempotency-Key` request header as the idempotency key (unrelated to the tracing header `X-Request-ID`, which is always generated server-side; a client-supplied value is ignored). Resubmitting the same key with identical parameters returns the sandbox created by the first request (with its current access data) plus an `Idempotency-Replayed: true` response header. The same key with different parameters returns 400 `Sandbox.IdempotentParameterMismatch`. If the creation under that key has deterministically failed, or the sandbox it created has been deleted, the request returns 409 `Sandbox.IdempotentKeyConsumed` (retryable failures are automatically re-attempted when the same key is retried). The deduplication window is 24 hours; after it expires the same key is treated as a new request. Without the header, no deduplication is performed.

Backends that create asynchronously return as soon as the request is accepted: the instance starts in `provisioning` and transitions to `running` once ready. The detail endpoint is queryable during this period (see GET /sandboxes/{id}).

**The `sandbox_access_token` stays valid for the entire lifetime of the sandbox.**




## OpenAPI

````yaml /api-spec/sandbox_api.yaml post /sandboxes
openapi: 3.0.3
info:
  title: GMI Sandbox API
  description: >-
    REST API for GMI Sandbox: create isolated execution environments from
    templates, manage their lifecycle on the control plane, and run commands or
    transfer files through each sandbox's own data plane.
  contact:
    name: GMI Cloud Support
    email: support@gmicloud.ai
  version: '2.0'
servers:
  - url: https://console.gmicloud.ai/api/v2
    description: Control plane
security:
  - bearerAuth: []
tags:
  - name: Sandbox
    description: |
      Sandbox instance lifecycle management (Sandbox v2, /api/v2/sandboxes)
  - name: SandboxTemplate
    description: Sandbox template management (Sandbox v2, `/api/v2/templates`)
  - name: Sandbox-Exec
    description: >
      Sandbox execution data plane (accessed via the sandbox host and sandbox
      access token). These endpoints are not under the control plane's `/api/v2`
      path; clients connect directly to `https://{sandbox_key}.{domain}` and
      authenticate with `X-Access-Token`.
  - name: Sandbox-Files
    description: >
      Sandbox file data plane (`/files`). **These endpoints are not under
      `/api/v2`** and do not use `Authorization: Bearer`: they are served by the
      sandbox's own data-plane entry point — clients connect directly to
      `https://{sandbox_key}.{domain}` and authenticate with `X-Access-Token`.
      `{sandbox_key}` is the `sandbox_key` returned by the create/connect
      endpoints, used for data-plane host addressing. `{domain}` and
      `X-Access-Token` are the `domain` and `sandbox_access_token` from the same
      responses — no extra endpoint is needed to obtain them.


      This split is not historical baggage but the nature of a data plane: file
      transfer is long-lived, high-volume, and addressed per sandbox, differing
      from the control plane's short requests in both capacity model and failure
      domain, so they do not share an entry point.


      **One unified abstraction.** The same contract is served by two backend
      kinds (an in-sandbox file service / a data-center data-plane proxy);
      clients need not — and cannot — tell them apart. The cost is that the
      contract is their intersection: `Content-Length` on download and resumable
      download (`Range`/`206`) are **optional capabilities** that vary by data
      center, and clients must work correctly when they are absent. See the
      per-operation notes below.
paths:
  /sandboxes:
    post:
      tags:
        - Sandbox
      summary: Create a sandbox
      description: >
        Creates a sandbox from a `template_id`.


        Compute resources (CPU / memory / disk / architecture) are inherited
        from the snapshot of the selected Template Build. They are fixed when
        the Template is built and cannot be overridden at creation time.


        Idempotency: pass an explicit `Idempotency-Key` request header as the
        idempotency key (unrelated to the tracing header `X-Request-ID`, which
        is always generated server-side; a client-supplied value is ignored).
        Resubmitting the same key with identical parameters returns the sandbox
        created by the first request (with its current access data) plus an
        `Idempotency-Replayed: true` response header. The same key with
        different parameters returns 400 `Sandbox.IdempotentParameterMismatch`.
        If the creation under that key has deterministically failed, or the
        sandbox it created has been deleted, the request returns 409
        `Sandbox.IdempotentKeyConsumed` (retryable failures are automatically
        re-attempted when the same key is retried). The deduplication window is
        24 hours; after it expires the same key is treated as a new request.
        Without the header, no deduplication is performed.


        Backends that create asynchronously return as soon as the request is
        accepted: the instance starts in `provisioning` and transitions to
        `running` once ready. The detail endpoint is queryable during this
        period (see GET /sandboxes/{id}).


        **The `sandbox_access_token` stays valid for the entire lifetime of the
        sandbox.**
      operationId: createSandbox
      parameters:
        - $ref: '#/components/parameters/IdempotencyKeyOptionalParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSandboxControlRequest'
      responses:
        '201':
          description: Sandbox created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateSandboxControlResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/QuotaExceeded'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  parameters:
    IdempotencyKeyOptionalParam:
      name: Idempotency-Key
      in: header
      required: false
      description: |
        Optional caller-generated idempotency key (a UUID is recommended).
        Matched byte-for-byte: 1-64 printable ASCII characters, no whitespace.
        Absent means no deduplication. The same key with a different request
        body returns 400 Sandbox.IdempotentParameterMismatch. Echoed on
        responses; replays add Idempotency-Replayed: true. Keys are remembered
        for 24 hours.
      schema:
        type: string
        minLength: 1
        maxLength: 64
  schemas:
    CreateSandboxControlRequest:
      type: object
      required:
        - template_id
      properties:
        template_id:
          type: string
          description: >-
            Template identifier or name. A snapshot-as-template `snapshotID` is
            also valid here.
        idc_name:
          type: string
          description: >
            Target data center name, e.g. us-central1-c. Optional: when omitted,
            the organization's configured default data center is used
            (maintained by the platform administrator); if the organization has
            no default configured, the request returns 400. Note that Templates
            are bound to a data center: the effective data center (whether
            explicit or default) must match the one that owns the Template
            referenced by `template_id`, otherwise the request is treated as
            template-not-found.
        timeout:
          type: integer
          format: int64
          description: >-
            Time-to-live in seconds. When omitted or 0 or less, 300 seconds is
            used.
        env_vars:
          type: object
          additionalProperties:
            type: string
        metadata:
          type: object
          additionalProperties:
            type: string
          description: >-
            Customer-defined key/value pairs; the platform does not interpret
            them. The list endpoint can filter by them.
    CreateSandboxControlResponse:
      type: object
      required:
        - request_id
        - data
      properties:
        request_id:
          type: string
          description: Request tracing ID
        data:
          $ref: '#/components/schemas/CreateSandboxControlResult'
    CreateSandboxControlResult:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: >-
            Unique sandbox resource ID (UUID), used both in control-plane path
            parameters and as the billing resource_id.
        sandbox_key:
          type: string
          description: >
            Data-plane addressing key (an `i` followed by a 20-character random
            string). Used solely to assemble data-plane URLs:
            `https://{sandbox_key}.{domain}` and
            `https://{port}-{sandbox_key}.{domain}`. Control-plane endpoints
            always use `id` and do not accept this field.
        template_id:
          type: string
          description: Template ID
        domain:
          type: string
          description: >
            Sandbox data-plane domain. It is the host suffix for data-plane
            endpoints such as `/files` (`https://{sandbox_key}.{domain}`) and
            for port services (`https://{port}-{sandbox_key}.{domain}`).
        sandbox_access_token:
          type: string
          description: >
            Sandbox data-plane access token (always issued). Sent as the
            `X-Access-Token` header on `/files`, Sandbox-Exec, and other
            data-plane endpoints; the control plane (`/api/v2`) does not use it.


            The token returned by create stays valid for the entire lifetime of
            the sandbox. If the lifetime is later extended via connect or `POST
            .../timeout`, call the connect endpoint to obtain a new token.
        traffic_access_token:
          type: string
          description: >
            Traffic token for non-control ports (issued only when secure=true;
            sent as the traffic-access-token header). Empty when secure=false.
    ErrorResponse:
      type: object
      required:
        - code
        - message
        - request_id
      properties:
        code:
          type: string
          description: Machine-readable business error code
          example: Resource.QuotaExceeded
        message:
          type: string
          description: Human-readable error description
          example: The resource quota is not enough.
        request_id:
          type: string
          description: Tracing ID
          example: req-xxxx
        details:
          type: object
          description: Field-level error details
          additionalProperties: true
  responses:
    BadRequest:
      description: Invalid request parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: Parameter.Invalid
            message: Invalid request parameters
            request_id: req-xxxx
    Unauthorized:
      description: Unauthenticated
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: Auth.Unauthorized
            message: Authentication required
            request_id: req-xxxx
    Forbidden:
      description: The caller cannot access the organization-scoped resource.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: Resource.NotFound
            message: The requested resource was not found
            request_id: req-xxxx
    Conflict:
      description: State conflict
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: Resource.StateConflict
            message: Resource state conflict
            request_id: req-xxxx
    UnprocessableEntity:
      description: >-
        The request is valid, but the selected provider does not support the
        requested capability.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: Template.ProviderNotSupported
            message: The selected provider does not support this template operation
            request_id: req-xxxx
    QuotaExceeded:
      description: The configured or temporary resource quota would be exceeded.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: Internal.ServerError
            message: An internal server error occurred
            request_id: req-xxxx
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >
        API Key or Access Token, always sent as `Authorization: Bearer <token>`.
        The gateway recognizes the token type automatically.

````