
## Reboot server

`POST /v1/infra/servers/:id/reboot`

Reboots a running server at the cloud provider. During the reboot the server moves to `provisioning`, the tunnel is briefly dropped — `blackholeStatus` becomes `DISCONNECTED` — and reconnects after the virtual machine starts. The operation is atomic: an internal database-level guard prevents races if several calls arrive at once. If the provider does not support reboot, it returns 501 and the status is rolled back to `running`.

## Parameters

| Parameter | In | Type | Required | Description |
|----------|---|-----|:-----:|----------|
| `id` | path | string (UUID) | yes | ID of a server in `running` status |

The request body is empty.

## Examples

### curl — personal key

```bash
curl -X POST -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/reboot
```

### curl — OAuth application

```bash
curl -X POST -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/reboot
```

### JavaScript — personal key

```javascript
await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/reboot`,
  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
)

// Poll readiness after the reboot
while (true) {
  await new Promise(r => setTimeout(r, 5000))
  const res = await fetch(
    `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}`,
    { headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
  )
  const { data } = await res.json()
  if (data.status === 'running' && data.blackholeStatus === 'CONNECTED') break
}
```

### JavaScript — OAuth application

```javascript
await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/reboot`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
    },
  }
)
```

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | `true`. The reboot command was sent to the provider |

## Response example

```json
{ "success": true }
```

## Error response example

422 — the server exists but is not in `running` status. The response carries the current state and the actions available now:

```json
{
  "success": false,
  "error": {
    "code": "SERVER_WRONG_STATE",
    "message": "Server is SLEEPING; /reboot requires RUNNING.",
    "userMessage": "Server is currently SLEEPING. Reboot only applies to a RUNNING server.",
    "currentState": { "status": "SLEEPING", "blackholeStatus": "DISCONNECTED", "hasExternalId": true },
    "availableActions": ["wake", "start", "repair", "delete"]
  }
}
```

409 — the server status changed during the operation (race):

```json
{
  "success": false,
  "error": {
    "code": "CONFLICT",
    "message": "Server state changed during operation"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not provided |
| 401 | `INVALID_API_KEY` | Invalid or expired API key |
| 402 | `ACCOUNT_FROZEN` | Vibecode balance is frozen. Top up and retry |
| 404 | `SERVER_NOT_FOUND` | No server with this `id` — deleted, or belonging to another API key |
| 409 | `CONFLICT` | State race — the server status changed during the operation. Retry the request after checking [`GET /v1/infra/servers/:id`](/docs/infra/servers/get) |
| 422 | `SERVER_WRONG_STATE` | The server exists but is not in `running` status. `error.currentState` carries the current state; `error.availableActions` lists what you can do now |
| 422 | `VM_MISSING` | The server record has no cloud VM (provisioning never finished or the VM was removed manually) — delete the server and create a new one |
| 429 | `RATE_LIMITED` | The platform's overall request limit was exceeded |
| 501 | `NOT_SUPPORTED` | The cloud provider does not support reboot. Use the sequence [`/stop`](./stop.md) → [`/start`](./start.md) |
| 502 | `PROVIDER_ERROR` | The cloud provider returned an error. The server status is automatically rolled back to `running` |

The full list of common API errors — [Errors](/docs/errors).

## Known specifics

- **Atomic transition `running → provisioning`.** The database is updated with a single `updateMany` conditioned on `status = 'RUNNING'`. If another `/reboot` or `/stop` arrives at the same moment, the second call gets 409 `CONFLICT`.
- **Automatic rollback on a provider error.** If `adapter.rebootServer()` throws an exception, the record is reverted to `running` status — so the client is not left with a "stuck" `provisioning`.
- **To restart only the application** (without rebooting the virtual machine) use [`POST /exec`](/docs/infra/deploy/exec) with the command `systemctl restart app` — it is dozens of times faster and does not break the tunnel.
- **After a reboot, wait for both fields.** For the server to be ready, you need both `status: "running"` and `blackholeStatus: "CONNECTED"` at the same time — the tunnel reconnects after the virtual machine starts.

## See also

- [Start server](./start.md) — `POST /v1/infra/servers/:id/start`.
- [Stop server](./stop.md) — `POST /v1/infra/servers/:id/stop`.
- [Repair tunnel](./repair.md) — if the tunnel does not recover after a reboot.
- [Run a command](/docs/infra/deploy/exec) — restart the application without rebooting the virtual machine.
