Серверы
CRUD-операции для серверов: создание нового сервера, список своих серверов, детали одного сервера по ID, удаление. Созданный сервер всегда находится в режиме Black Hole — невидим из интернета, доступ к приложению только через HTTPS-субдомен.
Скоуп: vibe:infra
Создать сервер
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". Отдельный вызов загрузки кода не нужен.
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.
# Шаг 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 — личный ключ
# 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-приложение
# 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 — личный ключ
// 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-приложение
// 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) | Момент создания |
Пример ответа
Отдельная виртуальная машина:
{
"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 нет:
{
"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:
{
"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:
{
"success": true,
"data": {
"id": "7c2b1f08-3a4d-4e91-9b6c-2f5e8a1d0c33",
"status": "error",
"createdVia": "galaxy",
"provisionError": "Docker build failed: npm ci exited with code 1"
}
}
Пример ответа при ошибке
400 — нарушена валидация (имя начинается с заглавной):
{
"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(точка),кириллица.
- Правильно:
sshPublicKeyvs автогенерация. Если передаёте свой публичный ключ — платформа не генерирует приватный, и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` — он установится между извлечением архива и запуском приложения.
Смотрите также
- Провайдеры и каталоги — откуда брать
provider,plan,region,image. - Получить сервер — опрос статуса до готовности.
- Список серверов — чтобы увидеть все свои.
- Удалить сервер — вернуть квоту.
- Deploy API — следующий шаг после создания.
- Полный деплой приложения — загрузка кода в galaxy-приложение по сценарию 2.
- Список рантаймов — допустимые значения
runtime. - Тариф и доступ — когда и почему возникают 402-ошибки.