---
title: "POST /v1/volumes — create a named volume (API key, org inferred from key)."
method: POST
path: "/v1/volumes"
tags: ["volumes"]
---

# POST /v1/volumes — create a named volume (API key, org inferred from key).

`POST /v1/volumes`

Create a named persistent volume with optional capacity and labels.

## Request body

- CreateVolumeRequest — POST /v1/orgs/{slug}/volumes
  - `capacity_gib` integer, nullable — Optional per-volume storage cap in GiB (#496). Omitted/`null` = no per-volume limit (the org's plan cap still governs). Must be `>= 1` and `<= the org's storage cap`.
  - `labels` object — User-defined labels (free-form string map). Omitted = none. Keys using a platform-reserved prefix are rejected.
  - `name` string, required — Volume name, unique within the org. Lowercase alphanumeric with single internal hyphens (e.g. `team-ml`). Creates a `managed` volume; the host disk is system-provisioned and has no name.
  - `storage` 'block' — How a volume is physically backed — distinct from [`VolumeKind`] (ownership). Every volume is `Block` today; the enum exists so future backings can be added (and reported to the SDK) without another schema change.

## Response `200`

Volume created

- VolumeResponse — Volume metadata returned in list/create responses. The GCS storage path is derived (not stored) and never exposed.
  - `capacity_bytes` integer, nullable — The volume's configured per-volume storage cap in bytes, or `null` when no cap is set (#496). Derived from the stored `capacity_gib` (the user's configured intent) — the effective ceiling is `min(this, org cap)`.
  - `created_at` string, date-time, required
  - `id` string, uuid, required
  - `kind` 'host' | 'managed', required — What kind of volume this is — its storage source / role. The host volume is the org's single shared "host disk"; managed volumes are user-created, named, platform-provisioned (JuiceFS over our object store). (A future `External` variant — bring-your-own S3/GCS — is intentionally out of scope for now.)
  - `labels` object, required — User-defined labels (empty object when none set).
  - `name` string, nullable — User-facing name. `null` for the host volume (it has no name; it's identified by `kind`).
  - `status` 'active' | 'deleting', required — Lifecycle status of a volume.
  - `storage` 'block', required — How a volume is physically backed — distinct from [`VolumeKind`] (ownership). Every volume is `Block` today; the enum exists so future backings can be added (and reported to the SDK) without another schema change.
  - `updated_at` string, date-time, required
  - `used_bytes` integer, nullable — Bytes currently used under this volume's subtree. `null` when usage is unavailable — the usage service is disabled or unreachable (list degrades gracefully rather than failing) — or on create/delete, which don't sample it.

## Other responses

- `400` — Invalid request
- `401` — Unauthorized
- `409` — Volume name already in use

---

[API](https://skmtc.dev/microsandbox/apis/microsandbox-api.md) · [All operations](https://skmtc.dev/microsandbox/apis/microsandbox-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/microsandbox/microsandbox-api/revisions/23f2a45cb09b/schema)
