
## Unstick the channel

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

Forcibly frees the command execution channel on the server: releases the server-side operation lock and bounces the agent tunnel. The virtual machine is not rebooted.

This is the recovery path after the `409 EXEC_BUSY` refusal returned by [Run a command](/docs/infra/deploy/exec) and by a deploy. The normal order is to call [Release a stuck lock](/docs/infra/deploy/lock) first, and to unstick the channel only if `EXEC_BUSY` persists after that.

## Parameters

| Parameter | In | Type | Required | Default | Description |
|----------|---|-----|:-----:|-----------|----------|
| `id` | path | string (UUID) | yes | — | ID of a `STANDALONE` server. List: [`GET /v1/infra/servers`](/docs/infra/servers/list) |
| `force` | query | string | no | — | `true` or `1` — unstick the channel even while a genuine operation is running on the server: that operation is aborted. Without the parameter such a call is rejected with `409 OPERATION_IN_PROGRESS` and the operation continues |

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

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

### JavaScript — personal key

```javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/unstick`,
  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
)
const body = await res.json()
if (!body.success) {
  console.error(body.error.code, body.error.message)
} else if (!body.data.reconnected) {
  console.log('The agent is still reconnecting — retry your command in a few seconds')
}
```

### JavaScript — OAuth application

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

To unstick on top of a running operation, send the same request with `?force=true` in the query string.

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | `true` when the channel was freed |
| `data.backendLockReleased` | boolean | The server-side operation lock was released |
| `data.agentBounced` | boolean | The agent tunnel was bounced. `false` when there was nothing to bounce — the agent was not connected, or the server is asleep |
| `data.reconnected` | boolean | The agent was confirmed to have reconnected within the wait window. `false` means the wait window expired, not that the reconnect failed |

## Response example

```json
{
  "success": true,
  "data": {
    "backendLockReleased": true,
    "agentBounced": true,
    "reconnected": true
  }
}
```

## Error response example

404 — the server was not found:

```json
{
  "success": false,
  "error": {
    "code": "SERVER_NOT_FOUND",
    "message": "Server not found"
  }
}
```

## 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 |
| 403 | `INFRA_FORBIDDEN_FOR_COWORK_KEY` | The call was made with a Cowork/Code 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) |
| 404 | `SERVER_NOT_FOUND` | The server does not exist, was deleted, or belongs to a different API key. Being on the server's development team does not grant access to this operation — it requires the managing key regardless of your role. The same code arrives if the server record disappeared between the access check and the unsticking. |
| 409 | `OPERATION_IN_PROGRESS` | A genuine operation is running on the server — a deploy, a command, a firewall hardening or a mode switch. The channel is not stuck, so the call is rejected and the operation continues. The `message` field names the operation. Retry with `force=true` only if you are certain the channel really is hung |
| 409 | `CONFLICT` | An unstick is already in progress for this server — wait for it to finish and retry |
| 409 | `GALAXY_UNSTICK_UNSUPPORTED` | A server of kind `GALAXY` or `GALAXY_APP`: the command execution channel is shared by every application on the host, and bouncing it would abort the neighbours' commands. If the busy state persists, contact support: releasing a shared host is a platform-team action |
| 429 | `RATE_LIMITED` | The limit of 6 requests per minute per "API key + server" pair was exceeded |
| 502 | `GATEWAY_ERROR` | The server-side lock was released, but the agent tunnel could not be bounced — the Gateway is unreachable. Recovery is incomplete — retry the request |

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

## Known specifics

- **What happens to the stuck command.** Bouncing the tunnel makes the agent terminate the stuck command's process group and connect again. The application service is not restarted, the files on disk are untouched, and the agent is not reinstalled — unlike [Repair the tunnel](/docs/infra/lifecycle/repair), which reinstalls the agent outright.
- **Unsticking does not wake a sleeping server.** If the server is in `sleeping` status or waking is blocked for it, there is no tunnel and nothing to bounce: the platform releases the server-side lock and answers with success and `agentBounced: false`.
- **The reconnect wait window is short and does not change the outcome.** The platform watches the tunnel for a few seconds after the bounce and answers without waiting any longer. The agent reconnects on its own, so `reconnected: false` means "not seen yet" rather than "did not come back" — retry your command a few seconds later.

## See also

- [Run a command](/docs/infra/deploy/exec)
- [Release a stuck lock](/docs/infra/deploy/lock)
- [Repair the tunnel](/docs/infra/lifecycle/repair)
- [Full application deploy](/docs/infra/deploy/deploy)
