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

# Create a volume

> Provisions a persistent volume synchronously. Volumes are backed by Brimble's
globally distributed S3-compatible object storage; when the response returns
the disk is allocated and ready to attach to a sandbox or project.

Names are unique per user. Region is permanently pinned at creation;
volumes can only attach to sandboxes / projects in the same region.

`type` declares the surface this volume is intended for and drives where
it shows up in attach pickers:
- `web`, project disk (default)
- `sandbox`, sandbox disk




## OpenAPI

````yaml POST /volumes
openapi: 3.0.3
info:
  title: Brimble Sandbox API
  description: >
    REST API for managing Brimble sandboxes, ephemeral compute environments with

    optional persistent storage. Covers lifecycle (create / pause / resume /
    destroy),

    egress policy, runtime operations (exec, runCode, file upload/download),

    observability (logs, stats), and snapshots.


    ## Conventions


    - **Response envelope:** non-`204` JSON responses use `{ "message": string,
    "data"?: <payload> }`.
      The schemas below describe the **`data`** payload only.
    - **Errors:** every non-2xx response uses `{ "message": string }`. The
    message is
      user-facing.
    - **Async transitions:** pause / resume / destroy return immediately;
      the status change is visible on the next `GET` or in the dashboard.
      **Create is synchronous** — `POST /sandboxes` blocks until `status` is `ready`.
    - **IDs:** every `id` is a 24-char hex string.
  version: 1.0.0
  contact:
    name: Brimble Engineering
    url: https://brimble.io
servers:
  - url: https://sandbox.brimble.io
    description: Production
security:
  - brimbleKey: []
tags:
  - name: Sandboxes
    description: Lifecycle and metadata
  - name: Runtime
    description: Exec, code, files
  - name: Observability
    description: Logs and stats
  - name: Snapshots
    description: Manual & automatic snapshots
  - name: Volumes
    description: >-
      Persistent disks, pre-provisioned independently of sandbox lifecycle, then
      attached to a sandbox or project
paths:
  /volumes:
    post:
      tags:
        - Volumes
      summary: Create a volume
      description: >
        Provisions a persistent volume synchronously. Volumes are backed by
        Brimble's

        globally distributed S3-compatible object storage; when the response
        returns

        the disk is allocated and ready to attach to a sandbox or project.


        Names are unique per user. Region is permanently pinned at creation;

        volumes can only attach to sandboxes / projects in the same region.


        `type` declares the surface this volume is intended for and drives where

        it shows up in attach pickers:

        - `web`, project disk (default)

        - `sandbox`, sandbox disk
      operationId: createVolume
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateVolumeInput'
      responses:
        '201':
          description: Volume created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VolumeEnvelope'
        '400':
          $ref: '#/components/responses/BadRequest'
        '403':
          $ref: '#/components/responses/Forbidden'
components:
  schemas:
    CreateVolumeInput:
      type: object
      required:
        - name
        - sizeGB
        - region
      properties:
        name:
          type: string
          pattern: ^[a-z0-9-]{1,40}$
          description: Lowercase letters, digits, hyphens; 1–40 chars. Unique per user.
        sizeGB:
          type: integer
          minimum: 10
          maximum: 50
          description: Disk size in GB. Subject to plan caps.
        region:
          type: string
          pattern: ^[a-f0-9]{24}$
          description: Region id from `GET /v1/regions`. Cannot be changed after creation.
        type:
          allOf:
            - $ref: '#/components/schemas/VolumeType'
          description: Defaults to `web` when omitted.
        teamId:
          type: string
          pattern: ^[a-f0-9]{24}$
          description: >-
            Create the volume under a team you're a member of. Copy the team ID
            from the team's settings page in the dashboard. Omit for a personal
            volume.
    VolumeEnvelope:
      type: object
      required:
        - message
        - data
      properties:
        message:
          type: string
          example: Volume fetched
        data:
          $ref: '#/components/schemas/Volume'
    VolumeType:
      type: string
      enum:
        - web
        - sandbox
      description: |
        Which surface a volume is intended for:
        - `web`, project disk (default)
        - `sandbox`, sandbox disk
    Volume:
      type: object
      required:
        - id
        - name
        - type
        - size
        - attached_sandbox_id
        - attached_project_id
      properties:
        id:
          type: string
        name:
          type: string
          description: Matches `^[a-z0-9-]{1,40}$`.
        type:
          $ref: '#/components/schemas/VolumeType'
        team:
          type: string
          nullable: true
          description: Team id if team-scoped.
        volume_handle:
          type: string
          nullable: true
          description: >-
            Storage-layer handle for the volume. Surfaced in advanced / debug
            views only.
        size:
          type: integer
          description: Disk size in GB (10–50).
        region:
          allOf:
            - $ref: '#/components/schemas/SandboxRegion'
          nullable: true
          description: |
            Populated server-side; the volume response carries the full region
            object inline, no separate `/v1/regions` lookup needed to render.
        mount_path:
          type: string
          nullable: true
          description: Where the volume mounts inside the attached sandbox or project.
        attached_sandbox_id:
          type: string
          nullable: true
          description: Non-null when the volume is currently attached to a sandbox.
        attached_project_id:
          type: string
          nullable: true
          description: Non-null when the volume is currently attached to a project.
        last_attached_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          type: string
          format: date-time
          nullable: true
        updated_at:
          type: string
          format: date-time
          nullable: true
    ErrorResponse:
      type: object
      required:
        - message
      properties:
        message:
          type: string
          description: Human-readable, user-facing error reason.
    SandboxRegion:
      type: object
      required:
        - id
        - name
        - country
        - continent
        - enabled
        - type
      properties:
        id:
          type: string
          example: 6a06df21cc6bef51342e199e
        name:
          type: string
          example: eu-west
        country:
          type: string
          example: France
        continent:
          type: string
          example: Europe
        enabled:
          type: boolean
          description: Whether the region is currently accepting new sandboxes.
        type:
          type: string
          enum:
            - sandbox
          description: Region kind. Sandbox endpoints only return sandbox-eligible regions.
  responses:
    BadRequest:
      description: Validation error / invalid state transition
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            invalidId:
              summary: Invalid sandbox id
              value:
                message: Invalid sandbox id
            statusTransition:
              summary: Wrong status
              value:
                message: Sandbox is paused; only ready sandboxes can be paused
            fileNotDir:
              summary: Parent dir missing on upload
              value:
                message: 'Destination directory does not exist: /work'
            duplicateVolumeName:
              summary: Duplicate volume name
              value:
                message: A volume named "node-cache" already exists
            volumeAttached:
              summary: Delete attempted on attached volume
              value:
                message: Volume is attached; detach it before deleting
    Forbidden:
      description: Plan / spending-limit / permission error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            planLimit:
              value:
                message: >-
                  Your plan allows up to 3 sandboxes. Destroy an existing one or
                  upgrade.
            spendingLimit:
              value:
                message: >-
                  Sandbox creation paused, spending limit reached. Raise the
                  limit or wait for the next billing cycle.
            writePerm:
              value:
                message: Permission denied writing to /etc/passwd
            volumeSizeCap:
              summary: Volume size exceeds plan cap
              value:
                message: Your plan allows volumes up to 20GB. Reduce size or upgrade.
            volumeCountCap:
              summary: Volume count exceeds plan cap
              value:
                message: >-
                  Your plan allows up to 2 volumes. Delete an existing one or
                  upgrade.
  securitySchemes:
    brimbleKey:
      type: apiKey
      in: header
      name: x-brimble-key
      description: |
        Your account-level Brimble API key. Find it in the dashboard under
        your profile drawer → **API key** (click the avatar in the sidebar).
        Available on paid plans only.

````