
## Удалить сервер

`DELETE /v1/infra/servers/:id`

Удаляет сервер безвозвратно: виртуальная машина уничтожается у провайдера, запись в базе помечается как `DELETED`, открытые биллинг-транзакции финализируются. Восстановить удалённый сервер нельзя — создавайте новый через [`POST /v1/infra/servers`](./create.md). Удаление идемпотентно только на уровне виртуальной машины у провайдера (если она уже удалена у провайдера, ошибки не будет). Повторный вызов для уже помеченного сервера вернёт 404.

## Параметры

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

## Примеры

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

```bash
curl -X DELETE -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.tech/v1/infra/servers/db008c84-91a5-4e15-b9d5-6c6aa2838448
```

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

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

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

```javascript
const res = await fetch(
  `https://vibecode.bitrix24.tech/v1/infra/servers/${serverId}`,
  {
    method: 'DELETE',
    headers: { 'X-Api-Key': 'YOUR_API_KEY' },
  }
)
const { success } = await res.json()
if (success) console.log('Сервер удалён')
```

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

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

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

| Поле | Тип | Описание |
|------|-----|----------|
| `success` | boolean | `true` при успешном удалении |

Ответ короткий — тело `{ "success": true }` подтверждает факт удаления. Дополнительных данных не возвращается.

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

```json
{
  "success": true
}
```

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

404 — сервер уже удалён или не существует:

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

## Ошибки

| HTTP | Код | Описание |
|------|-----|----------|
| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |
| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |
| 403 | `INFRA_FORBIDDEN_FOR_COWORK_KEY` | Вызов сделан ключом Cowork/Code — такой ключ работает только с данными, изменяющие операции ему закрыты. Что делать — [Проектный ключ для деплоя](/docs/cowork/deploy-key) |
| 404 | `NOT_FOUND` | Сервер не найден, принадлежит другому API-ключу, или уже был удалён |
| 409 | `GALAXY_HAS_APPS` | Сервер — галактика, на которой есть неудалённые приложения. Тело содержит `appCount`. Удалить галактику вместе с её приложениями можно в кабинете |
| 409 | `GALAXY_HOST_WAKE_BLOCKED` | Galaxy-приложение: его хост запрещено будить — например, заморожен счёт. Отказ терминальный, повтор не поможет. Тело содержит `error.reason` — см. «Известные особенности» |
| 502 | `GALAXY_HOST_UNREACHABLE` | Galaxy-приложение: пробуждение хоста началось и не удалось. Ответ несёт `error.hint` с планом восстановления — см. «Известные особенности». Может не возвращаться, когда гостевая операционная система хоста доказанно не загружается, — но метка сама по себе `200` не гарантирует: перед удалением без обращения к хосту платформа ещё убеждается через шлюз, что живого туннеля нет, и эта проверка fail-safe. Недоступный шлюз, ответ без списка соединений или поднявшийся хост оставляют `502` — см. «Известные особенности» |
| 429 | `RATE_LIMITED` | Превышен общий лимит запросов платформы |

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

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

- **Обработка 404 при повторах — норма.** Если клиент потерял соединение после первого `DELETE`, повтор вернёт 404. Ловите 404 как «уже удалено».
- **Если виртуальная машина уже удалена у провайдера другим способом** (панель провайдера, ручная очистка) — `DELETE` всё равно отработает успешно и пометит запись в базе как удалённую.
- **Квота освобождается сразу.** После удаления можно сразу создавать новый сервер — `MAX_SERVERS_REACHED` больше не будет считать эту запись.
- **Удаление работает для любого статуса.** Сервер в `provisioning`, `running`, `sleeping` и `error` — все удаляются штатно.
- **Снимки исходников переживают сервер.** Сохранённые версии кода остаются доступны после удаления: список — `GET /v1/infra/servers/:id/sources`, скачивание — `GET /v1/infra/servers/:id/sources/:versionId/download`. Сам сервер находится через [`GET /v1/infra/servers`](./list.md) с параметром `includeDeleted=true`. Как убрать ненужные версии — [Хранилище исходного кода](/docs/source-storage).
- **Galaxy-приложение удаляется этим же методом.** Если портал размещает приложения в галактиках (несколько приложений работают контейнерами на общем хосте), `DELETE /v1/infra/servers/:id` снимает приложение, которым владеет ключ: разбирает его контейнер на хосте и помечает запись удалённой. Ответ — `200 { "success": true }`, как для обычного сервера.
- **Спящую галактику платформа будит сама.** Если галактика спит, платформа разбудит её перед разбором контейнера — отдельно будить другое приложение и повторять запрос не нужно. Ошибка 502 `GALAXY_HOST_UNREACHABLE` остаётся только когда пробуждение началось и не удалось. В этом случае повторите запрос чуть позже.
- **Отказ будить и провал пробуждения — разные ответы.** Если платформе ЗАПРЕЩЕНО поднимать хост (заморожен счёт, истёк доступ, стоит запрет пробуждения), запрос вернёт `409 GALAXY_HOST_WAKE_BLOCKED`. Это терминальный отказ: повторять бессмысленно, пока причина не снята. Причина приходит в `error.reason` — `BILLING_FROZEN`, `ACCESS_EXPIRED`, `STOPPED` или `UNKNOWN`. Объекта `error.hint` в этом ответе нет: он описывает восстановление недоступного хоста, а восстанавливать здесь нечего.
- **У ответа `502 GALAXY_HOST_UNREACHABLE` есть поле `error.hint` с планом восстановления.** Это объект из четырёх строк: `reason` — почему хост сейчас недоступен, `recovery` — что делать, `recoveryAction` — конкретный вызов для повтора, `note` — оговорка о том, что статус хоста в выдаче может отставать от реального состояния туннеля. Смысл подсказки: запись сервера сохраняется до тех пор, пока разбор контейнера действительно не выполнится на хосте, поэтому повтор запроса через 1–2 минуты ничего не теряет. Если состояние держится дольше 15 минут, хост недоступен по-настоящему.
- **Незагружающийся хост — исключение: приложение удаляется без обращения к нему.** Если платформа доказала, что гостевая операционная система хоста не загружается (у карточки хоста `provisionErrorCode` равен `GUEST_NOT_BOOTING`), туннель не появится уже никогда, и ждать его бессмысленно. В этом случае запрос отвечает `200` — но только если платформа ещё и подтвердила через шлюз, что живого туннеля нет. Проверка fail-safe: недоступный шлюз, ответ без списка соединений или хост, поднявшийся между проверкой и удалением, оставляют прежний `502` даже при выставленной метке. Когда все условия сошлись, запись приложения закрывается, освобождаются его токены доступа, домен и карточка в каталоге. Удалив приложения по одному, вы удаляете и сам хост обычным вызовом — отказ `GALAXY_HAS_APPS` больше не возникает. Признак виден заранее в поле `provisionErrorCode` — [`GET /v1/infra/servers/:id`](./get.md).
- **Галактика с неудалёнными приложениями этим методом не удаляется.** Если сервер — галактика, на которой есть неудалённые приложения, запрос вернёт 409 `GALAXY_HAS_APPS` с полем `appCount`. Удалите приложения по одному, а затем саму галактику. Если приложения удалить нельзя — например, счёт заморожен и галактику не поднять, — удалите галактику вместе с приложениями в кабинете: на публичном интерфейсе такой операции нет.

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

- [Создать сервер](./create.md)
- [Список серверов](./list.md)
- [Получить сервер](./get.md)
- [Остановить сервер](/docs/infra/lifecycle/stop)
- [Усыпить сервер](/docs/infra/lifecycle/sleep-now)
- [Хранилище исходного кода](/docs/source-storage)
