[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"docs-infra\u002Flifecycle":3,"docs-tabs-infra\u002Flifecycle":6},{"content":4,"lastmod":5},"\n# Жизненный цикл\n\nДействия над уже созданным сервером: запуск и остановка, перезагрузка, авто-сон и немедленный сон, пробуждение, принудительное обновление статуса, восстановление туннеля через последовательную консоль (serial console). Все эндпоинты — экшены над конкретным `:id`, большинство возвращает `{ \"success\": true }`.\n\nСкоуп: `vibe:infra`\n\n## Операции\n\n- [Запустить сервер](.\u002Flifecycle\u002Fstart.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fstart`\n- [Остановить сервер](.\u002Flifecycle\u002Fstop.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fstop`\n- [Перезагрузить сервер](.\u002Flifecycle\u002Freboot.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Freboot`\n- [Разбудить сервер](.\u002Flifecycle\u002Fwake.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fwake`\n- [Усыпить сейчас](.\u002Flifecycle\u002Fsleep-now.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fsleep-now`\n- [Настроить авто-сон](.\u002Flifecycle\u002Fsleep.md) — `PATCH \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fsleep`\n- [Обновить статус](.\u002Flifecycle\u002Frefresh.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Frefresh`\n- [Восстановить туннель](.\u002Flifecycle\u002Frepair.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Frepair`\n- [Статус восстановления](.\u002Flifecycle\u002Frepair-status.md) — `GET \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Frepair-status`\n\n## Сценарии\n\n**Экономия на ночном простое (BLACKHOLE):**\n\n1. Настроить авто-сон: [`PATCH \u002Fsleep`](.\u002Flifecycle\u002Fsleep.md) с `sleepAfterMinutes: 60`.\n2. При первом обращении к HTTPS-субдомену или вызове [`\u002Fdeploy`](\u002Fdocs\u002Finfra\u002Fdeploy\u002Fdeploy) сервер пробуждается автоматически.\n3. Если нужно разбудить заранее (например, перед cron-задачей) — [`POST \u002Fwake?wait=true`](.\u002Flifecycle\u002Fwake.md).\n\n**Ручной перезапуск приложения без полной перезагрузки сервера:**\n\n1. Проверить, что туннель в порядке: [`GET \u002Fv1\u002Finfra\u002Fservers\u002F:id`](\u002Fdocs\u002Finfra\u002Fservers\u002Fget) → `blackholeStatus: \"CONNECTED\"`.\n2. Перезапустить сервис: [`POST \u002Fexec`](\u002Fdocs\u002Finfra\u002Fdeploy\u002Fexec) с `systemctl restart app`.\n\nЕсли перезапуск не помог — [`POST \u002Freboot`](.\u002Flifecycle\u002Freboot.md).\n\n**Туннель потерял соединение (DISCONNECTED):**\n\n1. Проверить: [`GET \u002Fv1\u002Finfra\u002Fservers\u002F:id`](\u002Fdocs\u002Finfra\u002Fservers\u002Fget) — `blackholeStatus: \"DISCONNECTED\"` на `RUNNING`-сервере.\n2. Запустить восстановление: [`POST \u002Frepair`](.\u002Flifecycle\u002Frepair.md).\n3. Опрашивать прогресс: [`GET \u002Frepair-status`](.\u002Flifecycle\u002Frepair-status.md).\n4. По завершении — `blackholeStatus` вернётся к `CONNECTED`.\n\n## Смотрите также\n\n- [Серверы](\u002Fdocs\u002Finfra\u002Fservers) — создание и удаление.\n- [Deploy API](\u002Fdocs\u002Finfra\u002Fdeploy) — deploy\u002Fexec\u002Fupload\u002Flogs работают только когда `blackholeStatus=CONNECTED`.\n- [Корневой раздел — Инфраструктура](\u002Fdocs\u002Finfra) — таблица статусов, коды ошибок.\n","2026-06-29",{"lifecycle\u002Fstart.md":7,"lifecycle\u002Fstop.md":8,"lifecycle\u002Freboot.md":9,"lifecycle\u002Fwake.md":10,"lifecycle\u002Fsleep-now.md":11,"lifecycle\u002Fsleep.md":12,"lifecycle\u002Frefresh.md":13,"lifecycle\u002Frepair.md":14,"lifecycle\u002Frepair-status.md":15},"\n## Запустить сервер\n\n`POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fstart`\n\nПоднимает сервер из состояний `sleeping`, `error` или `provisioning`. Для `sleeping` виртуальная машина снова запускается у провайдера и возвращается к статусу `running` по мере готовности — вызов возвращает ответ сразу, не дожидаясь фактической готовности. Её нужно отслеживать опросом [`GET \u002Fv1\u002Finfra\u002Fservers\u002F:id`](\u002Fdocs\u002Finfra\u002Fservers\u002Fget). Для `error` с подключённым туннелем (`blackholeStatus: \"CONNECTED\"`) сервер сразу переводится в `running` без обращения к провайдеру. Для `provisioning` делается повторная попытка старта без сброса таймера ожидания. Для `running` сервера вызов возвращает 404.\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | Описание |\n|----------|---|-----|:-----:|----------|\n| `id` | path | string (UUID) | да | ID сервера |\n\nТело запроса пустое.\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_API_KEY\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fstart\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fstart\n```\n\n### JavaScript — личный ключ\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fstart`,\n  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n)\n\u002F\u002F Ждать готовности — опрашивать GET \u002Fv1\u002Finfra\u002Fservers\u002F:id\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fstart`,\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | `true`. Виртуальная машина запущена у провайдера или команда на запуск отправлена в фоновом режиме |\n\n## Пример ответа\n\n```json\n{ \"success\": true }\n```\n\n## Пример ответа при ошибке\n\n404 — сервер в статусе `running`\u002F`deleted` либо чужой:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"NOT_FOUND\",\n    \"message\": \"Sleeping, error, or provisioning server not found\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 402 | `ACCOUNT_FROZEN` | Баланс Вайбкод заморожен. Пополните и повторите |\n| 404 | `NOT_FOUND` | Сервер в статусе `running`\u002F`deleted` либо принадлежит другому API-ключу |\n| 409 | `CONFLICT` | Статус сервера изменился во время операции — повторите запрос |\n| 422 | `VM_MISSING` | У записи нет `externalId` — виртуальная машина не создана или удалена извне. Удалите сервер и создайте новый |\n| 429 | `RATE_LIMITED` | Превышен общий лимит запросов платформы |\n| 502 | `PROVIDER_ERROR` | Облачный провайдер вернул ошибку при запуске виртуальной машины |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Блокирующий вариант.** Если клиенту нужна полная готовность сервера перед следующим шагом — используйте [`POST \u002Fwake?wait=true`](.\u002Fwake.md) вместо `\u002Fstart`. Он ждёт `status: \"running\"` + `blackholeStatus: \"CONNECTED\"` до ~6.5 минут.\n- **Ручной `\u002Fstart` обходит `preventWake`.** В отличие от автоматического пробуждения при обращении к субдомену, явный `POST \u002Fstart` снимает флаг `preventWake` и запускает сервер даже если он был заблокирован. Биллинговые блокировки (`ACCOUNT_FROZEN`) обходятся отдельным пополнением, не через `\u002Fstart`.\n- **Для `running` возвращает 404, не 409.** Сознательный выбор: сервер уже в нужном состоянии, делать нечего. Для перезагрузки — [`POST \u002Freboot`](.\u002Freboot.md).\n\n## Смотрите также\n\n- [Остановить сервер](.\u002Fstop.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fstop`.\n- [Разбудить сервер (с `?wait=true`)](.\u002Fwake.md) — блокирующий вариант с ожиданием готовности.\n- [Немедленно усыпить](.\u002Fsleep-now.md) — обратная операция.\n- [Обновить статус](.\u002Frefresh.md) — принудительно опросить провайдера после старта.\n- [Получить сервер](\u002Fdocs\u002Finfra\u002Fservers\u002Fget) — опрос готовности.\n","\n## Остановить сервер\n\n`POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fstop`\n\nШтатная остановка работающего сервера. Виртуальная машина останавливается у провайдера, статус меняется на `sleeping`, открытая биллинг-транзакция по рабочему периоду закрывается, открывается транзакция по сонному периоду (тариф sleep существенно ниже). Работает для любого режима — и BLACKHOLE, и OPEN. Сервер можно снова запустить через [`POST \u002Fstart`](.\u002Fstart.md) или разбудить автоматически обращением к субдомену.\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | Описание |\n|----------|---|-----|:-----:|----------|\n| `id` | path | string (UUID) | да | ID сервера |\n\nТело запроса пустое.\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_API_KEY\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fstop\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fstop\n```\n\n### JavaScript — личный ключ\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fstop`,\n  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fstop`,\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | `true` при успешной остановке |\n\n## Пример ответа\n\n```json\n{ \"success\": true }\n```\n\n## Пример ответа при ошибке\n\n422 — сервер существует, но не в статусе `running` (например, `sleeping`). В ответе — текущее состояние и доступные действия:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"SERVER_WRONG_STATE\",\n    \"message\": \"Server is SLEEPING; \u002Fstop requires RUNNING.\",\n    \"userMessage\": \"Server is currently SLEEPING. Stop only applies to a RUNNING server.\",\n    \"currentState\": { \"status\": \"SLEEPING\", \"blackholeStatus\": \"DISCONNECTED\", \"hasExternalId\": true },\n    \"availableActions\": [\"wake\", \"start\", \"repair\", \"delete\"]\n  }\n}\n```\n\n404 — сервера с таким `id` нет (удалён или принадлежит другому API-ключу):\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"SERVER_NOT_FOUND\",\n    \"message\": \"Server not found\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 404 | `SERVER_NOT_FOUND` | Сервера с таким `id` нет — удалён или принадлежит другому API-ключу |\n| 422 | `SERVER_WRONG_STATE` | Сервер существует, но не в статусе `running`. В `error.currentState` — текущее состояние, в `error.availableActions` — что можно сделать сейчас |\n| 422 | `VM_MISSING` | У серверной записи нет облачной ВМ (создание не завершилось или ВМ удалена вручную) — удалите сервер и создайте заново |\n| 429 | `RATE_LIMITED` | Превышен общий лимит запросов платформы |\n| 502 | `PROVIDER_ERROR` | Облачный провайдер вернул ошибку при остановке |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Почему `sleeping`, а не `stopped`.** Это терминология Infrastructure API: остановленный сервер называется «спящим», потому что биллинг для него идёт по отдельному тарифу `sleepPriceMonthly` (см. [тарифы провайдера](\u002Fdocs\u002Finfra\u002Fproviders\u002Fplans)) — ниже, чем рабочий. Значение `stopped` в v1-ответах не встречается.\n- **`\u002Fstop` сбрасывает `preventWake`** (автоматический флаг, блокирующий пробуждение) — после остановки сервер снова можно пробудить автоматически обращением к субдомену или через [`\u002Fwake`](.\u002Fwake.md).\n- **Для BLACKHOLE есть альтернатива — [`\u002Fsleep-now`](.\u002Fsleep-now.md).** Функционально результат идентичный. `\u002Fsleep-now` используется из UI-кнопки «Усыпить» и явно помечен как BH-специфический. `\u002Fstop` — универсальный для любого режима.\n\n## Смотрите также\n\n- [Запустить сервер](.\u002Fstart.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fstart`.\n- [Немедленно усыпить](.\u002Fsleep-now.md) — синоним для BLACKHOLE.\n- [Настроить авто-сон](.\u002Fsleep.md) — чтобы сервер засыпал сам через N минут простоя.\n- [Удалить сервер](\u002Fdocs\u002Finfra\u002Fservers\u002Fdelete) — полное удаление виртуальной машины.\n","\n## Перезагрузить сервер\n\n`POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Freboot`\n\nПерезагружает работающий сервер у облачного провайдера. Во время перезагрузки сервер переходит в `provisioning` и возвращается в `running` через 30–90 секунд. Операция атомарная: внутренний guard на уровне базы предотвращает гонки, если одновременно пришло несколько вызовов. Если провайдер не поддерживает перезагрузку — возвращается 501 и статус откатывается на `running`.\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | Описание |\n|----------|---|-----|:-----:|----------|\n| `id` | path | string (UUID) | да | ID сервера в статусе `running` |\n\nТело запроса пустое.\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_API_KEY\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Freboot\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Freboot\n```\n\n### JavaScript — личный ключ\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Freboot`,\n  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n)\n\n\u002F\u002F Опрос готовности после перезагрузки\nwhile (true) {\n  await new Promise(r => setTimeout(r, 5000))\n  const res = await fetch(\n    `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}`,\n    { headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n  )\n  const { data } = await res.json()\n  if (data.status === 'running' && data.blackholeStatus === 'CONNECTED') break\n}\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Freboot`,\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | `true`. Команда на перезагрузку отправлена провайдеру |\n\n## Пример ответа\n\n```json\n{ \"success\": true }\n```\n\n## Пример ответа при ошибке\n\n422 — сервер существует, но не в статусе `running`. В ответе — текущее состояние и доступные действия:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"SERVER_WRONG_STATE\",\n    \"message\": \"Server is SLEEPING; \u002Freboot requires RUNNING.\",\n    \"userMessage\": \"Server is currently SLEEPING. Reboot only applies to a RUNNING server.\",\n    \"currentState\": { \"status\": \"SLEEPING\", \"blackholeStatus\": \"DISCONNECTED\", \"hasExternalId\": true },\n    \"availableActions\": [\"wake\", \"start\", \"repair\", \"delete\"]\n  }\n}\n```\n\n409 — статус сервера изменился во время операции (гонка):\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"CONFLICT\",\n    \"message\": \"Server state changed during operation\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 404 | `SERVER_NOT_FOUND` | Сервера с таким `id` нет — удалён или принадлежит другому API-ключу |\n| 422 | `SERVER_WRONG_STATE` | Сервер существует, но не в статусе `running`. В `error.currentState` — текущее состояние, в `error.availableActions` — что можно сделать сейчас |\n| 422 | `VM_MISSING` | У серверной записи нет облачной ВМ (создание не завершилось или ВМ удалена вручную) — удалите сервер и создайте заново |\n| 409 | `CONFLICT` | Гонка состояний — статус сервера изменился во время операции. Повторите запрос после проверки [`GET \u002Fv1\u002Finfra\u002Fservers\u002F:id`](\u002Fdocs\u002Finfra\u002Fservers\u002Fget) |\n| 429 | `RATE_LIMITED` | Превышен общий лимит запросов платформы |\n| 501 | `NOT_SUPPORTED` | Облачный провайдер не поддерживает перезагрузку. Используйте последовательность [`\u002Fstop`](.\u002Fstop.md) → [`\u002Fstart`](.\u002Fstart.md) |\n| 502 | `PROVIDER_ERROR` | Облачный провайдер вернул ошибку. Статус сервера автоматически откатывается на `running` |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Атомарный переход `running → provisioning`.** База обновляется одним `updateMany` с условием `status = 'RUNNING'`. Если в тот же момент прилетел ещё один `\u002Freboot` или `\u002Fstop`, второй вызов получит 409 `CONFLICT`.\n- **Автоматический откат при ошибке провайдера.** Если `adapter.rebootServer()` кинул исключение, запись возвращается к статусу `running` — чтобы клиент не остался с «зависшим» `provisioning`.\n- **Для перезапуска только приложения** (без перезагрузки виртуальной машины) используйте [`POST \u002Fexec`](\u002Fdocs\u002Finfra\u002Fdeploy\u002Fexec) с командой `systemctl restart app` — это в десятки раз быстрее и не прерывает туннель.\n- **После перезагрузки ждите оба поля.** Чтобы сервер был готов к работе, нужны одновременно `status: \"running\"` и `blackholeStatus: \"CONNECTED\"` — туннель переподключается после старта виртуальной машины.\n\n## Смотрите также\n\n- [Запустить сервер](.\u002Fstart.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fstart`.\n- [Остановить сервер](.\u002Fstop.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fstop`.\n- [Восстановить туннель](.\u002Frepair.md) — если туннель не восстанавливается после перезагрузки.\n- [Выполнить команду](\u002Fdocs\u002Finfra\u002Fdeploy\u002Fexec) — перезапуск приложения без перезагрузки виртуальной машины.\n","\n## Разбудить сервер\n\n`POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fwake`\n\nПробуждает сервер из `sleeping` или `provisioning`. В отличие от [`\u002Fstart`](.\u002Fstart.md), `\u002Fwake` поддерживает блокирующий режим через `?wait=true` — ответ возвращается только когда сервер полностью готов (виртуальная машина запущена **и** туннель подключился) или сработал таймаут. Используйте блокирующий режим, когда клиенту нужна готовность перед следующим шагом (cron-задача, триггерный вызов), и асинхронный — когда можно подождать на опросе.\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | По умолч. | Описание |\n|----------|---|-----|:-----:|-----------|----------|\n| `id` | path | string (UUID) | да | — | ID сервера в статусе `sleeping` или `provisioning` |\n| `wait` | query | string | нет | — | `true` — блокирующий режим: ответ вернётся только когда сервер готов (до 6.5 минут) или сработает таймаут. Любое другое значение — асинхронный режим, ответ сразу |\n\nТело запроса пустое.\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\n# Асинхронный вызов — ответ сразу, готовность проверяйте опросом\ncurl -X POST -H \"X-Api-Key: YOUR_API_KEY\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fwake\n\n# Блокирующий — ждёт готовности до ~6.5 минут\ncurl -X POST -H \"X-Api-Key: YOUR_API_KEY\" \\\n  \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fwake?wait=true\"\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fwake?wait=true\"\n```\n\n### JavaScript — личный ключ\n\n```javascript\n\u002F\u002F Блокирующий вариант — проще всего для последующих шагов\nconst res = await fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fwake?wait=true`,\n  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n)\nconst body = await res.json()\nif (!body.success) {\n  \u002F\u002F Rich-error: показать пользователю userMessage, предложить alternatives\n  console.error(body.error.userMessage ?? body.error.message)\n  if (body.error.alternatives) console.log('Варианты:', body.error.alternatives)\n  throw new Error(body.error.code)\n}\nconsole.log(`Сервер готов: ${body.data.appUrl}`)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst res = await fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fwake?wait=true`,\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | `true` при успешном пробуждении |\n| `data.id` | string (UUID) | ID сервера |\n| `data.status` | string | Актуальный статус (`RUNNING` при `wait=true` успехе, `PROVISIONING` в асинхронном режиме) |\n| `data.blackholeStatus` | string | Состояние туннеля (`CONNECTED` в блокирующем при успехе) |\n| `data.appUrl` | string \\| null | HTTPS-адрес приложения |\n\n## Пример ответа\n\nУспешное пробуждение (`?wait=true`):\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"e765edfc-ba0a-43de-b8ea-838dd872c522\",\n    \"status\": \"RUNNING\",\n    \"blackholeStatus\": \"CONNECTED\",\n    \"appUrl\": \"https:\u002F\u002Fapp-05b67cf7.vibecode.bitrix24.tech\"\n  }\n}\n```\n\n## Пример ответа при ошибке\n\n402 — коммерческий тариф обязателен (расширенный формат ошибки для AI-агентов):\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"COMMERCIAL_PLAN_REQUIRED\",\n    \"message\": \"Waking this server requires a commercial Bitrix24 plan or an active trial\",\n    \"userMessage\": \"Для пробуждения сервера нужен коммерческий тариф Битрикс24 или активный trial. Оформите тариф на https:\u002F\u002Fwww.bitrix24.ru\u002Fprices\u002F\",\n    \"alternatives\": [\n      \"Обновить тариф Битрикс24 и повторить\",\n      \"Перейти на AI Router с BYOK-ключами — он работает на любом тарифе\"\n    ],\n    \"hint\": \"Не повторяйте автоматически — нужно действие пользователя\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 402 | `COMMERCIAL_PLAN_REQUIRED` | Бесплатный тариф и trial недоступен — обновите тариф Битрикс24 |\n| 402 | `TRIAL_EXPIRED` | Trial использован и завершился |\n| 402 | `BILLING_EXHAUSTED` | Баланс Вайбкод исчерпан — пополните |\n| 402 | `ACCOUNT_FROZEN` | Баланс заморожен |\n| 403 | `SERVER_WAKE_BLOCKED` | Пробуждение заблокировано не из-за биллинга (завершённый trial, административный блок, нарушения безопасности) |\n| 404 | `NOT_FOUND` | Сервер не в статусе `sleeping`\u002F`provisioning`, удалён или принадлежит другому API-ключу |\n| 422 | `VM_MISSING` | У записи нет `externalId` — виртуальная машина не создана у провайдера. Удалите сервер и создайте новый |\n| 429 | `RATE_LIMITED` | Превышен лимит запросов. В ответе приходит заголовок `Retry-After` с рекомендованной паузой |\n| 502 | `PROVIDER_ERROR` | Облачный провайдер вернул ошибку при запуске виртуальной машины |\n| 503 | `WAKE_TIMEOUT` | Блокирующий `?wait=true` не дождался готовности (таймаут ~6.5 минуты). Сервер возвращается в `sleeping` — попробуйте снова |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Поведение при таймауте `?wait=true`.** Если за ~6.5 минуты виртуальная машина не поднялась, эндпоинт возвращает `503 WAKE_TIMEOUT` и пробует откатить сервер в `sleeping` — чтобы квота не висела на «вечно зависшем» сервере. Поможет повторный `\u002Fwake` или [`\u002Frepair`](.\u002Frepair.md).\n- **Поля расширенной ошибки для AI-агентов.** При 402\u002F403 тело ошибки дополнительно содержит `userMessage` (переведённая формулировка для пользователя), `alternatives` (список путей решения) и `hint` (совет AI-агенту, повторять автоматически или нет). Используйте эти поля в UI вместо голого `code`\u002F`message`.\n- **`\u002Fwake` не нужен при доступе через HTTPS-субдомен.** Любое обращение к HTTPS-субдомену сервера само инициирует пробуждение BLACKHOLE-сервера. Явный `\u002Fwake` нужен, когда:\n  - Клиенту нужен программный gate «сначала разбуди, потом делай» — через `wait=true`.\n  - Сервер помечен `preventWake=true` (биллинговая блокировка, требует ручного действия).\n- **Проверка доступности ДО вызова.** Перед `\u002Fwake` вызывайте [`GET \u002Fv1\u002Fme`](\u002Fdocs\u002Fkeys-auth) и смотрите `capabilities.servers.wake.available`. Если `false`, пользователю нужно совершить действие (пополнить баланс, обновить тариф) до того, как пробуждение станет возможным.\n- **Для `error`-сервера `\u002Fwake` не подходит** — используйте [`\u002Fstart`](.\u002Fstart.md) или [`\u002Frepair`](.\u002Frepair.md).\n\n## Смотрите также\n\n- [Запустить сервер](.\u002Fstart.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fstart` — ручной старт без блокировки.\n- [Усыпить сейчас](.\u002Fsleep-now.md) — обратная операция.\n- [Восстановить туннель](.\u002Frepair.md) — если сервер проснулся, но туннель не подключается.\n- [Тариф и доступ](\u002Fdocs\u002Finfra#тариф-и-доступ) — контекст для 402-ошибок.\n","\n## Усыпить сейчас\n\n`POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fsleep-now`\n\nНемедленно усыпляет работающий BLACKHOLE-сервер: виртуальная машина останавливается у провайдера, статус меняется на `sleeping`, рабочая биллинг-транзакция финализируется и открывается сонная (тариф sleep ниже). Полезно для разовой экономии, когда вы знаете, что сервер не понадобится в ближайшие часы. Для автоматической остановки через N минут простоя используйте [`PATCH \u002Fsleep`](.\u002Fsleep.md).\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | Описание |\n|----------|---|-----|:-----:|----------|\n| `id` | path | string (UUID) | да | ID сервера в режиме `BLACKHOLE`, статус `running` |\n\nТело запроса пустое.\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_API_KEY\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fsleep-now\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fsleep-now\n```\n\n### JavaScript — личный ключ\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fsleep-now`,\n  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fsleep-now`,\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | `true` при успешном переходе в `sleeping` |\n\n## Пример ответа\n\n```json\n{ \"success\": true }\n```\n\n## Пример ответа при ошибке\n\n400 — сервер не в BLACKHOLE:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"BLACKHOLE_ONLY\",\n    \"message\": \"Sleep is only available for BLACKHOLE servers\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 400 | `BLACKHOLE_ONLY` | Сервер в режиме `OPEN`. Для OPEN-серверов используйте [`\u002Fstop`](.\u002Fstop.md) |\n| 400 | `NOT_RUNNING` | Сервер не в статусе `running` (уже спит, в ошибке или создаётся) |\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 404 | `NOT_FOUND` | Сервер не существует или принадлежит другому API-ключу |\n| 409 | `CONFLICT` | Гонка состояний — статус сервера изменился во время операции |\n| 429 | `RATE_LIMITED` | Превышен общий лимит запросов платформы |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **На OPEN-сервере используйте [`\u002Fstop`](.\u002Fstop.md).** Функционально для BLACKHOLE `\u002Fsleep-now` и `\u002Fstop` эквивалентны, но `\u002Fsleep-now` помечен как BH-специфический и для OPEN вернёт `BLACKHOLE_ONLY`.\n- **Автоматическое пробуждение сохраняется.** В отличие от административного блока (`preventWake=true`), ручной `\u002Fsleep-now` не ставит `preventWake` — сервер проснётся сам при обращении к HTTPS-субдомену или по вызову [`\u002Fdeploy`](\u002Fdocs\u002Finfra\u002Fdeploy\u002Fdeploy).\n- **Атомарный переход.** База обновляется одним `updateMany` с фильтром `status='RUNNING'` — гонки двух одновременных вызовов приводят ко второму `CONFLICT`, а не к двойному списанию.\n\n## Смотрите также\n\n- [Настроить авто-сон](.\u002Fsleep.md) — `PATCH \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fsleep` — сервер засыпает сам через N минут.\n- [Остановить сервер](.\u002Fstop.md) — универсальная остановка (работает и для OPEN).\n- [Запустить сервер](.\u002Fstart.md) — пробудить из `sleeping`.\n- [Разбудить с ожиданием](.\u002Fwake.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fwake?wait=true` — блокирующее пробуждение.\n","\n## Настроить авто-сон\n\n`PATCH \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fsleep`\n\nНастраивает таймер автоматического засыпания BLACKHOLE-сервера. При отсутствии HTTP-запросов или SSH-активности в течение `sleepAfterMinutes` минут сервер автоматически останавливается. При следующем обращении просыпается сам. Передача `null` отключает авто-сон.\n\n`null` отключает только наш авто-сон по бездействию. Если сервер стоит на **вытесняемом (preemptible)** тарифе (`bc-agent`, `bc-micro` — см. [Тарифы](\u002Fdocs\u002Finfra\u002Fproviders\u002Fplans)), облако всё равно принудительно перезапускает такую машину примерно раз в сутки, с коротким окном недоступности; платформа автоматически будит её обратно. Для по-настоящему непрерывной 24\u002F7-нагрузки выбирайте **невытесняемый** тариф (`bc-small` и выше) — на нём `null` действительно означает работу до ручной остановки.\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | Описание |\n|----------|---|-----|:-----:|----------|\n| `id` | path | string (UUID) | да | ID сервера в режиме BLACKHOLE |\n\n## Поля запроса (body)\n\n| Поле | Тип | Обяз. | Описание |\n|------|-----|:-----:|----------|\n| `sleepAfterMinutes` | number \\| null | **да** | Таймаут простоя в минутах. Допустимые значения: `15`, `30`, `60`, `240`, или `null` (для отключения авто-сна). Другие значения отклоняются с `VALIDATION_ERROR` |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\n# Включить авто-сон через 60 минут простоя\ncurl -X PATCH https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fsleep \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"sleepAfterMinutes\": 60}'\n\n# Отключить авто-сон\ncurl -X PATCH https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fsleep \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"sleepAfterMinutes\": null}'\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X PATCH https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fsleep \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"sleepAfterMinutes\": 60}'\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst res = await fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fsleep`,\n  {\n    method: 'PATCH',\n    headers: {\n      'X-Api-Key': 'YOUR_API_KEY',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({ sleepAfterMinutes: 60 }),\n  }\n)\nconst { data } = await res.json()\nconsole.log(`Авто-сон через ${data.sleepAfterMinutes} мин`)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fsleep`,\n  {\n    method: 'PATCH',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({ sleepAfterMinutes: null }),\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | Всегда `true` при успехе |\n| `data.sleepAfterMinutes` | number \\| null | Актуальное значение таймаута (эхо переданного) |\n\n## Пример ответа\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"sleepAfterMinutes\": 60\n  }\n}\n```\n\n## Пример ответа при ошибке\n\n400 — некорректное значение `sleepAfterMinutes`:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"VALIDATION_ERROR\",\n    \"message\": \"sleepAfterMinutes must be 15, 30, 60, 240, or null\"\n  }\n}\n```\n\n400 — сервер не в BLACKHOLE:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"BLACKHOLE_ONLY\",\n    \"message\": \"Sleep settings are only available for BLACKHOLE servers\"\n  }\n}\n```\n\n400 — переход в «Всегда онлайн» при включённых окнах пробуждения:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ALWAYS_ON_CONFLICT\",\n    \"message\": \"The server has enabled wake-schedule windows, which conflict with always-on (24\u002F7) mode. Delete or disable the wake windows first, or keep a sleep timeout.\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 400 | `VALIDATION_ERROR` | `sleepAfterMinutes` не в списке `[15, 30, 60, 240, null]` |\n| 400 | `BLACKHOLE_ONLY` | Сервер в режиме `OPEN` — авто-сон недоступен |\n| 400 | `ALWAYS_ON_CONFLICT` | `null` на невытесняемом тарифе при включённых [окнах пробуждения](\u002Fdocs\u002Fchangelog) — сначала удалите или отключите окна |\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 404 | `NOT_FOUND` | Сервер не существует, удалён или принадлежит другому API-ключу |\n| 429 | `RATE_LIMITED` | Превышен общий лимит запросов платформы |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Что считается активностью и сбрасывает таймер.** HTTP-обращения к приложению через туннель, активность на порту 22 (для OPEN-серверов) и exec-сессии Deploy API. Реальная активность проверяется раз в несколько минут через Gateway-метрики.\n- **Авто-пробуждение сохраняется.** Сервер, заснувший по таймеру, автоматически просыпается при следующем HTTP-запросе к HTTPS-субдомену или при вызове [`\u002Fdeploy`](\u002Fdocs\u002Finfra\u002Fdeploy\u002Fdeploy)\u002F[`\u002Fwake`](.\u002Fwake.md)\u002F[`\u002Fstart`](.\u002Fstart.md).\n- **Значение по умолчанию для новых серверов** — 60 минут. Текущее значение — в поле [`GET \u002Fv1\u002Finfra\u002Fservers\u002F:id`](\u002Fdocs\u002Finfra\u002Fservers\u002Fget).\n- **Агенты и managed-боты** создают свои серверы с `sleepAfterMinutes: null` — они должны оставаться в сети круглосуточно, чтобы отвечать на сообщения. Для обычных приложений такая настройка тоже допустима, но приведёт к постоянному списанию по рабочему тарифу. По умолчанию агент\u002Fбот создаётся на вытесняемом тарифе (дешевле), который облако перезапускает ~раз в сутки; для непрерывной работы включите опцию «Всегда онлайн» при создании — она ставит агента\u002Fбота на невытесняемый тариф.\n- **Взаимное исключение с расписанием пробуждения.** `sleepAfterMinutes: null` на невытесняемом тарифе означает «Всегда онлайн» — такой сервер несовместим с включёнными [окнами пробуждения](\u002Fdocs\u002Fchangelog): запрос отклоняется с `ALWAYS_ON_CONFLICT`. Верно и обратное — окно нельзя объявить на сервере «Всегда онлайн». Сначала удалите или отключите окна, либо оставьте числовой таймаут.\n- **Эндпоинт не меняет статус** — только обновляет конфигурацию. Чтобы усыпить сервер сразу, используйте [`POST \u002Fsleep-now`](.\u002Fsleep-now.md).\n\n## Смотрите также\n\n- [Усыпить сейчас](.\u002Fsleep-now.md) — немедленная остановка, не дожидаясь таймера.\n- [Запустить сервер](.\u002Fstart.md) — пробудить из `sleeping`.\n- [Тарифы провайдера](\u002Fdocs\u002Finfra\u002Fproviders\u002Fplans) — поле `sleepPriceMonthly` показывает тариф в режиме сна.\n- [Получить сервер](\u002Fdocs\u002Finfra\u002Fservers\u002Fget) — проверить текущее значение `sleepAfterMinutes`.\n","\n## Обновить статус\n\n`POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Frefresh`\n\nПринудительно опрашивает облачного провайдера, получает актуальный статус и IP сервера, и обновляет запись в базе, если что-то изменилось. Полезно, когда статус в платформе расходится с реальностью — например, после провайдерских работ, зависания в `provisioning` или ручной остановки виртуальной машины через панель провайдера.\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | Описание |\n|----------|---|-----|:-----:|----------|\n| `id` | path | string (UUID) | да | ID сервера |\n\nТело запроса пустое.\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_API_KEY\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Frefresh\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Frefresh\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst res = await fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Frefresh`,\n  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n)\nconst { data: status } = await res.json()\nconsole.log(`Актуальный статус: ${status}`)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Frefresh`,\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | Всегда `true` при успехе |\n| `data` | string | Актуальный статус в верхнем регистре: `PROVISIONING`, `RUNNING`, `SLEEPING`, `ERROR` |\n| `currentState` | object | Снимок состояния — те же поля, что в `error.currentState` для 422 SERVER_WRONG_STATE: `status`, `blackholeStatus`, `hasExternalId`, `lastSeenAt` |\n| `availableActions` | string[] | Подмножество `['wake','start','reboot','sleep-now','repair','delete']` — действия, которые имеет смысл вызывать в текущем состоянии |\n\n> Поле `data` — это строка со статусом для обратной совместимости. Снимок состояния и список действий вынесены в соседние поля `currentState` и `availableActions`. Для полного снимка сервера (IP, политика и т. п.) запросите [`GET \u002Fv1\u002Finfra\u002Fservers\u002F:id`](\u002Fdocs\u002Finfra\u002Fservers\u002Fget).\n\n## Пример ответа\n\n```json\n{\n  \"success\": true,\n  \"data\": \"RUNNING\",\n  \"currentState\": {\n    \"status\": \"RUNNING\",\n    \"blackholeStatus\": \"CONNECTED\",\n    \"hasExternalId\": true,\n    \"lastSeenAt\": null\n  },\n  \"availableActions\": [\"reboot\", \"sleep-now\", \"delete\"]\n}\n```\n\n## Пример ответа при ошибке\n\n404 — сервер не существует:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"SERVER_NOT_FOUND\",\n    \"message\": \"Server not found\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 404 | `SERVER_NOT_FOUND` | Сервер не существует, удалён или принадлежит другому API-ключу |\n| 429 | `RATE_LIMITED` | Превышен общий лимит запросов платформы |\n| 502 | `PROVIDER_ERROR` | Облачный провайдер вернул ошибку при опросе виртуальной машины |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Может переписать статус в базе.** Если провайдер сообщает статус, отличный от текущего в базе (например, `stopped` у провайдера при `running` в базе), запись обновляется: `running → sleeping`, `sleeping → running`, появляется IP и т. п. Это главный способ «самолечения» записи в `error`.\n- **Подводный камень сравнения:** `data === 'RUNNING'`, а не `data.status === 'RUNNING'` — поле `data` намеренно сохранено как строка ради обратной совместимости. Снимок состояния и список доступных действий — соседние поля `currentState` и `availableActions`. Это отличается от [`GET \u002Fv1\u002Finfra\u002Fservers\u002F:id`](\u002Fdocs\u002Finfra\u002Fservers\u002Fget), где вся информация внутри `data`.\n- **Идемпотентно и безопасно.** Частые вызовы не создают записи, не запускают виртуальную машину, не финализируют биллинг. Подходит для ad-hoc сверки. Для циклов опроса готовности лучше подходит [`GET \u002Fv1\u002Finfra\u002Fservers\u002F:id`](\u002Fdocs\u002Finfra\u002Fservers\u002Fget) — он даёт полный объект.\n- **Не сбивает таймер фонового монитора.** Если провайдер вернул тот же статус и IP, что уже в базе, `\u002Frefresh` не обновляет `updatedAt` — чтобы не сбить таймер внутреннего монитора, который отсчитывает таймауты `provisioning` (10 минут).\n\n## Смотрите также\n\n- [Получить сервер](\u002Fdocs\u002Finfra\u002Fservers\u002Fget) — `GET \u002Fv1\u002Finfra\u002Fservers\u002F:id` — полная картина (автоматически дёргает refresh, если статус `provisioning`).\n- [Восстановить туннель](.\u002Frepair.md) — если статус `running`, но `blackholeStatus: DISCONNECTED`.\n- [Запустить сервер](.\u002Fstart.md) — если `\u002Frefresh` показал `sleeping` неожиданно.\n","\n## Восстановить туннель\n\n`POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Frepair`\n\nЗапускает фоновое восстановление туннеля Black Hole через serial console облачного провайдера. Используйте, когда виртуальная машина в `running`, но `blackholeStatus` застрял в `DISCONNECTED` или `WAITING` — то есть агент туннеля не подключается. Процедура проходит через serial console (минуя файрвол) и включает: впрыск SSH-ключа → SSH-подключение → полную переустановку агента с актуальной версией → ожидание переподключения. Длится до 2 минут. Сам вызов возвращается сразу и не ждёт завершения, прогресс смотрите через [`GET \u002Frepair-status`](.\u002Frepair-status.md).\n\n> **Это не способ снять `EXEC_BUSY`.** `\u002Frepair` — полная переустановка агента туннеля: живые процессы, запущенные через [`\u002Fexec`](..\u002Fdeploy\u002Fexec.md), при этом прерываются вместе с их побочными эффектами (например, открытая транзакция `COPY` во внешней базе повиснет и будет держать блокировки до таймаута на её стороне). Если сервер отвечает `409 EXEC_BUSY`, снимите лок вызовом [`DELETE \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Flock`](..\u002Fdeploy\u002Flock.md) — агент и запущенные процессы при этом не затрагиваются. `\u002Frepair` оставьте для случая по назначению: туннель действительно не подключается.\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | Описание |\n|----------|---|-----|:-----:|----------|\n| `id` | path | string (UUID) | да | ID сервера |\n\nТело запроса пустое.\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_API_KEY\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Frepair\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Frepair\n```\n\n### JavaScript — личный ключ\n\n```javascript\n\u002F\u002F Запустить ремонт и периодически опрашивать статус\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Frepair`,\n  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n)\n\nwhile (true) {\n  await new Promise(r => setTimeout(r, 10000))\n  const res = await fetch(\n    `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Frepair-status`,\n    { headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n  )\n  const { data } = await res.json()\n  console.log(`Шаг: ${data.step ?? data.status}`)\n  if (data.status === 'idle' || data.status === 'completed' || data.status === 'failed') break\n}\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nawait fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Frepair`,\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | `true` — ремонт успешно запущен в фоне |\n| `data.status` | string | Всегда `\"started\"` при успехе |\n\n## Пример ответа\n\n```json\n{\n  \"success\": true,\n  \"data\": { \"status\": \"started\" }\n}\n```\n\n## Пример ответа при ошибке\n\n409 — ремонт заблокирован (например, сервер помечен `preventWake=true`):\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"REPAIR_BLOCKED\",\n    \"message\": \"Repair blocked: server prevents wake\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 404 | `NOT_FOUND` | Сервер не существует, удалён или принадлежит другому API-ключу |\n| 409 | `REPAIR_BLOCKED` | Ремонт заблокирован: `preventWake=true` (биллинговая заморозка, административный блок) или сервер в особом состоянии |\n| 422 | `VM_MISSING` | У записи нет `externalId` — виртуальная машина не создана у провайдера. Удалите сервер и создайте новый |\n| 429 | `RATE_LIMITED` | Превышен общий лимит запросов платформы |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Почему serial console, а не SSH.** Когда агент не подключён, SSH через iptables BLACKHOLE-сервера недоступен. Serial console провайдера Bitrix Cloud минует файрвол на уровне гипервизора и позволяет внедрить SSH-ключ в уже работающую виртуальную машину, не перезагружая её.\n- **Идемпотентно.** Процедура выполняет полный цикл (стоп агента → скачивание свежего бинарника → чистая конфигурация → запуск) и безопасна для здорового сервера — навредить не может. Повторный вызов во время идущего ремонта просто вернёт 409\u002Fто же `started`, ничего не ломает.\n- **Режим сервера сохраняется.** OPEN-сервер остаётся OPEN (iptables не трогается), BLACKHOLE — BLACKHOLE.\n- **Как разблокировать `REPAIR_BLOCKED`.** Если сервер помечен `preventWake` (биллинговая заморозка, истёкший trial, админблок) — сначала устраните причину (пополните баланс, обновите тариф), потом повторите `\u002Frepair`.\n\n## Смотрите также\n\n- [Статус ремонта](.\u002Frepair-status.md) — `GET \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Frepair-status` — прогресс текущей операции.\n- [Обновить статус](.\u002Frefresh.md) — проверить, поправился ли `blackholeStatus` после ремонта.\n- [Получить сервер](\u002Fdocs\u002Finfra\u002Fservers\u002Fget) — проверить `blackholeStatus` и `status`.\n- [Перезагрузить сервер](.\u002Freboot.md) — альтернатива, если `repair` не помог.\n","\n## Статус восстановления\n\n`GET \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Frepair-status`\n\nВозвращает прогресс фонового восстановления туннеля, запущенного через [`POST \u002Frepair`](.\u002Frepair.md). Используется для периодического опроса: клиент видит текущий шаг (`wake` \u002F `serial_console` \u002F `ssh_install` \u002F `connect` \u002F …), финальный статус (`running` \u002F `done` \u002F `failed`) и в случае ошибки — поле `error`. Завершённые записи автоматически очищаются через 10 минут.\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | Описание |\n|----------|---|-----|:-----:|----------|\n| `id` | path | string (UUID) | да | ID сервера |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -H \"X-Api-Key: YOUR_API_KEY\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Frepair-status\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Frepair-status\n```\n\n### JavaScript — личный ключ\n\n```javascript\n\u002F\u002F Цикл опроса прогресса\nwhile (true) {\n  const res = await fetch(\n    `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Frepair-status`,\n    { headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n  )\n  const { data } = await res.json()\n\n  if (data.status === 'idle') { console.log('Ремонт не запущен'); break }\n  if (data.status === 'done')  { console.log(`Готово, шаг: ${data.step}`); break }\n  if (data.status === 'failed'){ console.error(`Ошибка на шаге ${data.step}: ${data.error}`); break }\n\n  console.log(`Шаг: ${data.step}`)\n  await new Promise(r => setTimeout(r, 10000))\n}\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst res = await fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Frepair-status`,\n  {\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | Всегда `true` при успехе |\n| `data.status` | string | `idle` (ремонт не запускался или очищен по таймауту), `running` (идёт), `done` (успешно), `failed` (провалился) |\n| `data.step` | string | Текущий\u002Fпоследний шаг: `wake`, `serial_console`, `ssh_install`, `connect`, `iptables`, `cleanup`, `done` |\n| `data.agentVersion` | string \\| null | Версия установленного агента (заполняется на шаге `ssh_install`) |\n| `data.wasSlept` | boolean | Был ли сервер в `sleeping` на момент запуска ремонта (тогда после `done` возвращается в `sleeping`) |\n| `data.error` | string | Текст ошибки, если `status: \"failed\"` |\n| `data.startedAt` | number | Timestamp старта ремонта (миллисекунды Unix) |\n\nДля `status: \"idle\"` возвращается только поле `status`, остальные поля отсутствуют.\n\n## Пример ответа\n\nРемонт не запускался:\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"status\": \"idle\"\n  }\n}\n```\n\nРемонт идёт, завершён шаг установки агента:\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"status\": \"running\",\n    \"step\": \"connect\",\n    \"agentVersion\": \"1.2.3\",\n    \"wasSlept\": false,\n    \"startedAt\": 1745312400000\n  }\n}\n```\n\nРемонт провалился:\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"status\": \"failed\",\n    \"step\": \"ssh_install\",\n    \"agentVersion\": null,\n    \"wasSlept\": false,\n    \"error\": \"SSH connection refused\",\n    \"startedAt\": 1745312400000\n  }\n}\n```\n\n## Пример ответа при ошибке\n\n404 — сервер не существует:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"NOT_FOUND\",\n    \"message\": \"Server not found\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 404 | `NOT_FOUND` | Сервер не существует, удалён или принадлежит другому API-ключу |\n| 429 | `RATE_LIMITED` | Превышен общий лимит запросов платформы |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Порядок выполнения шагов:** `wake` (если сервер в `sleeping`) → `serial_console` (впрыск SSH-ключа через serial console Bitrix Cloud) → `ssh_install` (SSH-подключение и переустановка агента: скачивание бинаря, запись конфигурации, запуск сервиса) → `connect` (ожидание подключения агента к Gateway) → `iptables` (восстановление файрвола для BLACKHOLE) → `cleanup` (возвращение в `sleeping`, если сервер был спящим) → `done`.\n- **Сразу после [`POST \u002Frepair`](.\u002Frepair.md) статус уже `running`, не `idle`.** Статус выставляется в `running` синхронно при старте ремонта, поэтому первый же опрос `repair-status` (даже спустя миллисекунды) видит `running`. Раньше был короткий промежуток, где опрос мог увидеть `idle` и цикл опроса завершался преждевременно — теперь этого окна нет.\n- **TTL завершённых записей — 10 минут.** После этого повторный опрос вернёт `idle`. Если нужно подтвердить результат после TTL, смотрите на `blackholeStatus` в [`GET \u002Fv1\u002Finfra\u002Fservers\u002F:id`](\u002Fdocs\u002Finfra\u002Fservers\u002Fget) — если он `CONNECTED`, ремонт сработал.\n- **Одновременный ремонт невозможен** — на уровне сервиса стоит замок в памяти `repairingServers`. Повторный [`POST \u002Frepair`](.\u002Frepair.md) на сервере с уже идущим ремонтом корректно обрабатывается: второй вызов не запускает новую процедуру.\n\n## Смотрите также\n\n- [Восстановить туннель](.\u002Frepair.md) — `POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Frepair` — запуск ремонта.\n- [Получить сервер](\u002Fdocs\u002Finfra\u002Fservers\u002Fget) — проверить итоговый `blackholeStatus`.\n- [Обновить статус](.\u002Frefresh.md) — принудительно опросить провайдера после ремонта.\n"]