# Capacity (operators) API

> For the people who run the service: the capacity loop's decisions, the budget guard, and the server purchases waiting for approval. These routes need the operator token.

- [List capacity decisions (operators)](#list-capacity-decisions-operators): `GET /v1/operator/capacity/decisions`
- [Read the capacity budget (operators)](#read-the-capacity-budget-operators): `GET /v1/operator/capacity/budget`
- [List purchases waiting for approval (operators)](#list-purchases-waiting-for-approval-operators): `GET /v1/operator/capacity/approvals`
- [Approve a server purchase (operators)](#approve-a-server-purchase-operators): `POST /v1/operator/capacity/approvals/{purchase_id}/approve`
- [Reject a server purchase (operators)](#reject-a-server-purchase-operators): `POST /v1/operator/capacity/approvals/{purchase_id}/reject`

## List capacity decisions (operators)

`GET /v1/operator/capacity/decisions`

The capacity loop's decisions, newest first.

- **Authentication:** none on this route.
- **Who:** Service operators (operator token).

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `limit` | query | `integer` | No | 1-200, default 50. |
| `before` | query | `integer` | No | Only decisions older than this ID. |
| `X-VMYard-Operator-Token` | header | `string` | Yes | Operator token from the service configuration |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| `200` | — | [`CapacityDecisionPage`](/docs/api/schemas#capacitydecisionpage) |
| `401` | Not signed in, or the API key is malformed, expired, or revoked (`unauthenticated`, `invalid_api_key`). | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `404` | operator routes are not configured | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `422` | Invalid request (`invalid_request`); `field_errors` names the fields. | [`ProblemDetails`](/docs/api/schemas#problemdetails) |

```sh title="Request"
curl "$VMYARD_API_URL/v1/operator/capacity/decisions" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN"
```

```json title="Response 200"
{
  "decisions": [
    {
      "action": "string",
      "at": "string",
      "dry_run": false,
      "facts": {},
      "id": 0,
      "outcome": "string",
      "reason": "string",
      "region": "string",
      "server_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f"
    }
  ],
  "next_before": 0
}
```

## Read the capacity budget (operators)

`GET /v1/operator/capacity/budget`

What the budget guard allows now.

- **Authentication:** none on this route.
- **Who:** Service operators (operator token).

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `X-VMYard-Operator-Token` | header | `string` | Yes | Operator token from the service configuration |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| `200` | — | [`CapacityBudgetDto`](/docs/api/schemas#capacitybudgetdto) |
| `401` | Not signed in, or the API key is malformed, expired, or revoked (`unauthenticated`, `invalid_api_key`). | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `404` | operator routes or the capacity loop are not configured | [`ProblemDetails`](/docs/api/schemas#problemdetails) |

```sh title="Request"
curl "$VMYARD_API_URL/v1/operator/capacity/budget" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN"
```

```json title="Response 200"
{
  "allowance_micros": 0,
  "approval_threshold_micros": 0,
  "ceiling_micros": 0,
  "committed_monthly_micros": 0,
  "launch_floor_micros": 0,
  "revenue_30d_micros": 0,
  "revenue_share_bps": 0,
  "spend_30d_micros": 0
}
```

## List purchases waiting for approval (operators)

`GET /v1/operator/capacity/approvals`

Purchases waiting for an operator's approval, oldest first.

- **Authentication:** none on this route.
- **Who:** Service operators (operator token).

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `X-VMYard-Operator-Token` | header | `string` | Yes | Operator token from the service configuration |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| `200` | — | [`CapacityApprovalList`](/docs/api/schemas#capacityapprovallist) |
| `401` | Not signed in, or the API key is malformed, expired, or revoked (`unauthenticated`, `invalid_api_key`). | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `404` | operator routes are not configured | [`ProblemDetails`](/docs/api/schemas#problemdetails) |

```sh title="Request"
curl "$VMYARD_API_URL/v1/operator/capacity/approvals" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN"
```

```json title="Response 200"
{
  "approvals": [
    {
      "billing": "string",
      "decided_by": "string",
      "host_id": "string",
      "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
      "monthly_cost_micros": 0,
      "note": "string",
      "provider": "github",
      "reason": "string",
      "region": "string",
      "requested_at": "string",
      "setup_cost_micros": 0,
      "slots": 0,
      "state": "string"
    }
  ]
}
```

## Approve a server purchase (operators)

`POST /v1/operator/capacity/approvals/{purchase_id}/approve`

Approve a waiting purchase; the capacity loop orders it on its next
pass if the budget rules still allow it.

- **Authentication:** none on this route.
- **Who:** Service operators (operator token).

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `purchase_id` | path | `string (uuid)` | Yes |  |
| `X-VMYard-Operator-Token` | header | `string` | Yes | Operator token from the service configuration |

**Request body** (`application/json`, [`CapacityApprovalRequest`](/docs/api/schemas#capacityapprovalrequest))

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `operator` | `string` | Yes | The operator deciding, recorded with the decision (1-100 characters). |
| `note` | `string \| null` | No | Optional note recorded with the decision (at most 500 characters). |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| `200` | — | [`CapacityPurchaseDto`](/docs/api/schemas#capacitypurchasedto) |
| `401` | Not signed in, or the API key is malformed, expired, or revoked (`unauthenticated`, `invalid_api_key`). | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `404` | operator routes are not configured or the purchase is unknown | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `409` | the purchase is no longer waiting for approval | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `422` | Invalid request (`invalid_request`); `field_errors` names the fields. | [`ProblemDetails`](/docs/api/schemas#problemdetails) |

```sh title="Request"
curl -X POST "$VMYARD_API_URL/v1/operator/capacity/approvals/$PURCHASE_ID/approve" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "operator": "string"
}'
```

```json title="Response 200"
{
  "billing": "string",
  "decided_by": "string",
  "host_id": "string",
  "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
  "monthly_cost_micros": 0,
  "note": "string",
  "provider": "github",
  "reason": "string",
  "region": "string",
  "requested_at": "string",
  "setup_cost_micros": 0,
  "slots": 0,
  "state": "string"
}
```

## Reject a server purchase (operators)

`POST /v1/operator/capacity/approvals/{purchase_id}/reject`

Reject a waiting purchase; nothing is bought.

- **Authentication:** none on this route.
- **Who:** Service operators (operator token).

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `purchase_id` | path | `string (uuid)` | Yes |  |
| `X-VMYard-Operator-Token` | header | `string` | Yes | Operator token from the service configuration |

**Request body** (`application/json`, [`CapacityApprovalRequest`](/docs/api/schemas#capacityapprovalrequest))

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `operator` | `string` | Yes | The operator deciding, recorded with the decision (1-100 characters). |
| `note` | `string \| null` | No | Optional note recorded with the decision (at most 500 characters). |

**Responses**

| Status | Description | Body |
| --- | --- | --- |
| `200` | — | [`CapacityPurchaseDto`](/docs/api/schemas#capacitypurchasedto) |
| `401` | Not signed in, or the API key is malformed, expired, or revoked (`unauthenticated`, `invalid_api_key`). | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `404` | operator routes are not configured or the purchase is unknown | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `409` | the purchase is no longer waiting for approval | [`ProblemDetails`](/docs/api/schemas#problemdetails) |
| `422` | Invalid request (`invalid_request`); `field_errors` names the fields. | [`ProblemDetails`](/docs/api/schemas#problemdetails) |

```sh title="Request"
curl -X POST "$VMYARD_API_URL/v1/operator/capacity/approvals/$PURCHASE_ID/reject" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "operator": "string"
}'
```

```json title="Response 200"
{
  "billing": "string",
  "decided_by": "string",
  "host_id": "string",
  "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
  "monthly_cost_micros": 0,
  "note": "string",
  "provider": "github",
  "reason": "string",
  "region": "string",
  "requested_at": "string",
  "setup_cost_micros": 0,
  "slots": 0,
  "state": "string"
}
```
