# Server access recovery

A server stays bound to its current managing key, so once that key expires or is revoked, another key does not see the server. Access is restored by changing the managing key in your Vibecode account, without recreating the server.

## What access loss looks like

Access loss shows up like this:

- `GET /v1/infra/servers` returns success and an empty `data` array, although servers exist on the Bitrix24 account.
- `GET /v1/infra/servers/:id` for a known identifier returns `404 NOT_FOUND`.
- `GET /v1/me` at the same time confirms the new key is valid: `accessMode` equals `READWRITE`, the `vibe:infra` scope is present.
- In your Vibecode account the server is visible in the Black Hole Servers section and keeps running.

Listing servers with a key that does not manage them:

```json
{
  "success": true,
  "data": []
}
```

A request to a specific server with the same key:

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

The reliable check is to compare your Vibecode account and the API: the server is visible in the Black Hole Servers section but does not come back from `GET /v1/infra/servers`. Your Vibecode account lists servers by owner, so it is the source of truth on whether the server exists.

The counters in `GET /v1/me` give an extra hint, but not proof. The `infra.limits.used` field counts the dedicated virtual machines (`STANDALONE`) of the current key, and `infra.limits.breakdown` counts the owner's servers across all their keys on the Bitrix24 account. A zero `used` with a non-zero `breakdown.total` does not by itself mean the current key manages nothing: `used` skips galaxies and Galaxy apps even when the current key is the one managing them. This is a reason to compare with your Vibecode account, nothing more:

```json
{
  "success": true,
  "data": {
    "infra": {
      "limits": {
        "max": 3,
        "used": 0,
        "breakdown": {
          "direct": 7,
          "agents": 0,
          "bots": 0,
          "total": 7
        }
      }
    }
  }
}
```

The hint has other caveats too. A server that lost its key entirely does not appear in `breakdown` — both counters stay at zero there, although the server runs and is visible in your Vibecode account. Conversely, `breakdown` also counts the virtual machines of agents and bots: they also give `used: 0` with a non-zero `total`, but they are managed in their own sections of your Vibecode account rather than through `/v1` — see [AI agents](/docs/agents). More details on galaxies — [Galaxy app](/docs/infra/galaxy). So the counters point to where to look, but the comparison with your Vibecode account is what settles it.

## Why the server is not visible

A server has two different bindings. Ownership is tied to a user and is not affected by operations on keys. The `apiKeyId` field means something else — which key manages the server right now.

The `/v1/infra/*` endpoints authorize access by the managing key: a request sees only the servers whose `apiKeyId` matches the calling key. Your Vibecode account relies on ownership, so the server stays visible there. Hence the discrepancy: the server is in your Vibecode account, but the API does not return it for the new key.

Server data is not affected when a key expires. The virtual machine, the deployed application, the settings and the subdomain keep working — only management through the API is unavailable.

## How to restore access

The managing key is changed in your Vibecode account by the server owner:

1. Open the [Black Hole Servers](/black-hole) section.
2. Find the server in the list.
3. In the server card menu select **Change managing key**.
4. Select a new key from the list and confirm.

If the server has no managing key, its card shows a **Restore access** button that opens the same selection. When the card shows **Ownership lost**, first click **Reclaim** — this returns the server to your ownership, after which the key selection appears. Only a Bitrix24 account administrator sees ownerless servers and can reclaim them: for everyone else `POST /api/servers/:id/adopt` returns `403 ADMIN_ONLY`, and the card is not shown to them.

The change affects only the managing binding. The virtual machine, the data, the settings and the subdomain stay untouched, no restart is performed. After confirmation the new key immediately sees the server in `GET /v1/infra/servers` — provided its validity period has not ended. The set of available operations depends on the resource type: a dedicated virtual machine (`STANDALONE`) allows both lifecycle and deployment, while a Galaxy app (`GALAXY_APP`) allows deployment and deletion, because it has no virtual machine of its own and there is nothing to wake or reboot. The server owner receives a message from the companion bot that the managing key has been changed.

## Requirements for the new key

The selection list shows only eligible keys. A key is eligible when all conditions are met:

| Condition | Value |
|---------|----------|
| Type | API key (`vibe_api_`). An authorization key (`vibe_app_`) is not accepted as a managing key |
| Purpose | A general-purpose key. Temporary maintenance keys and Cowork keys issued by the platform are not accepted |
| Owner | The same user who owns the server |
| Account | The same Bitrix24 account as the server |
| State | Revoked and blocked keys are not shown in the list |
| Scope | `vibe:infra` |
| Not the current one | A key that already manages this server is not shown in the list |

Select a key that has not expired. An expired key stays in the list and rebinding to it succeeds — but requests with it are rejected with the `401 KEY_EXPIRED` code, and access to the server will have to be restored again. Each key's expiration date is shown in the [API Keys](/keys) section.

If there are no eligible keys, create a new one in the [API Keys](/keys) section with the `vibe:infra` scope — the form lets you do this without leaving the key change dialog.

## When this is needed

The situations lead to the same visible outcome — the server runs, and the new key does not see it. But there are three states behind it, and the procedure differs.

**The managing key is in place but does not work.** The server binding is intact, the key itself became unusable:

1. **The key secret is lost.** The key is valid, but its value was not saved at creation. A key value is shown once and cannot be recovered.
2. **The key is revoked.** The key was moved to the `REVOKED` state — by the owner, for example after a compromise, or by the platform when a self-hosted Bitrix24 account is disconnected: disconnection revokes the user's keys and does not touch the server binding.
3. **The key expired.** The validity period ended, and requests are rejected with the `401 KEY_EXPIRED` code.

In all three cases the procedure is the usual one — change the managing key to a new one.

**The server is left without a managing key.** The `apiKeyId` field is empty, the owner is kept. The card shows a **Restore access** button that opens the same key selection. A key with running servers cannot be deleted manually — the deletion check forbids it.

**The server is left without an owner as well.** Both fields are empty. This happens after the owner's account is deleted: their keys are deleted along with it, and `userId` and `apiKeyId` are nulled at the same time. The card shows **Ownership lost** — first click **Reclaim**, and only then the key selection appears. Only a Bitrix24 account administrator sees such servers.

Reclaiming ownership works for dedicated virtual machines (`STANDALONE`). A Galaxy app left without an owner cannot be reclaimed — the platform marks it deleted. While the app still has an owner, its managing key is changed the usual way.

## Errors

| HTTP | Code | When returned |
|------|-----|---------------------|
| 401 | `KEY_EXPIRED` | The key's validity period has ended |
| 401 | `KEY_INACTIVE` | The key is revoked or blocked |
| 404 | `NOT_FOUND` | A request to a server with a key that does not manage it |
| 403 | `WRONG_KEY` | Deployment to a server with a key that does not manage it |
| 409 | `KEY_HAS_ACTIVE_SERVERS` | Deleting a key that has active servers |
| 409 | `KEY_HAS_LINKED_AGENT` | Deleting a key that manages an agent or a bot |
| 409 | `APP_HAS_ACTIVE_SERVERS` | Deleting an application whose key has active servers |
| 409 | `CONCURRENT_REBIND` | A simultaneous change to different keys — the server is already bound to another key |

The full code reference is [Error codes](/docs/errors).

## Known specifics

**Deleting a key with active servers fails.** The request returns `409 KEY_HAS_ACTIVE_SERVERS`. Change the managing key of those servers — deleting the servers themselves is not needed for that. The full number of servers comes in `details.activeServerCount` when deleting from your Vibecode account and in `error.details.activeServerCount` for `DELETE /v1/keys/:id`. The list sits next to the counter — in `details.servers` and `error.details.servers` respectively. The list holds at most 10 servers — the newest ones. When the counter is above ten, rely on it and look at the remaining servers in your Vibecode account. If the key also has an agent or a bot, the next attempt returns `409 KEY_HAS_LINKED_AGENT` — rebinding the servers does not clear that check.

**The key change is available only in your Vibecode account.** The operation has no `/v1` equivalent: rebinding a running server is a human decision, not one for an automated client. A `vibe_api_` key does not perform this call.

**Deployment with a key that does not manage the server returns `403 WRONG_KEY`.** The response comes when the server exists but is managed by another key. The `hint` field explains the situation and points to changing the managing key as the way to recover.

**A server created by an application is no longer available to the application after the key change.** If a server was created by an authorization key, management can only be moved to the owner's personal API key — another authorization key cannot accept the binding. After that `GET /v1/infra/servers/:id` with the old key returns `404 NOT_FOUND`, while `POST /v1/infra/servers/:id/deploy` returns `403 WRONG_KEY`. The server can be managed through `/v1` only with the new personal key.

**The procedure applies to servers and Galaxy apps.** The Black Hole Servers section shows dedicated virtual machines (`STANDALONE`) and Galaxy apps (`GALAXY_APP`). A galaxy host (`GALAXY`) lives in the Galaxies section, and there is no managing-key change there — in `GET /v1/infra/servers` it is returned along with the rest, so an empty response of a new key does not tell it apart.

**A simultaneous key change from two devices is resolved by the target key.** When both requests picked the same key, the second request returns `200` — the binding is already what it asked for. When the requests picked different keys, the second one returns `409 CONCURRENT_REBIND`: refresh the page and check the current binding.

## See also

- [Server list](/docs/infra/servers/list)
- [Infrastructure](/docs/infra)
- [Creating and using a key](/docs/keys-auth)
- [Error codes](/docs/errors)
