
## Получить сервер

`GET /v1/infra/servers/:id`

Возвращает детали одного сервера по ID. Если сервер в статусе `provisioning`, эндпоинт автоматически опрашивает облачного провайдера на предмет актуального статуса и IP — подходит для цикла опроса после создания. Удалённый сервер (`status: "deleted"`) не доступен: возвращается 404.

## Параметры

| Параметр | В | Тип | Обяз. | Описание |
|----------|---|-----|:-----:|----------|
| `id` | path | string (UUID) | да | ID сервера из [`POST /v1/infra/servers`](./create.md) или [`GET /v1/infra/servers`](./list.md) |

## Примеры

### curl — личный ключ

```bash
curl -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.tech/v1/infra/servers/e765edfc-ba0a-43de-b8ea-838dd872c522
```

### curl — OAuth-приложение

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

### JavaScript — личный ключ

```javascript
// Опрос готовности сервера
async function waitReady(serverId) {
  while (true) {
    const res = await fetch(
      `https://vibecode.bitrix24.tech/v1/infra/servers/${serverId}`,
      { headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
    )
    const { data } = await res.json()
    if (data.status === 'running' && data.blackholeStatus === 'CONNECTED') {
      return data
    }
    if (data.status === 'error') {
      throw new Error(`Сервер в ошибке: ${data.id}`)
    }
    await new Promise(r => setTimeout(r, 10000))
  }
}
```

### JavaScript — OAuth-приложение

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

## Поля ответа

| Поле | Тип | Описание |
|------|-----|----------|
| `success` | boolean | Всегда `true` при успехе |
| `data.id` | string (UUID) | ID сервера |
| `data.status` | string | `provisioning` \| `running` \| `sleeping` \| `error`. Удалённый сервер возвращает 404 |
| `data.provider` | string | ID провайдера |
| `data.kind` | string | Тип ресурса: `STANDALONE` (отдельная виртуальная машина), `GALAXY` (галактика — хост-носитель galaxy-приложений) или `GALAXY_APP` (galaxy-приложение — контейнер на общем хосте). Определяет контракт деплоя — проверяйте его перед загрузкой кода |
| `data.galaxyId` | string (UUID) \| null | Для `GALAXY_APP` — ID хоста, на котором размещено приложение. Для остальных типов `null` |
| `data.appCount` | number \| null | Для `GALAXY`-хоста — число неудалённых приложений на нём. Для остальных типов `null` |
| `data.diskTotalMb` | number \| null | Размер диска машины-галактики в мебибайтах. Для `STANDALONE` и `GALAXY_APP` — `null` |
| `data.diskFreeMb` | number \| null | Свободное место на диске машины-галактики в мебибайтах. Для `STANDALONE` и `GALAXY_APP` — `null` |
| `data.diskState` | string \| null | Оценка занятости диска: `ok`, `warning`, `critical` или `unknown`, если замера ещё не было. Пороги описаны в [Галактика](/docs/infra/galaxy). Для `STANDALONE` и `GALAXY_APP` — `null` |
| `data.diskProbedAt` | string (ISO 8601) \| null | Время замера диска. У спящей машины приходит последнее известное значение вместе с временем этого замера |
| `data.reachability` | object \| null | Только для `GALAXY_APP` — может ли приложение ответить прямо сейчас: `effectiveStatus`, состояние галактики-носителя `hostStatus` и `hostTunnel`, живо снятые `container` и `forwarder`, исход опроса `probe` и его время `probedAt`. Поле `status` выше — состояние учётной записи приложения, и во время пробуждения оно отстаёт от машины. Разбор значений — [Сон и пробуждение Galaxy-приложения](/docs/infra/galaxy-sleep). Для остальных типов `null` |
| `data.name` | string | Системное имя сервера — технический идентификатор |
| `data.displayName` | string \| null | Отображаемое имя для UI. Если при создании не передавалось — совпадает с `name` |
| `data.description` | string \| null | Описание приложения для карточки каталога Битрикс24. `null`, если описание не задавали. Меняется через [`PATCH /v1/infra/servers/:id`](./update.md) |
| `data.ip` | string \| null | Публичный IP. `null` пока виртуальная машина не получит адрес |
| `data.ssh` | object \| null | Для OPEN-сервера: `{ user, port, hasPassword }`. Для BLACKHOLE может быть `null` или тот же блок без фактического доступа. **Пароль и приватный ключ здесь не возвращаются** — их отдаёт только [`POST /v1/infra/servers`](./create.md) один раз при создании |
| `data.plan` | string | Тариф. **Для galaxy-приложения** (`kind: "GALAXY_APP"`) возвращается тариф хоста-носителя, а не запрошенный при создании — приложения делят ресурсы хоста |
| `data.region` | string | Регион, в который сервер попал реально. **Для galaxy-приложения** возвращается регион хоста-носителя (платформа сама выбирает размещение), а не запрошенный |
| `data.image` | string | Образ ОС |
| `data.monthlyCost` | string | Каталожная месячная стоимость в Вайбах (Ꝟ) строкой (например `"1200"`). Фактическое списание может отличаться. Сравнивайте через `Number(data.monthlyCost)` |
| `data.mode` | string | `BLACKHOLE` или `OPEN` |
| `data.createdVia` | string | `api` — вызов через API Вайбкод, `ui` — действие в личном кабинете, `galaxy` — galaxy-приложение. У серверов агентов и ботов приходят собственные значения |
| `data.subdomain` | string | Субдомен для приложения |
| `data.blackholeStatus` | string | `NONE` \| `WAITING` \| `CONNECTED` \| `DISCONNECTED` |
| `data.accessPolicy` | string | `OWNER_ONLY` \| `NAMED_USERS` \| `DEPARTMENT` \| `PORTAL` \| `AUTHENTICATED` \| `PUBLIC` |
| `data.runtimeId` | string \| null | ID рантайма, установленного через POST /:id/deploy (создание сервера всегда даёт `null`). |
| `data.runtimeStatus` | string \| null | Устаревшее поле, оставлено для совместимости. Для серверов, созданных после 2026-04-25, всегда возвращается `null`. Рантайм ставится на этапе [`POST /:id/deploy`](/docs/infra/deploy/deploy), а сигнал его готовности — успех шага `runtime` в ответе деплоя, а не значение этого поля |
| `data.appUrl` | string \| null | HTTPS-адрес приложения |
| `data.localPort` | number | Локальный порт, на который туннель направляет трафик (по умолчанию `3000`). Меняется через [`PATCH /v1/infra/servers/:id/port`](/docs/infra/deploy/port) |
| `data.portPinned` | boolean | Порт закреплён в настройках агента на машине, поэтому переживает сон, пробуждение и восстановление туннеля. `false` — агент определяет порт сам при каждом старте. Подробнее — [Изменение порта](/docs/infra/deploy/port) |
| `data.sleepAfterMinutes` | number \| null | Через сколько минут простоя сервер автоматически усыпляется. `null` — не усыплять автоматически |
| `data.provisionError` | string \| null | Краткая причина последней ошибки провижининга/сборки. `null`, если ошибок не было |
| `data.provisionErrorCode` | string \| null | Машиночитаемый код категории сбоя: `PREEMPTIBLE_EVICTION` / `PROVISION_TIMEOUT` / `NO_CAPACITY` / `GUEST_NOT_BOOTING` / `GENERIC`. `null`, если ошибок не было. Значение `GUEST_NOT_BOOTING` терминальное — см. «Известные особенности» |
| `data.provisionReason` | string \| null | Структурный признак причины сбоя galaxy-приложения: `oom` — не хватило памяти контейнера, или `crash`. `null` у обычных серверов и когда сбоя не было. Значение `oom` — сигнал перенести приложение на выделенный сервер, порядок описан в [Создать сервер](./create.md) |
| `data.buildLog` | string \| null | Хвост лога docker-сборки (≤8 КБ) для упавшей сборки galaxy-приложения. `null` для обычных серверов и при успешной сборке |
| `data.nextScheduledWakeAt` | string (ISO 8601) \| null | Время ближайшего запланированного пробуждения (с учётом опережающего запаса). `null`, если у сервера нет включённых окон пробуждения. Настраивается через [Пробуждение по расписанию](/docs/infra/wake-schedules) |
| `data.wakeScheduleCapable` | boolean | Доступна ли серверу настройка окон пробуждения по расписанию — зависит от типа сервера и включённости фичи на портале |
| `data.buildHint` | string \| null | Локализованная рекомендация, что делать со сбоем сборки galaxy-приложения. Поле приходит всегда. `null` — у обычных серверов, у galaxy-приложения вне статуса `error` и когда причину сбоя не удалось отнести ни к одной известной категории |
| `data.b24CatalogSync` | object | Состояние карточки приложения в каталоге приложений Вайбкод на портале Битрикс24: `{ status, itemId, attempts, pendingOp, eligible }`. Разбор полей — [Опубликовать в каталоге](./b24-catalog-publish.md) |
| `data.createdAt` | string (ISO 8601) | Момент создания |

## Пример ответа

```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,
      "hasPassword": true
    },
    "plan": "bc-small",
    "region": "ru-central1-a",
    "image": "fd80bm0rh4rkepi5ksdi",
    "monthlyCost": "1200",
    "mode": "OPEN",
    "createdVia": "ui",
    "subdomain": "app-05b67cf7",
    "blackholeStatus": "CONNECTED",
    "accessPolicy": "OWNER_ONLY",
    "runtimeId": null,
    "runtimeStatus": null,
    "appUrl": "https://app-05b67cf7.vibecode.bitrix24.tech",
    "localPort": 3000,
    "portPinned": true,
    "sleepAfterMinutes": null,
    "provisionError": null,
    "provisionErrorCode": null,
    "provisionReason": null,
    "b24CatalogSync": {
      "status": "IDLE",
      "itemId": null,
      "attempts": 0,
      "pendingOp": null,
      "eligible": true
    },
    "buildLog": null,
    "nextScheduledWakeAt": null,
    "wakeScheduleCapable": true,
    "buildHint": null,
    "createdAt": "2026-04-03T13:30:25.819Z"
  }
}
```

## Пример ответа при ошибке

404 — сервер с таким ID не существует или принадлежит другому API-ключу:

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

## Ошибки

| HTTP | Код | Описание |
|------|-----|----------|
| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |
| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |
| 404 | `NOT_FOUND` | Сервер не найден или принадлежит другому API-ключу |
| 429 | `RATE_LIMITED` | Превышен общий лимит запросов платформы |

Полный список общих ошибок API — [Ошибки](/docs/errors).

## Известные особенности

- **Для `running`/`sleeping`/`error` запроса к провайдеру нет.** Автоматический опрос провайдера срабатывает только при статусе `provisioning`. Если нужно сверить состояние других статусов — используйте [`POST /v1/infra/servers/:id/refresh`](/docs/infra/lifecycle/refresh).
- **Критерий готовности — два поля.** Для продолжения работы с [Deploy API](/docs/infra/deploy) нужны одновременно `status: "running"` **и** `blackholeStatus: "CONNECTED"`. Если стоит только `running` — виртуальная машина уже жива, но агент туннеля ещё не подключился. Готовность рантайма после деплоя определяется успехом шага `runtime` в ответе [`POST /:id/deploy`](/docs/infra/deploy/deploy) — поле `runtimeStatus` для этого не используется, оно устаревшее и остаётся `null`.
- **`blackholeStatus: "DISCONNECTED"` при `running`** — туннель потерял связь у живого сервера. Попробуйте [`POST /v1/infra/servers/:id/repair`](/docs/infra/lifecycle/repair).
- **Подводный камень `monthlyCost`:** поле возвращается строкой. Сравнение двух таких строк идёт посимвольно: `"24" > "1000"` вернёт `true`, а `.sort()` выстроит значения не по величине. Приводите к числу через `Number(data.monthlyCost)`.
- **Если потеряли SSH-креды из ответа создания — восстановить нельзя.** Пересоздайте SSH-ключ вручную через [`POST /v1/infra/servers/:id/exec`](/docs/infra/deploy/exec) (для BLACKHOLE) или пересоздайте сервер.
- **`GUEST_NOT_BOOTING` — терминальное состояние, повтор не поможет.** Гостевая операционная система машины не загружается после прерванного обновления. [`POST /repair`](/docs/infra/lifecycle/repair) и [`POST /start`](/docs/infra/lifecycle/start) отвечают `422` с этим же кодом, в [`availableActions`](/docs/infra/lifecycle/refresh) остаётся только `delete`, начисление за машину закрыто. Приложения, размещённые на таком хосте, как правило удаляются по одному без живого туннеля — [`DELETE /v1/infra/servers/:id`](./delete.md) отвечает `200`, после чего удаляется и сам хост. Метка сама по себе `200` не гарантирует: платформа ещё подтверждает через шлюз отсутствие живого туннеля, и эта проверка fail-safe — при недоступном шлюзе ответ остаётся `502` (разбор — в [`DELETE`](./delete.md)). Клиент, который запускает или ремонтирует серверы по расписанию, обязан читать это значение: такую машину нужно пересоздать, а не чинить.

## Смотрите также

- [Создать сервер](./create.md)
- [Список серверов](./list.md)
- [Обновить имя и описание](./update.md)
- [Удалить сервер](./delete.md)
- [Обновить статус](/docs/infra/lifecycle/refresh)
- [Метрики туннеля](/docs/infra/deploy/metrics)
