
## Start the server

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

Brings a server up from the `sleeping`, `error`, or `provisioning` states. For `sleeping`, the virtual machine is started again at the provider and returns to `running` status as it becomes ready — the call returns immediately, without waiting for actual readiness. Track readiness by polling [`GET /v1/infra/servers/:id`](/docs/infra/servers/get). For `error` with a connected tunnel (`blackholeStatus: "CONNECTED"`), the server is moved straight to `running` without contacting the provider. For `provisioning`, the start is retried without resetting the wait timer. If the server is not in one of these states — for example, already `running` — the call returns 422 `SERVER_WRONG_STATE` with the current state (`currentState`) and the list of available actions (`availableActions`).

## Parameters

| Parameter | In | Type | Required | Description |
|----------|---|-----|:-----:|----------|
| `id` | path | string (UUID) | yes | Server ID |

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/start
```

### 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/start
```

### JavaScript — personal key

```javascript
await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/start`,
  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
)
// Wait for readiness — poll GET /v1/infra/servers/:id
```

### JavaScript — OAuth application

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

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | `true`. The virtual machine has been started at the provider, or the start command has been dispatched in the background |

## Response example

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

## Error response example

422 — the server exists but is not in `sleeping`/`error`/`provisioning` status, for example already `running`. The response carries the current state and the actions available now:

```json
{
  "success": false,
  "error": {
    "code": "SERVER_WRONG_STATE",
    "message": "Server is RUNNING; /start requires one of SLEEPING, ERROR, PROVISIONING.",
    "userMessage": "Server is currently RUNNING. Start only applies to SLEEPING, ERROR, or PROVISIONING servers.",
    "currentState": { "status": "running", "blackholeStatus": "CONNECTED", "hasExternalId": true },
    "availableActions": ["reboot", "sleep-now", "delete"]
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not provided |
| 401 | `INVALID_API_KEY` | The key is not recognized — no such key exists on the platform |
| 402 | `ACCOUNT_FROZEN` | The Vibecode balance is frozen. Top up and retry |
| 402 | `INT_TARIFF_REQUIRED`, `INT_VIBE_PLUS_REQUIRED` | A Galaxy app: waking the galaxy host is stopped by the account access check, not by the balance state. `INT_TARIFF_REQUIRED` arrives when the Bitrix24 account is on a free plan. `INT_VIBE_PLUS_REQUIRED` arrives when access is narrowed to the Vibe+ plan line and the account is on an ordinary commercial plan. Code breakdown — [Errors](/docs/errors) |
| 403 | `VIBE_DEMO_EXPIRED` | The server is a Vibe+ trial machine and the trial has ended: the platform froze it at the scheduled access check and refuses to start it. The server and its data are kept; a paid Vibe+ plan on the Bitrix24 account restores access; the server is not started automatically — start it with a new call |
| 403 | `SERVER_WAKE_BLOCKED` | A Galaxy app: waking the galaxy host is blocked. A standalone virtual machine never returns this code, because `/start` clears the block itself |
| 403 | `INFRA_FORBIDDEN_FOR_COWORK_KEY` | The call was made with a Cowork key — such a key works with data only and cannot perform write operations. To issue a key that can, see [Project key for deploy](/docs/cowork/deploy-key) |
| 403 | `SERVER_ROLE_FORBIDDEN` | You are on this server's development team with the Developer role, and this operation is open to the Administrator role. `error.hint` carries your role, the required threshold and the list of calls that are open to you. Role breakdown — [List servers](/docs/infra/servers/list) |
| 403 | `WRONG_KEY` | A live server in your Bitrix24 account is proven to belong to the key owner or one of its live applications, but another key manages it. This diagnostic refusal does not authorize the start. Rebind the server through a human session, then retry with the new managing key |
| 404 | `SERVER_NOT_FOUND` | The server does not exist, was deleted, is in another Bitrix24 account, or no relationship to the key owner or its live application is proven |
| 404 | `GALAXY_HOST_NOT_FOUND` | A Galaxy app: the galaxy host it is placed on was not found |
| 409 | `CONFLICT` | The server status changed during the operation — retry the request |
| 409 | `CONFLICT` | A galaxy host: maintenance is already running on it. Wait for it to finish and retry the request |
| 409 | `MANAGED_SERVER_LIFECYCLE` | The server belongs to an AI agent or a bot. Its start is controlled from the agent or bot card, not by `/start` |
| 422 | `SERVER_WRONG_STATE` | The server exists but is not in `sleeping`/`error`/`provisioning` status. `error.currentState` carries the current state; `error.availableActions` lists what you can do now |
| 422 | `SERVER_WRONG_STATE` | A Galaxy app whose code has never been uploaded, or an app in `error` status: `/start` does not recover a failed build. `error.message` names the code-upload call that fixes this |
| 422 | `CREDENTIAL_MISSING` | A Galaxy app: the galaxy host has no cloud-provider access attached — contact support |
| 422 | `VM_MISSING` | The record has no `externalId` and the cloud review sees no machine under this server's cloud name — the virtual machine was not created or was deleted externally. Replace the server: delete it and create a new one. `error.hint` names the endpoint of each step only if that step is available to this request, and for an unavailable step it gives the reason for the refusal and what to change |
| 422 | `VM_POINTER_LOST` | The record has no `externalId`, but the cloud review does see a machine under this server's cloud name: the link is lost while the machine itself is most likely running and billed. Do NOT delete the server and create a new one — that would leave the machine running with no record at all. The server is not moved to `error`; contact support to have the link restored |
| 422 | `GUEST_NOT_BOOTING` | The machine's guest operating system does not boot — the state is terminal and starting it is pointless. The server has to be recreated, and `error.availableActions` keeps only `delete` |
| 422 | `AGENT_NEVER_CONNECTED` | The agent never came up on a newly created machine or on a galaxy host, so there is no tunnel. Starting it fixes nothing and erases the explanation, which is why it is refused. Repair fixes it — [`POST /repair`](./repair.md); `error.availableActions` carries `repair` and `delete` |
| 429 | `RATE_LIMITED` | The platform-wide request limit was exceeded |
| 502 | `PROVIDER_ERROR` | The cloud provider returned an error while starting the virtual machine |

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

## Known specifics

- **Blocking variant.** If the client needs the server fully ready before the next step, use [`POST /wake?wait=true`](./wake.md) instead of `/start`. It waits for `status: "running"` + `blackholeStatus: "CONNECTED"` for up to ~6.5 minutes.
- **Manual `/start` bypasses `preventWake`.** Unlike [automatic wake](./wake.md), which does not fire on every request to the subdomain, an explicit `POST /start` clears the `preventWake` flag and starts the server even if it was blocked. The one `preventWake` block it does not lift is the Vibe+ trial freeze: an expired trial machine answers 403 `VIBE_DEMO_EXPIRED` before anything is cleared. Billing locks (`ACCOUNT_FROZEN`) are cleared by a separate top-up, not via `/start`.
- **For a `running` server it returns 422 `SERVER_WRONG_STATE`.** The server is already running — there is no need to start it again. To reboot it, use [`POST /reboot`](./reboot.md).
- **The three `422` codes on this route mean different things.** `SERVER_WRONG_STATE` is a transient state and retrying makes sense. `GUEST_NOT_BOOTING` is terminal: handle it as "recreate the server", not as a temporary error, otherwise a scheduled start retries forever. `AGENT_NEVER_CONNECTED` is neither terminal nor transient: retrying the start will never help, but repair fixes it. A client that restarts failed servers on a schedule must tell the three apart — otherwise it waits in vain on the first, spins forever on the second, and erases its own diagnosis on the third.

## Galaxy apps (`kind=GALAXY_APP`)

`/start` on a sleeping Galaxy app brings it up through the host, the same way [`/wake`](./wake.md) does. One difference from a standalone virtual machine matters for the client: the host `preventWake` flag blocks `/start`, and here the call does **not** clear that block.

The full map of an app's lifecycle operations is on the [Galaxy app](/docs/infra/galaxy) page.

## See also

- [Galaxy app](/docs/infra/galaxy)
- [Stop the server](./stop.md)
- [Wake the server (with `?wait=true`)](./wake.md)
- [Sleep now](./sleep-now.md)
- [Refresh status](./refresh.md)
- [Get a server](/docs/infra/servers/get)
