## GET /api/v2/vps/{id}/storage

**Get VPS storage state**

Return VPS disks, filesystem usage, block IO counters, guest-agent availability, and disk action gates. Get `{id}` from `GET /api/v2/vps`. Use this endpoint when an agent needs to explain disk usage or whether a disk can be detached, resized, or expanded.

### Related Endpoints

- `GET /api/v2/vps/{id}`: Get VPS details
- `GET /api/v2/vps/{id}/iso`: List VPS ISO media
- `GET /api/v2/vps/{id}/disks`: List VPS disks

### Headers

- `Accept`: application/json
- `Authorization`: Bearer YOUR_API_KEY
- Required API scope: `read:vm`

### Parameters

- `id` (path, string, required): Public VPS ID from `GET /api/v2/vps` `data[].id`. Do not invent this value; use the exact ID returned by the referenced API response. Example: `vps_01hxa3b4c5d6e7f8g9h0j1k2m3`

### Request Example

```bash
curl -X GET "https://cloud.hostup.se/api/v2/vps/vps_01hxa3b4c5d6e7f8g9h0j1k2m3/storage" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
```

### Response Schema

- `disks` (array<object>, required)
- `disks[].id` (string,null, required) Example: `vpsdisk_01hxa3b4c5d6e7f8g9h0j1k2m3`
- `disks[].name` (string,null, required) Example: `scsi0`
- `disks[].type` (string,null, required) Example: `SCSI`
- `disks[].device` (string,null, required) Example: `/dev/scsi0`
- `disks[].isCdrom` (boolean, required) Example: `false`
- `disks[].bootOrder` (number,null, required) Example: `1`
- `disks[].capacity` (object, required)
- `disks[].capacity.totalGb` (number, required) Example: `80`
- `disks[].capacity.usedGb` (number, required) Example: `24.2`
- `disks[].capacity.freeGb` (number, required) Example: `55.8`
- `disks[].capacity.usagePercent` (number, required) Example: `30.25`
- `disks[].io` (object, required)
- `disks[].io.readGb` (number, required) Example: `120.5`
- `disks[].io.writeGb` (number, required) Example: `64.2`
- `disks[].io.readOperations` (number, required) Example: `102400`
- `disks[].io.writeOperations` (number, required) Example: `51200`
- `disks[].actions` (object, required)
- `disks[].actions.canDetach` (object, required)
- `disks[].actions.canDetach.allowed` (boolean, required) Example: `true`
- `disks[].actions.canDetach.reason` (string,null, required) Example: `null`
- `disks[].actions.canDetach.code` (string,null, optional): Machine-readable reason code when an action is blocked. Example: `pending_order`
- `disks[].actions.canResize` (object, optional)
- `disks[].actions.canResize.allowed` (boolean, required) Example: `true`
- `disks[].actions.canResize.reason` (string,null, required) Example: `null`
- `disks[].actions.canResize.code` (string,null, optional): Machine-readable reason code when an action is blocked. Example: `pending_order`
- `disks[].actions.canExpand` (object, optional)
- `disks[].actions.canExpand.allowed` (boolean, required) Example: `true`
- `disks[].actions.canExpand.reason` (string,null, required) Example: `null`
- `disks[].actions.canExpand.code` (string,null, optional): Machine-readable reason code when an action is blocked. Example: `pending_order`
- `filesystems` (array<object>, required)
- `filesystems[].mountpoint` (string,null, required) Example: `/`
- `filesystems[].type` (string,null, required) Example: `ext4`
- `filesystems[].name` (string,null, required) Example: `rootfs`
- `filesystems[].devices` (array<string>, required) Example: `["/dev/sda1"]`
- `filesystems[].capacity` (object, required)
- `filesystems[].capacity.totalGb` (number, required) Example: `78`
- `filesystems[].capacity.usedGb` (number, required) Example: `24.2`
- `filesystems[].capacity.freeGb` (number, required) Example: `53.8`
- `filesystems[].capacity.usagePercent` (number, required) Example: `31.03`
- `blockStats` (object, required)
- `blockStats.totalReadGb` (number, required) Example: `120.5`
- `blockStats.totalWriteGb` (number, required) Example: `64.2`
- `guestAgentAvailable` (boolean, required) Example: `true`
- `vmNotRunning` (boolean, required) Example: `false`

### Responses

#### 200 - VPS storage state.
```json
{
  "disks": [
    {
      "id": "vpsdisk_01hxa3b4c5d6e7f8g9h0j1k2m3",
      "name": "scsi0",
      "type": "SCSI",
      "device": "/dev/scsi0",
      "isCdrom": false,
      "bootOrder": 1,
      "capacity": {
        "totalGb": 80,
        "usedGb": 24.2,
        "freeGb": 55.8,
        "usagePercent": 30.25
      },
      "io": {
        "readGb": 120.5,
        "writeGb": 64.2,
        "readOperations": 102400,
        "writeOperations": 51200
      },
      "actions": {
        "canDetach": {
          "allowed": false,
          "reason": "Cannot detach root disk."
        },
        "canResize": {
          "allowed": false,
          "reason": "To expand your main disk, use Billing -> Add Resources."
        },
        "canExpand": {
          "allowed": false,
          "reason": "Guest agent is not installed. Install qemu-guest-agent on the VM to enable disk expansion."
        }
      }
    }
  ],
  "filesystems": [
    {
      "mountpoint": "/",
      "type": "ext4",
      "name": "rootfs",
      "devices": [
        "/dev/sda1"
      ],
      "capacity": {
        "totalGb": 78,
        "usedGb": 24.2,
        "freeGb": 53.8,
        "usagePercent": 31.03
      }
    }
  ],
  "blockStats": {
    "totalReadGb": 120.5,
    "totalWriteGb": 64.2
  },
  "guestAgentAvailable": true,
  "vmNotRunning": false
}
```

#### 400 - Invalid request. The response body is an RFC 7807 Problem Details document.
```json
{
  "type": "https://developer.hostup.se/errors/invalid_request",
  "title": "Invalid request",
  "status": 400,
  "detail": "The request body failed validation.",
  "code": "invalid_request",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z",
  "errors": [
    {
      "pointer": "/items/0/domainName",
      "detail": "`domainName` is required.",
      "code": "invalid_request"
    }
  ]
}
```

#### 401 - Unauthorized. Authentication is required.
```json
{
  "type": "https://developer.hostup.se/errors/unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Authentication is required.",
  "code": "unauthorized",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 403 - Forbidden. The caller lacks a required scope or does not own the resource.
```json
{
  "type": "https://developer.hostup.se/errors/forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "The caller lacks a required scope or does not own the resource.",
  "code": "forbidden",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 404 - Not found. The resource does not exist or is not owned by the caller.
```json
{
  "type": "https://developer.hostup.se/errors/not_found",
  "title": "Not found",
  "status": 404,
  "detail": "The requested resource could not be found.",
  "code": "not_found",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 429 - Rate limited. Retry after the limit resets. 429 responses include `Retry-After` seconds plus `X-RateLimit-*` headers.
```json
{
  "type": "https://developer.hostup.se/errors/rate_limit_exceeded",
  "title": "Too many requests",
  "status": 429,
  "detail": "Too many requests. Retry after the limit resets.",
  "code": "rate_limit_exceeded",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 500 - Internal error. Retry later or contact support if the issue persists.
```json
{
  "type": "https://developer.hostup.se/errors/internal_error",
  "title": "Internal server error",
  "status": 500,
  "detail": "An unexpected error occurred. Retry later or contact support if the issue persists.",
  "code": "internal_error",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```
