---
title: "Update a Cube (toggle termination protection)"
method: PATCH
path: "/spaces/{spaceId}/cubes/{cubeId}"
tags: ["Cubes"]
---

# Update a Cube (toggle termination protection)

`PATCH /spaces/{spaceId}/cubes/{cubeId}`

## Request

- Base URL: `https://krova.cloud/api/v1`
- URL: `https://krova.cloud/api/v1/spaces/{spaceId}/cubes/{cubeId}`
- Auth: API key in header `X-API-KEY`

Idempotent. Termination protection is the only PATCHable field today: sending the value it already has returns the Cube unchanged and writes no audit row. Omitting it is a 400 rather than a no-op, so a typo in the field name cannot look like success. Rename and resize are not part of the public API.

## Path parameters

- `spaceId` string, required
- `cubeId` string, required

## Request body

- object
  - `terminationProtection` boolean, required: Turn protection on or off. Turning it on stamps `terminationProtectionChangedAt` and `terminationProtectionChangedBy`; turning it off clears both.

## Response `200`

The updated Cube

- object
  - `cube` Cube, required
    - `id` string, required
    - `name` string, required
    - `state` 'pending' | 'booting' | 'running' | 'stopped' | 'stopping' | 'resizing' | 'error' | 'deleted', required
    - `publicIpv4` string, nullable, required
    - `resources` object, required
      - `vcpu` integer, required
      - `ramGb` number, required
      - `diskGb` integer, required
    - `image` string, required
    - `sshUser` string, required
    - `costPerHour` number, required
    - `serverDomain` string, nullable: The hostname of the server currently hosting this Cube (e.g. `mango.krova.cloud`), shared by every Cube on that server. This is NOT the Cube's own SSH target — use `host` from GET .../ssh for that, which is the Cube's own stable hostname and survives migration to another server. Null when the Cube has no server assigned. Only present on the single-Cube GET; list and create responses omit it.
    - `terminationProtection` boolean, required: Per-cube opt-in flag. When true, customer-initiated destroy paths return 409 with `error.code = "termination_protected"`. Power-off, wake, restart, restore, network-reset, and snapshot ops are NOT termination and remain allowed. Default false.
    - `terminationProtectionChangedAt` string, date-time, nullable, required: ISO8601 timestamp of the most recent toggle of `terminationProtection`. Null when the flag has never been turned on.
    - `terminationProtectionChangedBy` string, nullable, required: Identifies the actor that last toggled the flag: `"user:<id>"` for a customer, `"admin:<id>"` for an operator, `"system:<job-name>"` for a worker-driven write. Null when the flag has never been turned on.
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required

## Other responses

- `400`: Bad request
- `404`: Resource not found
- `429`: Rate limit exceeded (10 mutations / 60s)

---

[API](https://skmtc.dev/krova/apis/krova-cloud-api.md) · [All operations](https://skmtc.dev/krova/apis/krova-cloud-api/llms.txt) · [OpenAPI document](https://skmtc.dev/krova/apis/krova-cloud-api/revisions/46bb68281ce1?raw)
