# instances (/docs/reference/api/instances)

> Instances are VMs in a VPS pool: hosted pools place them on a host through capacity, and provider pools create them through the pool's provider account. After `create`, every call only changes `desiredState`; the `vps.instances` reconciler converges the instance and publishes `instance.*` events as its `state` moves. Instances are also the sandbox primitive today. See [Instances](/docs/guides/vps/instances).



Instances are VMs in a VPS pool: hosted pools place them on a host through capacity, and provider pools create them through the pool's provider account. After `create`, every call only changes `desiredState`; the `vps.instances` reconciler converges the instance and publishes `instance.*` events as its `state` moves. Instances are also the sandbox primitive today. See [Instances](/docs/guides/vps/instances).

All 7 methods are served by this release.

| Method              | Kind     | Authorization                                       | Phase | Status     |
| ------------------- | -------- | --------------------------------------------------- | ----- | ---------- |
| [`create`](#create) | mutation | `compute:instances:create` @ `compute-instance`     | v0.3  | registered |
| [`list`](#list)     | read     | `compute:instances:read` @ `compute-tenant` + items | v0.3  | registered |
| [`get`](#get)       | read     | `compute:instances:read` @ `compute-instance`       | v0.3  | registered |
| [`start`](#start)   | mutation | `compute:instances:update` @ `compute-instance`     | v0.3  | registered |
| [`stop`](#stop)     | mutation | `compute:instances:update` @ `compute-instance`     | v0.3  | registered |
| [`resize`](#resize) | mutation | `compute:instances:update` @ `compute-instance`     | v0.3  | registered |
| [`delete`](#delete) | mutation | `compute:instances:delete` @ `compute-instance`     | v0.3  | registered |

## create [#create]

`POST /api/compute/instances/create`

Admits a VM from a pool, flavor and image after one IAM decision on the draft; returns the instance in `scheduling`, or in `provisioning` with a `nodeId` when a hosted pool placed it at once.

* **Idempotency.** `idempotencyKey` is required. The instance id derives from the tenant, the caller and the key: a retry of a finished request returns the same instance without a second decision, and a different request under the same key is `CONFLICT` with `details.instanceId`.

* **IAM.** `compute:instances:create` is decided on `compute-instance/` plus the draft id, whose attributes (`vcpu`, `memoryGiB`, `gpus`, `imageId`, `imageVerified`, `projectId`) policies can test. A refusal deletes the draft; a delegated session can get `CONFIRMATION_REQUIRED`.

* **Errors.** `NOT_FOUND` for a pool the tenant neither owns nor is offered, an archived pool, a missing or archived flavor, or an image a hosted pool cannot resolve. `INVALID_INPUT` for a pool that is not `vps-host` or `provider`. `QUOTA_EXCEEDED` when the shape does not fit the tenant's quota; `CAPACITY_UNAVAILABLE` when a hosted pool has no free IP address. `INVALID_STATE` for a provider pool without an account, `INVALID_CONFIG` for a hosted pool when `vps()` has no `images`.

* **Events.** `instance.created`, and `instance.scheduled` with the `nodeId` when a hosted instance is placed. When no host fits, the instance stays in `scheduling` with an `Unschedulable` condition and is retried every 30 seconds.

* **Kind:** mutation

* **Authorization:** `compute:instances:create` @ `compute-instance`

* **Module:** `vps`

* **Phase:** v0.3 (registered)

**Input**

| Field            | Type                        | Required | Constraints                                                             |
| ---------------- | --------------------------- | -------- | ----------------------------------------------------------------------- |
| `tenantId`       | string                      | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`              |
| `poolId`         | string                      | yes      | at most 57 characters; matches `^pool_[0-9a-hjkmnp-tv-z]{26,52}$`       |
| `projectId`      | string                      |          | at most 56 characters; matches `^prj_[0-9a-hjkmnp-tv-z]{26,52}$`        |
| `flavor`         | string                      | yes      | at most 63 characters; matches `^[a-z0-9][a-z0-9._-]{0,62}$`            |
| `imageId`        | string                      | yes      | at most 200 characters; matches `^[A-Za-z0-9][A-Za-z0-9._@:/-]{0,199}$` |
| `sshKeys`        | list of string              |          | 0-32 items; default `[]`                                                |
| `userData`       | string                      |          | at most 32768 characters                                                |
| `desiredState`   | one of `running`, `stopped` |          | default `"running"`                                                     |
| `idempotencyKey` | string                      | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`              |
| `wait`           | object                      |          |                                                                         |
| `wait.timeoutMs` | integer                     | yes      | 0-30000                                                                 |

## list [#list]

`POST /api/compute/instances/list`

Returns a page of the tenant's instances, newest first, with a `cursor` when more remain.

`scope` defaults to `mine`, the caller's own instances; `all` returns every instance of the tenant that the caller may read. `state` and `poolId` filter the list, and `limit` is 1 to 200 (default 50). Drafts are never listed.

* **Kind:** read
* **Authorization:** `compute:instances:read` @ `compute-tenant` + items
* **Module:** `vps`
* **Phase:** v0.3 (registered)

**Input**

| Field      | Type                                                                                                                                                        | Required | Constraints                                                       |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------- |
| `tenantId` | string                                                                                                                                                      | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`        |
| `scope`    | one of `mine`, `all`                                                                                                                                        |          | default `"mine"`                                                  |
| `state`    | one of `pending`, `scheduling`, `provisioning`, `starting`, `running`, `stopped`, `rebooting`, `resizing`, `deleting`, `deleted`, `error`, `lost`, `paused` |          |                                                                   |
| `poolId`   | string                                                                                                                                                      |          | at most 57 characters; matches `^pool_[0-9a-hjkmnp-tv-z]{26,52}$` |
| `limit`    | integer                                                                                                                                                     |          | 1-200                                                             |
| `cursor`   | string                                                                                                                                                      |          | at most 57 characters; matches `^inst_[0-9a-z]{26,52}$`           |

## get [#get]

`POST /api/compute/instances/get`

Returns one instance of the tenant, deleted instances included.

Drafts and instances of other tenants are `NOT_FOUND`.

* **Kind:** read
* **Authorization:** `compute:instances:read` @ `compute-instance`
* **Module:** `vps`
* **Phase:** v0.3 (registered)

**Input**

| Field        | Type   | Required | Constraints                                                       |
| ------------ | ------ | -------- | ----------------------------------------------------------------- |
| `tenantId`   | string | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`        |
| `instanceId` | string | yes      | at most 57 characters; matches `^inst_[0-9a-hjkmnp-tv-z]{26,52}$` |

## start [#start]

`POST /api/compute/instances/start`

Sets `desiredState` to `running` and wakes the reconciler; returns the instance before anything has changed on the host or provider.

An instance in `error` that has a host or a provider machine moves to `starting` and is tried again. An instance being deleted is `INVALID_STATE`. Publishes `instance.starting`.

* **Kind:** mutation
* **Authorization:** `compute:instances:update` @ `compute-instance`
* **Module:** `vps`
* **Phase:** v0.3 (registered)

**Input**

| Field        | Type   | Required | Constraints                                                       |
| ------------ | ------ | -------- | ----------------------------------------------------------------- |
| `tenantId`   | string | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`        |
| `instanceId` | string | yes      | at most 57 characters; matches `^inst_[0-9a-hjkmnp-tv-z]{26,52}$` |

## stop [#stop]

`POST /api/compute/instances/stop`

Sets `desiredState` to `stopped` and wakes the reconciler; returns the instance before anything has changed on the host or provider.

An instance being deleted is `INVALID_STATE`. Publishes `instance.stopping`.

* **Kind:** mutation
* **Authorization:** `compute:instances:update` @ `compute-instance`
* **Module:** `vps`
* **Phase:** v0.3 (registered)

**Input**

| Field        | Type   | Required | Constraints                                                       |
| ------------ | ------ | -------- | ----------------------------------------------------------------- |
| `tenantId`   | string | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`        |
| `instanceId` | string | yes      | at most 57 characters; matches `^inst_[0-9a-hjkmnp-tv-z]{26,52}$` |

## resize [#resize]

`POST /api/compute/instances/resize`

Moves a stopped hosted instance to another flavor of its pool, in place on the same host; returns the instance `stopped` with the new flavor.

Growth is charged to quota first and shrinkage refunded after; if the host lacks room the charge is undone and the call is `CAPACITY_UNAVAILABLE` with `details.resource`. Other errors: `UNSUPPORTED` for a provider instance or a flavor with a different GPU count, `INVALID_STATE` when the instance is not stopped (both `state` and `desiredState`) or holds no allocation, `NOT_FOUND` for a missing or archived flavor, `QUOTA_EXCEEDED` when the growth does not fit. Publishes `instance.resized`.

* **Kind:** mutation
* **Authorization:** `compute:instances:update` @ `compute-instance`
* **Module:** `vps`
* **Phase:** v0.3 (registered)

**Input**

| Field        | Type   | Required | Constraints                                                       |
| ------------ | ------ | -------- | ----------------------------------------------------------------- |
| `tenantId`   | string | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`        |
| `instanceId` | string | yes      | at most 57 characters; matches `^inst_[0-9a-hjkmnp-tv-z]{26,52}$` |
| `flavor`     | string | yes      | at most 63 characters; matches `^[a-z0-9][a-z0-9._-]{0,62}$`      |

## delete [#delete]

`POST /api/compute/instances/delete`

Sets `desiredState` to `deleted` and wakes the reconciler, which releases the allocation, IP lease and quota; returns the instance at once.

The call is idempotent: an instance already `deleted` is returned unchanged, and stays readable through `get`. Publishes `instance.deleting`; `instance.deleted` follows when everything is released.

* **Kind:** mutation
* **Authorization:** `compute:instances:delete` @ `compute-instance`
* **Module:** `vps`
* **Phase:** v0.3 (registered)

**Input**

| Field        | Type   | Required | Constraints                                                       |
| ------------ | ------ | -------- | ----------------------------------------------------------------- |
| `tenantId`   | string | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`        |
| `instanceId` | string | yes      | at most 57 characters; matches `^inst_[0-9a-hjkmnp-tv-z]{26,52}$` |
