> ## 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.

# Start an existing Build

> Starts a Build created by the split create flow (a `waiting` initial
Build). This is an action on an existing record — nothing new is
created — so success is a 202 acceptance; poll the Build for the
outcome. Starting a Build that is not in `waiting` state returns 400 `Parameter.Invalid`. Not
supported in every IDC; unsupported IDCs reject it with 422.




## OpenAPI

````yaml /api-spec/sandbox_api.yaml post /templates/{template_id}/builds/{id}
openapi: 3.0.3
info:
  title: GMI Sandbox API
  description: >-
    REST API for GMI Sandbox: create isolated execution environments from
    templates or durable snapshots, 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: SandboxSnapshot
    description: Durable sandbox snapshot management (Sandbox v2, `/api/v2/snapshots`)
  - 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-Shell
    description: >
      Sandbox interactive terminal (PTY) data plane. **These endpoints are not
      under `/api/v2`**: clients connect directly to
      `https://{sandbox_key}.{domain}` and authenticate with `X-Access-Token`.
      `{sandbox_key}`, `{domain}` and the `X-Access-Token` value are the
      `sandbox_key`, `domain` and `sandbox_access_token` returned by the
      control-plane create/connect endpoints; no extra endpoint is needed.


      Each sandbox has exactly **one logical shell session** and at most **one
      active WebSocket connection** at a time (a second concurrent attach is
      refused at handshake with `409`). Disconnecting does not destroy the shell
      — re-attaching resumes the same session; only `POST /shell/control` with
      `action=close` destroys it.
  - 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:
  /templates/{template_id}/builds/{id}:
    parameters:
      - $ref: '#/components/parameters/TemplateBuildTemplateIdPathParam'
      - $ref: '#/components/parameters/BuildIdPathParam'
    post:
      tags:
        - SandboxTemplate
      summary: Start an existing Build
      description: >
        Starts a Build created by the split create flow (a `waiting` initial

        Build). This is an action on an existing record — nothing new is

        created — so success is a 202 acceptance; poll the Build for the

        outcome. Starting a Build that is not in `waiting` state returns 400
        `Parameter.Invalid`. Not

        supported in every IDC; unsupported IDCs reject it with 422.
      operationId: startTemplateBuild
      parameters:
        - $ref: '#/components/parameters/IdcNameQueryParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BuildDefinition'
      responses:
        '202':
          description: The start instruction was accepted; the Build is now building.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TemplateBuildMutation'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: >
            State conflict (`Resource.StateConflict` or an operation-specific
            code), or the selected IDC is under maintenance
            (`IDC.UnderMaintenance`): write operations are rejected until the
            IDC is usable again. Read operations are unaffected.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          $ref: '#/components/responses/Unsupported'
        '499':
          $ref: '#/components/responses/RequestCanceled'
        '500':
          $ref: '#/components/responses/InternalError'
        '504':
          $ref: '#/components/responses/RequestTimeout'
components:
  parameters:
    TemplateBuildTemplateIdPathParam:
      name: template_id
      in: path
      required: true
      description: Owning GMI Template identifier.
      schema:
        type: string
        format: uuid
    BuildIdPathParam:
      name: id
      in: path
      required: true
      description: GMI Template Build identifier.
      schema:
        type: string
        format: uuid
    IdcNameQueryParam:
      name: idc_name
      in: query
      description: Filter by data center name, e.g. us-denver-1
      schema:
        type: string
  schemas:
    BuildDefinition:
      type: object
      additionalProperties: false
      required:
        - source
      properties:
        default_user:
          $ref: '#/components/schemas/TemplateDefaultUser'
        source:
          $ref: '#/components/schemas/BuildSource'
        commands:
          type: array
          maxItems: 100
          description: >
            Shell command strings executed sequentially during the Build. They
            may

            run as a non-root account with passwordless sudo: prefix privileged

            commands with `sudo`, and set ownership of files that the runtime

            account must use. To control the build identity explicitly, use a

            Dockerfile source with `USER` instructions, as in a regular
            Dockerfile.
          items:
            type: string
            minLength: 1
            maxLength: 8192
        envs:
          type: object
          maxProperties: 256
          additionalProperties:
            type: string
            maxLength: 32768
          description: >
            Environment variables available only during the Template Build.

            They are visible to subsequent build commands/steps and are not
            persisted

            into the resulting template artifact as sandbox runtime environment

            variables. Pass runtime env when creating a Sandbox instead.
            Write-only:

            values are never returned on Template or TemplateBuild responses.

            Keys must be unique (JSON object); the server orders them

            deterministically by key. Key names must match

            `[A-Za-z_][A-Za-z0-9_]*`.
        build_timeout_sec:
          type: integer
          minimum: 60
          maximum: 3600
          description: |
            Wall-clock budget for this Build in seconds. Omit or null to use the
            platform default (600). Allowed range: 60–3600. On expiry the Build
            is finalized as `error` with failure code `TemplateBuild.TimedOut`,
            its backing build in the selected IDC is cancelled, and its partial
            artifacts are reclaimed, best-effort.
        start_cmd:
          type: string
          minLength: 1
          maxLength: 8192
          description: >
            Launch command persisted with the Build and applied when Sandboxes

            created from this Template start.


            It runs as a boot script before the sandbox's main process, and the

            sandbox only becomes ready once it returns, so the command must

            terminate. A foreground long-running command (`sleep infinity`, a

            server started in the foreground) leaves the Sandbox stuck

            initializing and every exec against it rejected.


            Appending `&` alone is not sufficient: a backgrounded process that

            still holds the inherited stdout/stderr keeps boot blocked just the

            same. Long-running processes must be backgrounded *and* detached

            from those streams, e.g.

            `my-server > /var/log/my-server.log 2>&1 &`.


            Resume continues the saved processes without re-running this
            command.
        file_context:
          $ref: '#/components/schemas/TemplateFileContext'
    TemplateBuildMutation:
      type: object
      additionalProperties: false
      required:
        - request_id
        - data
      properties:
        request_id:
          type: string
          description: HTTP request correlation identifier.
        data:
          type: object
          additionalProperties: false
          required:
            - id
            - template_id
            - status
          properties:
            id:
              type: string
              description: The Build this mutation created or started.
            template_id:
              type: string
              description: Owning GMI Template identifier.
            status:
              $ref: '#/components/schemas/BuildStatus'
    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
        trace_id:
          type: string
          description: >-
            Server-side trace identifier for this request; quote it when
            reporting a problem.
        details:
          type: object
          description: Field-level error details
          additionalProperties: true
    TemplateDefaultUser:
      type: object
      additionalProperties: false
      required:
        - username
      description: >
        Runtime default identity for Sandboxes launched from this Build.

        Without it, Sandboxes run as `docker run` would: as the Dockerfile's
        final

        USER, else the image's USER, else root, in the final WORKDIR, else the

        image's, else `/`.

        Sandboxes run commands as a named account: an image USER given as a

        numeric uid (or uid:gid) needs a matching /etc/passwd entry in the
        image,

        otherwise the Build fails with a reason that names the USER. The group

        part is ignored.

        It is applied after all build commands and overrides the final
        Dockerfile

        USER at runtime; it does not change the identity of earlier build
        commands.


        Recommended setup for a custom account: create it in the Dockerfile,
        give

        it a working directory it can access, and pass its uid, for example

        `RUN useradd --uid 9999 --create-home --shell /bin/bash app`,

        `WORKDIR /home/app`, and `default_user: {username: app, uid: 9999}`.


        - default_user changes the identity only, not the working directory or
        its
          permissions. If the account cannot enter the final working directory,
          commands cannot start there and the Build may fail; declare an
          accessible WORKDIR to fix it.
        - With uid, the account must already exist with that UID and an existing
          home directory; otherwise the Build fails. The platform does not change
          UID, ownership, groups, or sudo privileges.
        - A non-root username without uid may be rejected with HTTP 422
          (Template.ProviderNotSupported); supply uid to avoid this. root may omit uid.
        - Invalid username, out-of-range uid, or root with a nonzero uid returns
          HTTP 400 (Parameter.Invalid).
        - A Build from a base template keeps the base template's user and
        working
          directory, as Docker FROM does; set default_user on the child Build to
          select another. Changing it requires a new Build.

        When omitted, the template's default runtime identity is used. A Build

        response reports the requested setting; an omitted uid stays omitted.
      properties:
        username:
          type: string
          minLength: 1
          maxLength: 32
          pattern: ^[a-z_][a-z0-9_-]{0,31}$
          example: app
        uid:
          type: integer
          format: int32
          minimum: 0
          maximum: 2147483647
          description: >-
            UID of the account. Recommended for non-root usernames. root only
            accepts 0.
          example: 9999
    BuildSource:
      oneOf:
        - $ref: '#/components/schemas/ImageSource'
        - $ref: '#/components/schemas/TemplateSource'
        - $ref: '#/components/schemas/DockerfileSource'
      discriminator:
        propertyName: type
        mapping:
          image: '#/components/schemas/ImageSource'
          template: '#/components/schemas/TemplateSource'
          dockerfile: '#/components/schemas/DockerfileSource'
      description: Manual Build source. Sandbox sources use the snapshot endpoint.
    TemplateFileContext:
      type: object
      additionalProperties: false
      required:
        - file_id
      properties:
        file_id:
          type: string
          format: uuid
          description: GMI file identifier returned by the upload initialization endpoint.
        destination:
          type: string
          minLength: 1
          maxLength: 4096
          pattern: ^/
          description: |
            Absolute destination copied from the archive root during the Build.
            Required for image/template sources; forbidden for a dockerfile
            source, whose `COPY {{file:...}} /dest` lines carry their own
            destinations.
    BuildStatus:
      type: string
      enum:
        - waiting
        - building
        - ready
        - error
      description: Normalized Template Build status.
    ImageSource:
      type: object
      additionalProperties: false
      required:
        - type
        - image
      properties:
        type:
          type: string
          enum:
            - image
        image:
          type: string
          minLength: 1
          description: |
            OCI container image reference. The following distributions have
            been validated: Debian/Ubuntu, Fedora/CentOS Stream/Rocky Linux/
            AlmaLinux, Arch Linux, and Alpine Linux.
        registry_credential:
          $ref: '#/components/schemas/GeneralRegistryCredential'
    TemplateSource:
      type: object
      additionalProperties: false
      required:
        - type
        - template_id
      properties:
        type:
          type: string
          enum:
            - template
        template_id:
          type: string
          description: Parent GMI Template identifier in the same IDC.
        build_id:
          type: string
          description: |
            Optional parent Build identifier. When omitted, the parent's
            current successful Build is used.
    DockerfileSource:
      type: object
      additionalProperties: false
      required:
        - type
        - dockerfile
      properties:
        type:
          type: string
          enum:
            - dockerfile
        dockerfile:
          type: string
          minLength: 1
          maxLength: 262144
          description: >
            Raw Dockerfile text. Supported instructions: FROM (exactly one; no

            multi-stage), RUN, ENV, WORKDIR, USER, COPY/ADD, CMD/ENTRYPOINT;

            EXPOSE and VOLUME are skipped; anything else is rejected with 400.


            A trailing backslash continues an instruction on the next line;
            blank

            and comment lines inside a continuation are skipped.


            The Dockerfile's final USER is the runtime identity of Sandboxes
            unless

            `default_user` is set. A Build fails when that account cannot enter
            the

            final working directory; declare an accessible WORKDIR.


            COPY/ADD sources must reference an uploaded Template file as

            `COPY {{file:<file_id>}} /dest` — local paths and URLs are

            rejected, and at most one file may be referenced per build (its

            `file_id` must also be attached via `file_context`, with

            `file_context.destination` omitted).


            With a dockerfile source, the sibling `commands` and `envs` fields

            are forbidden: write RUN/ENV lines in the Dockerfile instead.

            CMD/ENTRYPOINT are extracted into the Build's start command; an

            explicit `start_cmd` takes precedence over them.


            ENV values are visible to subsequent build steps and are part of

            the sandbox runtime environment, as under `docker run`; a value

            passed as `env_vars` when creating a Sandbox overrides one of the

            same name. Do not put build-time secrets in ENV: build the Template

            from an image or template source and pass them in `envs`, which

            reach the build steps only.
    GeneralRegistryCredential:
      type: object
      additionalProperties: false
      required:
        - type
        - username
        - password
      description: >-
        A one-time registry credential used to pull the private image named by
        `image`. `username` and `password` are used only for this build request:
        they are never persisted and never returned in any response. The Build
        detail's `registry_authentication` reports only whether a credential was
        used and of what kind, never the username or password.
      properties:
        type:
          type: string
          enum:
            - general
        username:
          type: string
        password:
          type: string
          description: Can be a password or an access token.
  responses:
    BadRequest:
      description: >-
        Invalid request parameters. Two code families are used:
        `Request.InvalidParameter` for request parsing and format validation
        (unknown or malformed body fields, malformed IDs, invalid enum values,
        out-of-range paging) and `Parameter.Invalid` for business validation
        (for example a template or IDC that cannot be found, or a `timeout` over
        the limit). Unknown or invalid fields inside the `params` of `POST
        /sandboxes/{id}/actions` are reported as `Parameter.Invalid`. Other 400
        codes are specific to an operation, for example `Sandbox.SourceConflict`
        (both or neither of `template_id` and `snapshot_id`) and
        `Sandbox.IdempotentParameterMismatch` (an `Idempotency-Key` reused with
        different parameters). Both code families share the same HTTP status, so
        decide by the `code` value, not the status alone.
      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
    Unsupported:
      description: |
        The request is valid but the selected IDC does not support
        the requested capability or resolved resource specification.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    RequestCanceled:
      description: The caller canceled the current HTTP request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: Request.Canceled
            message: Request canceled
            request_id: req-xxxx
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: System.Internal
            message: An internal server error occurred
            request_id: req-xxxx
    RequestTimeout:
      description: The current HTTP request exceeded the control-plane processing deadline.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: Request.Timeout
            message: Request timed out
            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.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.