Создать сервер

POST /v1/infra/servers

Создаёт приложение у облачного провайдера. Всегда в режиме Black Hole — iptables блокирует все входящие порты, приложение невидимо из интернета.

На портале есть две модели размещения, и от модели зависит, чего ждать после создания:

  • Отдельная виртуальная машина (модель по умолчанию). Ответ возвращается сразу со статусом provisioning, провижининг занимает 1–3 минуты, после чего нужно опрашивать `GET /v1/infra/servers/:id` до status: "running" и blackholeStatus: "CONNECTED". Ответ единственный раз содержит SSH-данные ssh.password и ssh.privateKey — они будут нужны при переключении в режим OPEN, сохраните их сразу. Эта страница описывает данную модель в полях запроса, полях ответа и таблице ошибок ниже.
  • Galaxy-приложение — контейнер на общем хосте. Если портал размещает приложения в галактиках, тот же POST /v1/infra/servers создаёт galaxy-приложение, а не виртуальную машину. Признак модели в ответе — поле createdVia равно galaxy. Раздел «Galaxy-приложение» ниже описывает два сценария запуска, полная модель — на странице Galaxy-приложение.

Galaxy-приложение

Если портал размещает приложения в галактиках, POST /v1/infra/servers создаёт galaxy-приложение — контейнер на общем хосте, а не отдельную виртуальную машину. Запрос и порядок вызовов те же, отличается жизненный цикл. Признак модели в ответе — поле createdVia равно galaxy. Полная модель, стоимость и отличия деплоя — на странице Galaxy-приложение.

Не ждите CONNECTED перед загрузкой кода. Galaxy-приложение никогда само не доходит до blackholeStatus: "CONNECTED" — его контейнер собирается при загрузке кода. Если просто опрашивать статус, приложение останется в provisioning, а примерно через 20 минут платформа пометит его как error и запишет в поле provisionError, что код так и не был загружен. Поэтому код загружают сразу — одним из двух сценариев ниже.

Сценарий 1 — прозрачный, рекомендуется

Один запрос. Передайте в POST /v1/infra/servers код приложения в поле source вместе с runtime и start (и при необходимости install, env, port). Сборка пойдёт в фоновом режиме. После ответа опрашивайте `GET /v1/infra/servers/:id` до status: "running". Отдельный вызов загрузки кода не нужен.

Terminal
curl -X POST https://vibecode.bitrix24.tech/v1/infra/servers \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-crm-app",
    "displayName": "Мой CRM-бот",
    "source": { "content": "<base64-архив>" },
    "runtime": "node20",
    "start": "node index.js",
    "install": "npm ci",
    "port": 3000
  }'

Поля source, runtime, start, install, env, port совпадают по смыслу с телом `POST /:id/deploy`:

Поле Тип Обяз. Описание
source object да (для этого сценария) Источник кода. source.content — архив приложения в base64, до 500 МБ на тело запроса
runtime string да (если передан source) ID рантайма: node20, python311, php83, static и другие. Список — `GET /v1/infra/runtimes`
start string да (если передан source) Команда запуска приложения, одной строкой. Перенос строки вернёт 400
install string нет Команда установки зависимостей, одной строкой
env object нет Переменные окружения { "KEY": "value" }. Подставляются в контейнер при запуске, см. ниже
port number нет Порт, на котором приложение слушает

Без полей runtime и start поле source вернёт 400 — оба поля обязательны. На портале без режима галактик source запрещён и вернётся 400 SOURCE_AT_CREATE_GALAXY_ONLY.

Сценарий 2 — в два шага

Создайте приложение без source — ответ придёт со статусом provisioning и подсказкой next: "deploy". Сразу вызовите `POST /v1/infra/servers/:id/deploy` с кодом в source, рантаймом и командой запуска. Загружайте код сразу, не дожидаясь CONNECTED.

Terminal
# Шаг 1 — создать приложение без кода
curl -X POST https://vibecode.bitrix24.tech/v1/infra/servers \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "provider": "bitrix-cloud", "name": "my-crm-app", "plan": "bc-medium", "region": "ru-central1-a" }'

# Ответ содержит data.id, data.next = "deploy" и data.hint.
# Шаг 2 — сразу загрузить код, не дожидаясь CONNECTED
curl -X POST https://vibecode.bitrix24.tech/v1/infra/servers/SERVER_ID/deploy \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": { "content": "<base64-архив>" },
    "runtime": "node20",
    "start": "node index.js",
    "port": 3000
  }'

provider, plan и region обязательны по схеме для создания без source; для galaxy-приложения их значения информационны — приложение наследует план и регион своего хоста.

Диагностика и переменные окружения

  • Поле provisionError. Если сборка или запуск упали, `GET /v1/infra/servers/:id` вернёт в data.provisionError причину сбоя, а при ошибке сборки образа — ещё и хвост лога сборки Docker. Читайте это поле, чтобы понять причину.
  • Переменные env подставляются при запуске. Значения из env передаются в контейнер во время запуска через docker run --env, а не вшиваются в образ. Поэтому ключи API и секреты из env не попадают в слои образа.

Поля запроса (body)

Поле Тип Обяз. Описание
provider string да ID провайдера из `GET /v1/infra/providers`, например bitrix-cloud. 1–50 символов
name string да Технический идентификатор (slug). 2–63 символа, только строчные латинские буквы, цифры и -, первым символом — буква. Паттерн: ^[a-z][a-z0-9-]*$. Используется в URL поддомена (app-<hex> генерируется отдельно), логах, audit-журнале. Неизменяемый после создания. Для отображаемого имени используйте displayName
displayName string нет Отображаемое имя на любом языке (русский, китайский, эмодзи — что угодно). 2–100 символов, без управляющих байтов. Отображается в UI, уведомлениях о падении сервера, security-алертах, биллинг-строках, B24-каталоге. Если не передан — подставится name (slug). name остаётся техническим идентификатором (неизменяемым, используется в URL поддомена и логах)
plan string да ID тарифа из `GET /v1/infra/providers/:providerId/plans`, например bc-small
region string да ID региона из `GET /v1/infra/providers/:providerId/regions`, например ru-central1-b
image string нет ID образа ОС из `GET /v1/infra/providers/:providerId/images`. Если не передан — платформа сама подставит актуальный образ провайдера. Если передаёте — берите актуальный из ответа: ID меняется при обновлении сборки
sshPublicKey string нет Ваш SSH-публичный ключ (ssh-rsa …, ssh-ed25519 …, ecdsa-sha2-nistp256/384/521 …, security-keys). До 8192 символов. Если не передан — платформа сгенерирует приватный ключ и вернёт его один раз в ssh.privateKey
placement string нет Модель размещения: auto (по умолчанию) или dedicated. На портале с режимом «Сначала галактика» (galaxies-only) значение dedicated создаёт отдельную виртуальную машину, а не galaxy-приложение — перенос приложения на собственный сервер. Проходит те же проверки, что и обычное создание сервера: политику serverCreation и квоту серверов на пользователя. При auto поведение прежнее (в режиме «Сначала галактика» создаётся galaxy-приложение)
graduateFrom string нет ID вашего galaxy-приложения (kind=GALAXY_APP), которое платформа удалит сразу после того, как создаст для него выделенный сервер — чтобы старое приложение не осталось висеть в галактике. Ограничен владельцем: тот же ключ, тот же портал, kind=GALAXY_APP. Чужой идентификатор или идентификатор не galaxy-приложения вернёт 404, ничего не удаляя. Имеет смысл только вместе с placement: dedicated. Заголовок Idempotency-Key с graduateFrom для выделенного сервера несовместим — см. Идемпотентность

Примечание: для модели отдельной виртуальной машины параметр runtime в POST /v1/infra/servers не принимается — передача вернёт 400 RUNTIME_PARAM_REMOVED. Рантайм устанавливается на этапе деплоя. См. POST /:id/deploy. Исключение — режим галактик: при передаче поля source параметр runtime обязателен (см. раздел «Galaxy-приложение»), и 400 RUNTIME_PARAM_REMOVED в этом случае не возвращается.

Примеры

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

Terminal
# name — только строчные латинские буквы, цифры и дефис, первый символ буква (^[a-z][a-z0-9-]*$)
curl -X POST https://vibecode.bitrix24.tech/v1/infra/servers \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "bitrix-cloud",
    "name": "my-crm-app",
    "displayName": "Мой CRM-бот",
    "plan": "bc-small",
    "region": "ru-central1-b",
    "image": "fd83esfomhq25p2ono90"
  }'

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

Terminal
# name — только строчные латинские буквы, цифры и дефис, первый символ буква (^[a-z][a-z0-9-]*$)
curl -X POST https://vibecode.bitrix24.tech/v1/infra/servers \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "bitrix-cloud",
    "name": "my-crm-app",
    "displayName": "Мой CRM-бот",
    "plan": "bc-small",
    "region": "ru-central1-b",
    "image": "fd83esfomhq25p2ono90"
  }'

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

javascript
// name — только строчные латинские буквы, цифры и дефис, первый символ буква (^[a-z][a-z0-9-]*$)
const res = await fetch('https://vibecode.bitrix24.tech/v1/infra/servers', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    provider: 'bitrix-cloud',
    name: 'my-crm-app',
    displayName: 'Мой CRM-бот',
    plan: 'bc-small',
    region: 'ru-central1-b',
    image: 'fd83esfomhq25p2ono90',
  }),
})
const { data } = await res.json()
console.log('Server ID:', data.id, 'Subdomain:', data.subdomain)

// Сохраняем SSH-креды на всякий случай — они возвращаются только один раз
if (data.ssh.privateKey) {
  await saveLocally(`${data.id}.key`, data.ssh.privateKey)
}

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

javascript
// name — только строчные латинские буквы, цифры и дефис, первый символ буква (^[a-z][a-z0-9-]*$)
const res = await fetch('https://vibecode.bitrix24.tech/v1/infra/servers', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    provider: 'bitrix-cloud',
    name: 'my-crm-app',
    displayName: 'Мой CRM-бот',
    plan: 'bc-small',
    region: 'ru-central1-b',
    image: 'fd83esfomhq25p2ono90',
  }),
})

Поля ответа

Поле Тип Описание
success boolean Всегда true при успехе
data.id string (UUID) Уникальный идентификатор сервера
data.status string Всегда "provisioning" сразу после создания. Ждите "running" через 1–3 минуты
data.provider string Эхо переданного provider
data.name string Эхо переданного name (slug)
data.kind string Тип сервера, всегда: STANDALONE или GALAXY_APP
data.galaxyId string Только для galaxy-ветки (id хоста-галактики); в standalone-ответе ключ отсутствует
data.displayName string | null Отображаемое имя. Если при создании не передавали displayName — будет равно name
data.ip string | null Публичный IP. null сразу после создания, заполнится когда виртуальная машина запустится
data.ssh.user string Пользователь для SSH: root для новых серверов
data.ssh.port number Порт SSH: 22
data.ssh.password string | null Одноразово! Пароль root. Сохраняйте сразу — позже не вернётся. Нужен при переключении в OPEN-режим
data.ssh.privateKey string | null Одноразово! Приватный ключ в формате OpenSSH (если sshPublicKey не передавали при создании). Сохраняйте сразу
data.plan string Эхо переданного plan. Исключение — galaxy-приложение (createdVia: "galaxy"): возвращается тариф хоста-носителя, а не запрошенный
data.region string Регион, в который сервер реально попал. Может отличаться от запрошенного при переключении на запасную зону (см. «Известные особенности»). Для galaxy-приложения — регион хоста-носителя
data.image string Эхо переданного image
data.mode string Всегда "BLACKHOLE" сразу после создания
data.createdVia string "api" для вызовов через v1 API, "ui" для вызовов из личного кабинета
data.subdomain string Субдомен для приложения, например app-92fb1c34. Используется в appUrl
data.blackholeStatus string Состояние туннеля агента. Сразу после создания — "NONE", затем проходит через WAITING и завершается CONNECTED
data.accessPolicy string Политика доступа к приложению. По умолчанию "OWNER_ONLY" — только владелец ключа
data.runtimeId string | null Всегда null при создании. Заполняется при деплое с runtime
data.runtimeStatus string | null Всегда null при создании. Обновляется во время деплоя
data.appUrl string | null HTTPS-адрес приложения: https://{subdomain}.vibecode.bitrix24.tech
data.createdAt string (ISO 8601) Момент создания

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

Отдельная виртуальная машина:

JSON
{
  "success": true,
  "data": {
    "id": "db008c84-91a5-4e15-b9d5-6c6aa2838448",
    "status": "provisioning",
    "provider": "bitrix-cloud",
    "name": "docs-test-temp",
    "kind": "STANDALONE",
    "ip": null,
    "ssh": {
      "user": "root",
      "port": 22,
      "password": "0FPIIR9EfO2OAeSSMK6bKA",
      "privateKey": "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmU…\n-----END OPENSSH PRIVATE KEY-----\n"
    },
    "plan": "bc-agent",
    "region": "ru-central1-b",
    "image": "fd83esfomhq25p2ono90",
    "mode": "BLACKHOLE",
    "createdVia": "api",
    "subdomain": "app-92fb1c34",
    "blackholeStatus": "NONE",
    "accessPolicy": "OWNER_ONLY",
    "runtimeId": null,
    "runtimeStatus": null,
    "appUrl": "https://app-92fb1c34.vibecode.bitrix24.tech",
    "createdAt": "2026-04-22T10:50:11.477Z"
  }
}

Galaxy-приложение по сценарию 1 — source передан, сборка идёт в фоне. Полей ssh и next нет:

JSON
{
  "success": true,
  "data": {
    "id": "7c2b1f08-3a4d-4e91-9b6c-2f5e8a1d0c33",
    "status": "provisioning",
    "provider": "bitrix-cloud",
    "name": "my-crm-app",
    "kind": "GALAXY_APP",
    "galaxyId": "<galaxy-host-id>",
    "displayName": "Мой CRM-бот",
    "ip": null,
    "ssh": null,
    "plan": "bc-medium",
    "region": "ru-central1-a",
    "image": "ubuntu-2404-lts",
    "mode": "BLACKHOLE",
    "createdVia": "galaxy",
    "subdomain": "app-7c2b1f08",
    "blackholeStatus": "NONE",
    "accessPolicy": "OWNER_ONLY",
    "runtimeId": null,
    "runtimeStatus": null,
    "appUrl": "https://app-7c2b1f08.vibecode.bitrix24.tech",
    "createdAt": "2026-04-22T10:50:11.477Z"
  }
}

Galaxy-приложение по сценарию 2 — source не передан, появляются next и hint:

JSON
{
  "success": true,
  "data": {
    "id": "7c2b1f08-3a4d-4e91-9b6c-2f5e8a1d0c33",
    "status": "provisioning",
    "provider": "bitrix-cloud",
    "name": "my-crm-app",
    "kind": "GALAXY_APP",
    "galaxyId": "<galaxy-host-id>",
    "displayName": "Мой CRM-бот",
    "ip": null,
    "ssh": null,
    "plan": "bc-medium",
    "region": "ru-central1-a",
    "image": "ubuntu-2404-lts",
    "mode": "BLACKHOLE",
    "createdVia": "galaxy",
    "subdomain": "app-7c2b1f08",
    "blackholeStatus": "NONE",
    "accessPolicy": "OWNER_ONLY",
    "runtimeId": null,
    "runtimeStatus": null,
    "appUrl": "https://app-7c2b1f08.vibecode.bitrix24.tech",
    "createdAt": "2026-04-22T10:50:11.477Z",
    "next": "deploy",
    "hint": "This is a galaxy app — POST /v1/infra/servers/:id/deploy with source.content now; it will not reach \"running\" on its own."
  }
}

Если сборка galaxy-приложения упала, `GET /v1/infra/servers/:id` вернёт причину в data.provisionError:

JSON
{
  "success": true,
  "data": {
    "id": "7c2b1f08-3a4d-4e91-9b6c-2f5e8a1d0c33",
    "status": "error",
    "createdVia": "galaxy",
    "provisionError": "Docker build failed: npm ci exited with code 1"
  }
}

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

400 — нарушена валидация (имя начинается с заглавной):

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "name: Name must start with a letter and contain only lowercase letters, digits, and hyphens"
  }
}

Ошибки

HTTP Код Описание
400 INVALID_REQUEST Нарушена валидация полей (неверный формат имени, отсутствует обязательное поле, неверный SSH-ключ и т. д.). Поле message содержит конкретную причину
400 SOURCE_AT_CREATE_GALAXY_ONLY Поле source передано на портале без режима галактик. Загружайте код через `POST /:id/deploy` после создания
400 RUNTIME_PARAM_REMOVED Параметр runtime удалён для модели отдельной виртуальной машины. Указывайте рантайм в `POST /:id/deploy`
400 UNKNOWN_PARAM В теле есть неизвестное поле (например deployMode вместо placement). details.unknownFields перечисляет лишние поля, details.suggestions подсказывает правильное имя, details.validParams — полный список допустимых полей
401 MISSING_API_KEY Не передан заголовок X-Api-Key
401 INVALID_API_KEY Неверный или просроченный API-ключ
402 COMMERCIAL_PLAN_REQUIRED Бесплатный тариф Битрикс24 и пробный период недоступны (пробный уже использован). См. раздел «Тариф и доступ»
402 TRIAL_EXPIRED Trial использован и завершился
402 TRIAL_PORTAL_LIMIT Превышена квота серверов портала на trial
402 TRIAL_USER_LIMIT Превышена квота серверов на пользователя на trial
402 PLAN_NOT_ALLOWED_ON_TRIAL На trial разрешён только тариф bc-micro
402 ACCOUNT_FROZEN Баланс Вайбкод заморожен, нужно пополнить
403 INFRA_NOT_PERMITTED Инфраструктура отключена на платформе или на портале
403 SERVER_CREATION_DISABLED Создание серверов запрещено политикой портала
403 MAX_SERVERS_REACHED Превышен лимит серверов на API-ключ (по умолчанию 3). Удалите ненужные через `DELETE` или создавайте новый API-ключ
404 NO_CREDENTIALS Провайдер provider не сконфигурирован на платформе
502 PROVIDER_ERROR Облачный провайдер вернул ошибку при создании виртуальной машины. Запись сервера помечается как удалённая, квота не расходуется — можно сразу повторить попытку. Поле message содержит текст от провайдера
429 RATE_LIMITED Превышен общий лимит запросов платформы

Полный список общих ошибок API — Ошибки.

Идемпотентность

Передайте необязательный заголовок Idempotency-Key, чтобы безопасно повторять создание отдельного сервера (standalone). Если ответ на первый запрос потерялся (обрыв сети, таймаут балансировщика), повтор с тем же ключом не создаст второй сервер — вернётся тот же самый сервер, что и в первый раз, со статусом 201 и заголовком ответа Idempotent-Replayed: true.

  • Ключ — строка 1–255 символов из набора [A-Za-z0-9_.:-]. Область действия — ваш API-ключ.
  • При повторе одноразовые SSH-данные не выдаются повторно. В теле ответа ssh.privateKey и ssh.password будут null, а поле note пояснит это. Сохраняйте данные из ответа первого создания.
  • Заголовок работает только для standalone-серверов. На порталах с размещением в галактике корректный ключ игнорируется без ошибки, и защита от повторного создания на этот путь не распространяется.
  • Заголовок несовместим с graduateFrom для выделенного сервера — вернётся 400 IDEMPOTENCY_UNSUPPORTED_WITH_GRADUATION.
Код code Когда
400 INVALID_IDEMPOTENCY_KEY Ключ не проходит валидацию (длина или недопустимые символы)
400 IDEMPOTENCY_UNSUPPORTED_WITH_GRADUATION Ключ вместе с graduateFrom для выделенного сервера
409 IDEMPOTENCY_KEY_ALREADY_USED Ключ уже использован для сервера, который затем был удалён — возьмите новый ключ
409 IDEMPOTENCY_CONCURRENT_RETRY Параллельный запрос с тем же ключом ещё выполняется — повторите чуть позже

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

  • Примеры корректных и некорректных имён по паттерну ^[a-z][a-z0-9-]*$:
    • Правильно: my-app, bot-1, crm-dashboard.
    • Неправильно: My-App (заглавная), bot_1 (подчёркивание), my.app (точка), кириллица.
  • sshPublicKey vs автогенерация. Если передаёте свой публичный ключ — платформа не генерирует приватный, и ssh.privateKey в ответе будет null. Пароль в ssh.password всё равно возвращается.
  • Когда region в ответе отличается от запрошенного. В запрошенной зоне могли кончиться IP-адреса (Address space exhausted) — тогда платформа автоматически пробует следующие зоны в порядке из `GET /v1/infra/providers/:providerId/regions`, и фиксирует это в аудит-логе событием SERVER_ZONE_FALLBACK.
  • Таймаут провижининга — 10 минут. Если status застрял в provisioning дольше, система сама вернёт сервер в sleeping с preventWake: true, после чего остаётся вызвать `DELETE` и создать новый.
  • Рантайм устанавливается на этапе деплоя. Параметр runtime был удалён из POST /v1/infra/servers (вернёт 400 RUNTIME_PARAM_REMOVED). Указывайте runtime в теле `POST /:id/deploy` — он установится между извлечением архива и запуском приложения.

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