
## List servers

`GET /v1/infra/servers`

Returns three groups: servers managed by the current API key, galaxy hosts referenced by its Galaxy applications, and servers whose development team the key owner is on. A referenced host arrives only as a safe read-only row with `access.via: "galaxy-reference"`. Every row carries an `access` block explaining why it is visible. Deleted servers managed by the key (`status: "deleted"`) are not included by default — pass `?includeDeleted=true` to see them. The parameter does not return deleted hosts or references through deleted applications. Other servers are not visible, even within the same Bitrix24 account. To view every server in the account, use the administrator panel in the Vibecode dashboard.

## Query parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `includeDeleted` | string | No | Pass `true` to include deleted servers managed by the current key. Any other value, or omitting the parameter, keeps the default listing. The parameter does not affect `collaborator` or `galaxy-reference` rows |
| `page` | number | No | Page number, starting at 1. Applies only to servers whose development team you are a member of. Managed rows and referenced hosts arrive in full — see "Known specifics" |
| `limit` | number | No | Page size, 1..500, defaults to 50. Applied only when `page` and/or `limit` is passed, and limits only `collaborator` rows |

Why this exists: sources outlive their server. Once you delete a server, you can still list, untag, download or clean up its source versions — but for that you need its ID, and there is nowhere else to get it. The sources contract lives on the [Source storage](/docs/source-storage) page.

## Examples

### curl — personal key

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

### curl — OAuth application

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

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/infra/servers', {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})
const { data: servers } = await res.json()

servers.forEach(s => {
  if (s.access.via === 'galaxy-reference') {
    console.log(`${s.name}: shared host is read-only`)
    return
  }
  const ready = s.status === 'running' && s.blackholeStatus === 'CONNECTED'
  console.log(`${s.name}: ${ready ? '✓ ready' : s.status} — ${s.appUrl}`)
})
```

### JavaScript — OAuth application

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

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | Always `true` on success |
| `data` | array | Array of managed rows, unique `galaxy-reference` hosts and `collaborator` rows, in that order. The managed-row field set differs from the full [`GET /v1/infra/servers/:id`](./get.md) card: the card additionally contains `reachability`, `ssh.hasPassword` inside a non-null `ssh` block, `localPort`, `portPinned`, `buildLog`, and `buildHint`, while the list row adds `deletedAt` and `access: { via: "owner" }`. Neither GET returns `ssh.password` or `ssh.privateKey`. A team member's row is shorter. A referenced host row contains only `id`, `status`, `kind`, `galaxyId`, `name`, `displayName`, `createdAt` and `access`. Check that a field is present before reading it |
| `data[].id` | string (UUID) | Server ID |
| `data[].status` | string | Last stored status: `provisioning`, `running`, `stopped`, `sleeping`, `error`, `deleted`. Deleted managed servers (`deleted`) are not returned by default — see `includeDeleted` |
| `data[].deletedAt` | string \| null | Deletion date and time, ISO-8601. `null` for live servers |
| `data[].provider` | string | Provider ID |
| `data[].kind` | string | Resource type: `STANDALONE` (a dedicated virtual machine), `GALAXY` (a host carrying Galaxy applications) or `GALAXY_APP` (a Galaxy application on a shared host). Determines the deploy contract |
| `data[].galaxyId` | string (UUID) \| null | For `GALAXY_APP` — the ID of the host. `null` for other types |
| `data[].appCount` | number \| null | For a `GALAXY` host — the number of non-deleted applications on it. `null` for other types |
| `data[].diskTotalMb` | number \| null | Disk size of the galaxy host machine, in mebibytes. `null` for `STANDALONE` and `GALAXY_APP` |
| `data[].diskFreeMb` | number \| null | Free disk space on the galaxy host machine, in mebibytes. `null` for `STANDALONE` and `GALAXY_APP` |
| `data[].diskState` | string \| null | Disk usage verdict: `ok`, `warning`, `critical`, or `unknown` when nothing has been measured yet. Thresholds are described in [Galaxy app](/docs/infra/galaxy). `null` for `STANDALONE` and `GALAXY_APP` |
| `data[].diskProbedAt` | string (ISO 8601) \| null | Time of the disk measurement. A sleeping machine reports the last known value together with the time of that measurement |
| `data[].name` | string | System name of the server |
| `data[].displayName` | string \| null | Display name for the dashboard. Equals `name` if it was not provided |
| `data[].description` | string \| null | Application description shown on the Bitrix24 catalog card. `null` if no description was set. Changed via [`PATCH /v1/infra/servers/:id`](./update.md) |
| `data[].ip` | string \| null | Public IP (may be `null` while provisioning) |
| `data[].ssh` | object \| null | SSH data block: `{ user, port }`. The `hasPassword`, `password` and `privateKey` fields are not present in the list |
| `data[].plan` | string | Plan. **For a Galaxy application** (`kind: "GALAXY_APP"`) the host's plan is returned, not the one requested |
| `data[].region` | string | The actual region of the server — may differ from the requested one after a zone fallback. **For a Galaxy application** the host's region is returned |
| `data[].image` | string | OS image |
| `data[].monthlyCost` | string | Catalog monthly cost in Vibe credits (Ꝟ), as a string: `"24"` or `"24.00"`. The amount actually billed may differ. Compare via `Number(s.monthlyCost)` |
| `data[].mode` | string | `BLACKHOLE` or `OPEN` |
| `data[].createdVia` | string | `api` — a call through the Vibecode API, `ui` — an action in the Vibecode dashboard, `galaxy` — a Galaxy application. Servers of agents and bots carry their own values |
| `data[].subdomain` | string | Subdomain for the application |
| `data[].blackholeStatus` | string | Tunnel state: `NONE`, `CONNECTED`, `DISCONNECTED`. A stored `CONNECTED` may become `DISCONNECTED` in this response only, if a non-empty gateway snapshot does not contain the tunnel |
| `data[].accessPolicy` | string | Access policy: `OWNER_ONLY`, `NAMED_USERS`, `DEPARTMENT`, `PORTAL`, `AUTHENTICATED`, `PUBLIC` |
| `data[].runtimeId` | string \| null | ID of the runtime installed via `POST /:id/deploy` (always `null` at server creation). |
| `data[].runtimeStatus` | string \| null | A deprecated field, kept for compatibility. For servers created after 2026-04-25 it always returns `null`. The runtime is installed at the [`POST /:id/deploy`](/docs/infra/deploy/deploy) stage, and its readiness signal is the success of the `runtime` step in the deploy response, not this field's value |
| `data[].appUrl` | string \| null | HTTPS address of the application |
| `data[].sleepAfterMinutes` | number \| null | Number of idle minutes after which the server is automatically put to sleep. `null` — never auto-sleep |
| `data[].idleSleepProtected` | boolean | `true` when idle sleep is unavailable because the server must stay reachable. The field exposes only the decision and no bot or API-key metadata |
| `data[].runMode` | string | Run mode: `IDLE` — sleeps when idle, `SCHEDULE` — runs on a schedule, `ALWAYS` — around the clock. Derived from the assigned schedule, `idleSleepProtected`, `createdVia`, and `sleepAfterMinutes`. A protected server without a schedule is `ALWAYS` even when it stores a numeric threshold |
| `data[].workSchedule` | object \| null | The assigned schedule, or `null`. Fields: `id`, `name` (empty for a platform preset — identify it by `presetKey`), `presetKey`, `timezone`, `windows`. Every window is `{{ isoDay, start, end }}`, where `isoDay` is 1…7 counted from Monday and `start`/`end` are local HH:MM in the timezone of that schedule. Windows arrive as a LIST: one day may hold two of them — for instance, a shift with a break |
| `data[].provisionError` | string \| null | A short reason for the last creation or build failure. `null` if there were no errors |
| `data[].provisionErrorCode` | string \| null | Public failure category: `PROVISION_TIMEOUT` / `NO_CAPACITY` / `NETWORK_CAPACITY` / `OVERLOADED` / `TRANSPORT_UNAVAILABLE` / `CONFIG` / `INVALID_INPUT` / `GENERIC` / `BOX_UNREACHABLE` / `HOST_UNREACHABLE` / `WAKE_NO_CAPACITY` / `PREEMPTIBLE_EVICTION` / `AGENT_SERVER_GONE` / `AGENT_NEVER_CONNECTED` / `KEY_ISSUE_REFUSED` / `KEY_ISSUE_OUTCOME_UNKNOWN` / `KEY_ISSUE_RESPONSE_LOST` / `DISK_FULL` / `CREATION_HELD` / `KEY_ISSUE_MODULE_MISSING` / `GUEST_NOT_BOOTING`. A creation hold may instead return the stored hold reason, for example `BILLING_FROZEN` or `TRIAL_EXPIRED`. Internal and unknown codes are returned as `GENERIC` with a neutral `provisionError`: contact support before creating another server. `null` when no code is stored. `GUEST_NOT_BOOTING` is terminal; it and `DISK_FULL` are explained in "Known specifics" |
| `data[].provisionReason` | string \| null | Structured cause of a Galaxy application failure: `oom` — the container ran out of memory, or `crash`. `null` for regular servers and when there was no failure. `oom` is the signal to move the application to a dedicated server. The procedure is described in [Create a server](./create.md) |
| `data[].b24CatalogSync` | object | State of the app card in the Vibecode apps catalog on the Bitrix24 account: `{ status, itemId, attempts, pendingOp, eligible }`. Field breakdown — [Publish to the catalog](./b24-catalog-publish.md) |
| `data[].createdAt` | string (ISO 8601) | Creation timestamp |
| `data[].access` | object | How this server ended up in the output. Arrives on every row |
| `data[].access.via` | string | `owner` — the server is managed by the current key, `galaxy-reference` — a live Galaxy application managed by the key references this live host in the same Bitrix24 account, `collaborator` — you are on the server's development team. On an `owner` row the block consists of this field alone |
| `data[].access.role` | string | Only when `via: "collaborator"`. Your role: `DEVELOPER` — work with the code, `ADMIN` — machine management on top of that |
| `data[].access.allowedActions` | array | With `via: "collaborator"`, lists the role's capabilities: `read`, `code`, `sources`, `wake`, and for `ADMIN` also `lifecycle`, `settings`, `audience`, `catalogMeta` and `billing`. With `via: "galaxy-reference"`, contains only `read` |
| `data[].access.allowedEndpoints` | array | Ready-to-call operations. With `via: "collaborator"`, the list covers reading the card, working with code and sources, and waking. With `via: "galaxy-reference"`, contains only `GET /v1/infra/servers` and `GET /v1/infra/servers/:id` |
| `data[].access._note` | string | With `via: "collaborator"`, explains team access. With `via: "galaxy-reference"`, warns that the host is read-only and that host management and application operations must target resources managed by the current key |
| `total` | number | Only when requested with `page` and/or `limit`: the number of all unique rows without pagination, meaning managed servers, referenced hosts and all memberships |
| `page` | number | Only when requested with `page` and/or `limit`: the page number applied |
| `limit` | number | Only when requested with `page` and/or `limit`: the page size applied |

## Response example

```json
{
  "success": true,
  "data": [
    {
      "id": "e765edfc-ba0a-43de-b8ea-838dd872c522",
      "status": "running",
      "provider": "bitrix-cloud",
      "kind": "STANDALONE",
      "galaxyId": null,
      "appCount": null,
      "diskTotalMb": null,
      "diskFreeMb": null,
      "diskState": null,
      "diskProbedAt": null,
      "name": "vibe-server-pd9l",
      "displayName": "vibe-server-pd9l",
      "description": null,
      "ip": "111.88.251.211",
      "ssh": {
        "user": "ubuntu",
        "port": 22
      },
      "plan": "bc-small",
      "region": "bc-eu-central",
      "image": "ubuntu-2404-lts",
      "monthlyCost": "24",
      "mode": "OPEN",
      "createdVia": "ui",
      "subdomain": "app-05b67cf7",
      "blackholeStatus": "CONNECTED",
      "accessPolicy": "OWNER_ONLY",
      "runtimeId": null,
      "runtimeStatus": null,
      "appUrl": "https://app-05b67cf7.vibecode.bitrix24.com",
      "sleepAfterMinutes": null,
      "idleSleepProtected": false,
      "runMode": "IDLE",
      "workSchedule": null,
      "provisionError": null,
      "provisionErrorCode": null,
      "provisionReason": null,
      "b24CatalogSync": {
        "status": "IDLE",
        "itemId": null,
        "attempts": 0,
        "pendingOp": null,
        "eligible": true
      },
      "createdAt": "2026-04-03T13:30:25.819Z",
      "access": { "via": "owner" }
    },
    {
      "id": "3f7a91c4-6e0b-42d8-8b55-19ad7c204e6f",
      "status": "running",
      "kind": "GALAXY",
      "galaxyId": null,
      "name": "vibe-galaxy-host-q7x2",
      "displayName": "Shared Galaxy host",
      "createdAt": "2026-06-18T08:15:30.000Z",
      "access": {
        "via": "galaxy-reference",
        "allowedActions": ["read"],
        "allowedEndpoints": [
          "GET /v1/infra/servers",
          "GET /v1/infra/servers/:id"
        ],
        "_note": "This host is readable only because one of your galaxy applications references it. Host management and application operations must target resources owned by your key, not this shared host."
      }
    },
    {
      "id": "b0f4c8a2-7d31-4e56-9a10-2c6f5b83de47",
      "status": "running",
      "provider": "bitrix-cloud",
      "kind": "GALAXY_APP",
      "galaxyId": "3f7a91c4-6e0b-42d8-8b55-19ad7c204e6f",
      "name": "vibe-app-mk4t",
      "displayName": "Request tracker",
      "description": null,
      "plan": "bc-small",
      "region": "bc-eu-central",
      "image": "ubuntu-2404-lts",
      "mode": "BLACKHOLE",
      "createdVia": "galaxy",
      "subdomain": "app-91c40e7b",
      "blackholeStatus": "CONNECTED",
      "accessPolicy": "PORTAL",
      "runtimeId": null,
      "runtimeStatus": null,
      "appUrl": "https://app-91c40e7b.vibecode.bitrix24.com",
      "provisionError": null,
      "provisionErrorCode": null,
      "provisionReason": null,
      "createdAt": "2026-08-14T09:12:47.301Z",
      "access": {
        "via": "collaborator",
        "role": "DEVELOPER",
        "allowedActions": ["read", "code", "sources", "wake"],
        "allowedEndpoints": [
          "GET /v1/infra/servers/:id",
          "POST /v1/infra/servers/:id/deploy",
          "POST /v1/infra/servers/:id/exec",
          "POST /v1/infra/servers/:id/upload",
          "GET /v1/infra/servers/:id/logs",
          "GET /v1/infra/servers/:id/sources",
          "GET /v1/infra/servers/:id/sources/:versionId/download",
          "POST /v1/infra/servers/:id/sources",
          "POST /v1/infra/servers/:id/wake"
        ],
        "_note": "You are on this server's development team, not its owner. Deploying and changing the application code is fully available to you through `allowedEndpoints` — no extra grant and no API-key rebind is needed. Server management (lifecycle, tariff, SSH, access lists) answers 403 SERVER_ROLE_FORBIDDEN and names your role; that is the expected boundary, not a broken permission."
      }
    }
  ]
}
```

## Error response example

401 — no API key passed:

```json
{
  "success": false,
  "error": {
    "code": "MISSING_API_KEY",
    "message": "API key required. Pass via X-Api-Key header."
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not passed |
| 401 | `INVALID_API_KEY` | The key is not recognized — no such key exists on the platform |
| 429 | `RATE_LIMITED` | The platform's overall request limit was exceeded |

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

## Known specifics

- **Tunnel reconciliation uses one snapshot and repairs nothing.** For running BLACKHOLE servers stored as `CONNECTED`, the list uses one current gateway snapshot. A subdomain missing from a non-empty snapshot is shown as `DISCONNECTED`; an unavailable gateway or a successful empty `connections[]` is treated as ambiguous for the whole fleet and preserves the database values. The GET does not persist statuses or run `repair`; `galaxy-reference` rows are excluded from the check.
- **An empty array while servers are running means the current key does not manage them, you are not on their development teams, and its live Galaxy applications do not reference their live hosts.** After the previous key expires or is revoked, the server stays bound to it. If the previous key is deleted, the server is left without a managing key. In both cases a new key returns an empty `data` while the servers keep running and remain visible in the dashboard. How to restore access — [Server access recovery](/docs/infra/server-access-recovery).
- **Even a Bitrix24 account administrator sees only their own servers, hosts referenced by their own Galaxy applications, and servers whose development team they are on.** For an account-wide picture, use the administrator panel in the dashboard — this output ignores account-administrator rights.
- **A team member's row is shorter than the owner's.** It is assembled from its own set of fields rather than by cutting private ones out of the owner's: with `access.via: "collaborator"` the fields `ip`, `ssh`, `deletedAt`, `appCount`, the disk fields, `wakeScheduleCapable` and `b24CatalogSync` do not arrive. Costs (`monthlyCost`) and the sleep threshold with the next wake-up (`sleepAfterMinutes`, `nextScheduledWakeAt`) are added for the `ADMIN` role only. So check whether a field is present on the row rather than treating it as mandatory.
- **A management operation outside your role answers `403 SERVER_ROLE_FORBIDDEN`, not `404`.** The refusal names your role, the required threshold and the calls open to you in `error.hint`. This is the boundary of the role, not lost access: an API-key rebind and a fresh grant are both beside the point — work through the list in `access.allowedEndpoints`, or ask the owner to run the operation. For a key unrelated to the server, the server's existence is still not disclosed — such a key keeps getting `404`.
- **A `galaxy-reference` host is read-only.** The row appears while a live Galaxy application managed by the current key references a live `GALAXY` host in the same Bitrix24 account. Multiple applications on one host produce one row. If the key also manages the host, the full `owner` row arrives. A reference row has no `role`, provider, network, SSH, plan, billing, capacity, build or runtime data. Every host call except the two GET operations in `allowedEndpoints` keeps answering as it would for an unrelated key.
- **Only live servers of your own Bitrix24 account arrive through membership.** Galaxy hosts (`kind: "GALAXY"`) are not shown to a team member. They appear only on separate `galaxy-reference` grounds. Deleted servers never arrive through membership even with `?includeDeleted=true` — that parameter applies only to servers managed by the current key. A server the key manages and whose team you are also on arrives as one row with `access.via: "owner"`.
- **`appUrl` on a member's row is empty until the application's audience opens it to you.** The field is filled only if the server's access policy (`accessPolicy`) opens the application to everyone in the Bitrix24 account, or you hold a personal grant. Team membership gives you the code, not the right to open the application. There is one exception: if your access comes through a department, you can open the application, but the field will not show the link — ask the owner or a team administrator for it.
- **Servers of Bitrix24 accounts marked as deleted are hidden automatically.** The platform checks account availability daily: if an account responds with 410/403 three days in a row, it is marked as deleted and its servers stop being displayed.
- **Without `page`/`limit` the response is not paginated.** Managed servers and unique referenced hosts always arrive in full. `page`/`limit` slice only the servers whose development team you are a member of. With pagination, `total` counts all three groups without duplicates.
- **`includeDeleted=true` does not surface servers of deleted Bitrix24 accounts or restore reference access.** Account-level hiding applies regardless of the parameter value. A deleted application or host also produces no `galaxy-reference` row.
- **`GUEST_NOT_BOOTING` is terminal — retrying does not help.** The machine's guest operating system does not boot after an interrupted update. [`POST /repair`](/docs/infra/lifecycle/repair) and [`POST /start`](/docs/infra/lifecycle/start) return `422` with the same code, [`availableActions`](/docs/infra/lifecycle/refresh) keeps only `delete`, and billing for the machine has stopped. A client that starts or repairs servers on a schedule must read this value: such a machine has to be recreated, not repaired.
- **`DISK_FULL` — the repair could not install the agent: the server's disk is full.** Repeating the repair helps only once disk space has been freed. A successful repair clears the code. Details are in [Get a server](./get.md).

## See also

- [Create a server](./create.md)
- [Get a server](./get.md)
- [Update name and description](./update.md)
- [Delete a server](./delete.md)
- [Lifecycle](/docs/infra/lifecycle)
- [Server access recovery](/docs/infra/server-access-recovery)
