Для AI-агентов: markdown этой страницы — /docs-content/infra/servers/create.md индекс документации — /llms.txt
Создать сервер
POST /v1/infra/servers
Создаёт приложение у облачного провайдера. Всегда в режиме Black Hole — iptables блокирует все входящие порты, приложение невидимо из интернета. На части серверов в правилах остаётся одна служебная запись: вход по SSH с единственного адреса платформы, он нужен для переустановки агента.
На портале есть две модели размещения, и от модели зависит, чего ждать после создания:
- Отдельная виртуальная машина (модель по умолчанию). Если под выбранный тариф есть заранее подготовленная машина, платформа настраивает её и только потом отвечает — уже со статусом
runningи с IP-адресом. Иначе платформа отвечает сразу со статусом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, healthPath совпадают по смыслу с телом POST /:id/deploy:
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
source |
object | да (для этого сценария) | Источник кода. source.content — архив приложения в base64, до 96 МБ на тело запроса, то есть около 72 МБ самого архива: base64 тяжелее исходных байт примерно на треть. Тело сверх потолка отклоняется кодом 413 INLINE_SOURCE_TOO_LARGE. Архив крупнее разворачивайте в два шага — сценарий 2 ниже |
runtime |
string | да (если передан source) |
ID рантайма: node20, python311, php83, static и другие. Список — GET /v1/infra/runtimes |
start |
string | да (если передан source) |
Команда запуска приложения, одной строкой. Перенос строки вернёт 400 |
install |
string | нет | Команда установки зависимостей, одной строкой |
env |
object | нет | Переменные окружения { "KEY": "value" }. Подставляются в контейнер при запуске, см. ниже |
port |
number | нет | Порт, на котором приложение слушает |
healthPath |
string | нет | Путь, по которому платформа проверяет готовность приложения внутри контейнера. До 500 символов, начинается со /. По умолчанию /. На создании отдельной виртуальной машины игнорируется |
Других полей деплоя одношаговое создание не принимает: preStart, systemd, serviceName, cleanDeploy, extractTo, hardening, preserveEnv, dataDirs, dataDirsRecursive вернут 400 UNKNOWN_PARAM, а полный список допустимых полей придёт в details.validParams. Эти поля относятся к деплою отдельной виртуальной машины и к galaxy-приложению не применяются — команды, которые нужно выполнить до старта приложения, задавайте в install.
Без полей runtime и start поле source вернёт 400 — оба поля обязательны. На портале без режима галактик новый запрос с source запрещён и вернёт 400 SOURCE_AT_CREATE_GALAXY_ONLY. Повтор, который безопасно сходится на уже создаваемом keyless GALAXY_APP, выполняет это схождение раньше fresh-only отказа: возвращает прежний id с sourceIgnored: true и не запускает вторую сборку.
На пробном периоде сначала прочитайте блоки deployment и capabilities.servers.create из GET /v1/me. Если galaxyApp присутствует, одношаговое создание стоит попробовать, но этот блок отражает сохранённое состояние и не гарантирует успех: текущую вместимость проверяет только POST. Если режима галактик нет, placementNote отсутствует, а запрос с source возвращает 400 SOURCE_AT_CREATE_GALAXY_ONLY. При отсутствии хоста и в режиме отдельной машины двухшаговый путь разрешён, только когда capabilities.servers.create.available равен true; допустимый идентификатор тарифа выберите из capabilities.servers.create.limits.allowedPlans. Если существующий хост непригоден, для нового one-shot запроса дождитесь его восстановления, попросите администратора починить его либо повысьте тариф. Пока available равен false, не переходите на отдельную машину: при включённом контроле trial-ограничений занятый слот даёт 402 TRIAL_PORTAL_LIMIT. После удаления хоста заново прочитайте GET /v1/me и используйте объявленный там двухшаговый путь.
Сценарий 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 обязательны по схеме для создания без source. region необязателен: без него платформа сама подставит регион по умолчанию для выбранного провайдера. Для galaxy-приложения значения информационны — приложение наследует провайдера, план и регион своего хоста.
Если присланное значение расходится с тем, что приложение реально получило, ответ несёт запись в warnings[] рядом с data: она называет разошедшиеся поля, показывает и присланное, и действующее значение и предупреждает, что повторная отправка ничего не изменит. Совпавшие поля не упоминаются, так что корректный вызов остаётся без предупреждения. Нужна машина, у которой провайдера, план и регион выбираете вы, — создавайте её с placement равным dedicated.
Отдельная виртуальная машина вместо galaxy-приложения
Если портал размещает приложения в галактиках, а конкретному приложению нужен свой сервер — передайте поле placement равным dedicated. Пара provider, plan при этом обязательна, region по-прежнему необязателен. Поле source в таком запросе вернёт 400 SOURCE_AT_CREATE_GALAXY_ONLY: отдельная виртуальная машина разворачивается в два шага, код загружают через POST /:id/deploy.
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-small",
"region": "ru-central1-b",
"placement": "dedicated"
}'
В ответе kind равен STANDALONE. Дальше действует порядок для отдельной виртуальной машины: дождаться status: "running" и blackholeStatus: "CONNECTED", затем деплой.
Диагностика и переменные окружения
- Поле
provisionError. Если сборка или запуск упали,GET /v1/infra/servers/:idвернёт вdata.provisionErrorпричину сбоя, а при ошибке сборки образа — ещё и хвост лога сборки Docker. Читайте это поле, чтобы понять причину. - Переменные
envподставляются при запуске. Значения изenvпередаются в контейнер во время запуска черезdocker run --env, а не вшиваются в образ. Вместе с ними платформа передаётPORT(равен полюport, по умолчанию3000): ключPORTзарезервирован, присланный свой перекрывается, и ответ несёт строку вwarnings[]— см. POST /v1/infra/servers/:id/deploy. Поэтому ключи API и секреты изenvне попадают в слои образа.
Поля запроса (body)
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
provider |
string | да | ID провайдера из GET /v1/infra/providers, например bitrix-cloud. 1–50 символов |
name |
string | да | Системное имя сервера — технический идентификатор. 2–63 символа, только строчные латинские буквы, цифры и -, первым символом — буква. Паттерн: ^[a-z][a-z0-9-]*$. Используется в URL поддомена (app-<hex> генерируется отдельно), логах, audit-журнале. Неизменяемый после создания. Для отображаемого имени используйте displayName |
displayName |
string | нет | Отображаемое имя на любом языке (русский, китайский, эмодзи — что угодно). 2–100 символов, без управляющих байтов. Отображается в UI, уведомлениях о падении сервера, security-алертах, биллинг-строках, B24-каталоге. Если не передан — подставится name. Само name остаётся техническим идентификатором, неизменяемым, оно используется в URL поддомена и логах |
description |
string | нет | Описание приложения для карточки каталога Битрикс24, до 500 символов. Переносы строк и табуляции разрешены, прочие управляющие байты запрещены. Значение обрезается по краям. Если не передать — описание останется пустым, задать его позже можно через PATCH /v1/infra/servers/:id |
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 | нет | Публичный идентификатор образа ОС из GET /v1/infra/providers/:providerId/images. Можно передать стабильное семейство, например ubuntu-2404-lts: платформа сама разрешит его в актуальный конкретный образ провайдера. Если поле не передано, разрешается образ провайдера по умолчанию |
sshPublicKey |
string | нет | Ваш SSH-публичный ключ (ssh-rsa …, ssh-ed25519 …, ecdsa-sha2-nistp256/384/521 …, security-keys). До 8192 символов. Платформа ставит его рядом со своим ключом: на заранее подготовленную машину — до ответа о создании, на создаваемую с нуля — во время подготовки |
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 для выделенного сервера несовместим — см. Идемпотентность |
runMode |
object | нет | Режим работы, в котором сервер рождается. Та же форма, что у PATCH /:id/run-mode: {"mode": "ALWAYS"}, {"mode": "IDLE", "idleMinutes": 15|30|60|240} или {"mode": "SCHEDULE", "scheduleId": "…"}. Разбор идёт по полю mode, поэтому лишнее поле рядом с режимом отвергается, а не выбрасывается молча. Отказ приходит ДО создания машины, поэтому неудачный запрос не оставляет сервер. Без блока сервер рождается на расписании, которое администратор портала отметил для новых машин, — Отметить расписание по умолчанию. Без такой отметки действует таймаут авто-сна по умолчанию из «Известных особенностей» |
Примечание: для модели отдельной виртуальной машины параметр
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 | "running", если платформа взяла заранее подготовленную машину. Иначе "provisioning" — ждите "running" через 1–3 минуты. При повторе с тем же Idempotency-Key — статус сервера на момент повтора. В reuse-ответе (reused: true) это статус существующего сервера и он может быть любым, в том числе сразу "running" — тогда ожидание "running" ничего не проверяет |
data.provider |
string | Эхо переданного provider. Исключение — galaxy-приложение (createdVia: "galaxy"): возвращается провайдер хоста-носителя, а не запрошенный |
data.name |
string | Системное имя сервера. Эхо переданного name при создании нового. В reuse-ответе — имя существующего сервера, а запрошенное вами лежит в data.requestedName |
data.kind |
string | Тип сервера, всегда: STANDALONE или GALAXY_APP |
data.galaxyId |
string | Только для galaxy-ветки — ID хоста-галактики. В standalone-ответе ключ отсутствует |
data.displayName |
string | null | Отображаемое имя. Если при создании не передавали displayName — будет равно name |
data.description |
string | null | Эхо переданного description. Ключ есть только в ответе для отдельной виртуальной машины. Для galaxy-приложения, где createdVia равно galaxy, ключа в ответе нет, хотя описание сохраняется — прочитайте его через GET /v1/infra/servers/:id |
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. null — при повторе с тем же Idempotency-Key, см. Идемпотентность. В ответе переиспользования и у galaxy-приложения null весь блок ssh. Сохраняйте сразу |
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" для вызовов из личного кабинета. В reuse-ответе — значение существующего сервера, поэтому на ответ v1-создания может прийти "ui" |
data.subdomain |
string | Субдомен для приложения, например app-92fb1c34. Используется в appUrl |
data.blackholeStatus |
string | Состояние туннеля агента. У машины, созданной с нуля, — "NONE", пока агент не подключится, затем "CONNECTED". У заранее подготовленной машины ответ несёт "NONE" или уже "CONNECTED" |
data.accessPolicy |
string | Политика доступа к приложению. По умолчанию "OWNER_ONLY" — только владелец ключа |
data.sleepAfterMinutes |
number | null | Сохранённый таймаут авто-сна в минутах. Поле есть в каждом успешном 201-ответе — для новой отдельной машины и galaxy-приложения, а также при reuse и idempotency replay. null — сохранённый выбор «Никогда»: без действующего расписания авто-сон отключён, а с ним применяется платформенный таймаут после окна |
data.runtimeId |
string | null | Всегда null при создании. Заполняется при деплое с runtime |
data.runtimeStatus |
string | null | Устаревшее поле, оставлено для совместимости. Для серверов, созданных после 2026-04-25, всегда null. Готовность рантайма после деплоя определяет успех шага runtime в ответе POST /:id/deploy, а не это поле |
data.appUrl |
string | null | HTTPS-адрес приложения: https://{subdomain}.vibecode.bitrix24.tech |
data.createdAt |
string (ISO 8601) | Момент создания |
warnings |
array<string> | Рядом с data, не внутри. Приходит, только если есть что сказать: например, displayName или description потеряли не-ASCII символы по дороге (типичный случай — Windows PowerShell без явной сериализации в UTF-8). Сервер при этом создаётся, а обе строки уезжают в карточку каталога Битрикс24 как есть |
data.sleepAfterMinutes — поле ответа, а не параметр создания. Чтобы изменить сохранённую политику после создания отдельной машины, вызовите PATCH /v1/infra/servers/:id/sleep. Не подставляйте в это поле ожидаемый дефолт: при reuse или idempotency replay ответ возвращает значение уже существующей записи, в том числе null или историческое числовое значение. Поле не является вычисленным фактическим таймаутом: при null и действующем расписании пробуждения применяется платформенный запас после окна, по умолчанию 15 минут.
Пример ответа
Отдельная виртуальная машина, созданная с нуля:
{
"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",
"sleepAfterMinutes": 60,
"runtimeId": null,
"runtimeStatus": null,
"appUrl": "https://app-92fb1c34.vibecode.bitrix24.tech",
"createdAt": "2026-04-22T10:50:11.477Z"
}
}
У заранее подготовленной машины в этом ответе status равен running, а ip заполнен.
Galaxy-приложение по сценарию 1 — source передан, сборка идёт в фоне. Поле ssh равно null. Поля 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",
"sleepAfterMinutes": 60,
"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",
"sleepAfterMinutes": 60,
"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 содержит конкретную причину. Если на портале с размещением в галактике не передано ни source, ни пара обязательных полей provider + plan — добавляется объект error.hint (см. ниже) |
| 400 | SOURCE_AT_CREATE_GALAXY_ONLY |
Запрос с source не удалось разместить в галактике. Это происходит при выключенном режиме галактик, вместе с placement: "dedicated" или когда фактическая проверка не нашла пригодный хост. Следуйте error.hint и capabilities.servers.create: без хоста галактики двухшаговый путь доступен только при available: true; при существующем хосте и available: false подсказка запрещает его, потому что при включённом контроле trial-ограничений создание отдельной машины вернёт 402 TRIAL_PORTAL_LIMIT |
| 400 | GALAXY_SOURCE_URL_NOT_ALLOWED |
Ссылка в source.url не прошла проверку до отправки на хост галактики. Причины: адрес ведёт не в хранилище исходников платформы, значение не является абсолютным URL, схема не http и не https, адрес ведёт не в публичную сеть — на локальный, внутренний или служебный узел. Текст ответа называет сработавшее правило, а для стороннего адреса подсказывает замену — сохранить архив версией и выложить её вторым шагом через выкладку кода. Та же проверка стоит и на самой выкладке |
| 400 | RUNTIME_PARAM_REMOVED |
Параметр runtime передан без source. Указывайте рантайм в POST /:id/deploy либо передайте runtime, start и source вместе в этом же запросе. На портале с размещением в галактике добавляется объект error.hint (см. ниже) |
| 400 | UNKNOWN_PARAM |
В теле есть неизвестное поле (например deployMode вместо placement). details.unknownFields перечисляет лишние поля, details.suggestions подсказывает правильное имя, details.validParams — полный список допустимых полей |
| 400 | WORK_SCHEDULE_NOT_FOUND |
В блоке runMode назван идентификатор расписания, которого в вашем аккаунте нет. Машина при этом не создаётся |
| 400 | WORK_SCHEDULE_EMPTY |
У названного расписания нет ни одного окна — на таком сервер не работал бы никогда. Машина не создаётся |
| 400 | RUN_MODE_UNAVAILABLE |
Режимы работы для вашего аккаунта ещё не включены. Машина не создаётся |
| 400 | INVALID_PLAN |
Тариф из поля plan отсутствует в каталоге провайдера. Список — GET /v1/infra/providers/:providerId/plans |
| 400 | INVALID_REGION |
Присланный region отсутствует в каталоге провайдера. Список — GET /v1/infra/providers/:providerId/regions. Второй случай: region не передан, а у провайдера нет ни одного региона — тогда message называет провайдера, и подставлять значение по умолчанию платформе не из чего |
| 401 | MISSING_API_KEY |
Не передан заголовок X-Api-Key |
| 401 | INVALID_API_KEY |
Ключ не опознан: такой строки на платформе нет |
| 401 | UNAUTHENTICATED |
Ключ авторизации (vibe_app_) прислан без заголовка Authorization: Bearer — создание сервера проходит тарифную проверку, которой нужно знать, кто именно создаёт сервер. Поле error.hint называет следующий шаг: пройти OAuth-авторизацию или взять личный API-ключ (vibe_api_), которому сессия не нужна. Порядок — Ключи и авторизация |
| 402 | MARKETPLACE_REQUIRED |
На портале нет активной подписки, а доступ к платформе здесь открывает именно она. Если у российского облачного портала прочитан бесплатный тариф Битрикс24, userMessage и подсказка называют оба условия: платный тариф Битрикс24 и подписку BitrixGPT + Маркетплейс; касса портала соберёт их в одну корзину. Для демо-тарифа и непрочитанного тарифа эта пара не применяется. Пути решения — в error.alternatives, требуемые тарифы и ссылка на оформление — в error.details. Какой путь доступа действует в регионе портала — Тариф и доступ |
| 402 | BY_PAID_ONLY |
Доступ открывает платный или демо-тариф Битрикс24. Открывает его и платная подписка Битрикс24 Маркет Плюс — в Беларуси она продаётся |
| 402 | KZ_PAID_ONLY |
Регион портала открывает доступ по тарифу: платный или демо-тариф Битрикс24, подписка в регионе не продаётся |
| 402 | UZ_PAID_ONLY |
То же для региона UZ: платный или демо-тариф Битрикс24, подписка в регионе не продаётся |
| 402 | COMMERCIAL_PLAN_REQUIRED |
Платформа не нашла запись портала, к которому привязан ключ, поэтому не может проверить доступ |
| 402 | TRIAL_PORTAL_LIMIT |
Превышена квота серверов портала на trial error.retryable: false; не повторяйте создание с другими именами, ключами, провайдерами или планами. Проверьте deployment.standalone.reuseTarget в GET /v1/me, иначе следуйте userMessage и alternatives. |
| 402 | PLAN_NOT_ALLOWED_ON_TRIAL |
Запрошенный тариф недоступен на пробном периоде. Набор разрешённых тарифов читайте из error.details.allowedPlans — он различается, поэтому не зашивайте его в код. Поле error.details.requestedPlan, когда оно есть, повторяет отклонённый тариф |
| 402 | GALAXY_NOT_ON_TRIAL |
Хост Galaxy нельзя создать на пробном доступе. Получите полный доступ по модели региона; для пробного развёртывания используйте отдельный сервер с планом из capabilities.servers.create.limits.allowedPlans ответа GET /v1/me в пределах оставшейся квоты. Контейнер GALAXY_APP на существующем подходящем хосте этим отказом не запрещён |
| 402 | ACCOUNT_FROZEN |
Баланс Вайбкод заморожен, нужно пополнить |
| 403 | PORTAL_SUBSCRIPTION_UNREADABLE |
Состояние подписки аккаунта прочитать не удалось: ключу разработчика не хватает прав на чтение лицензии. Покупка такой отказ не снимает, поэтому поле error.details.requiredTariffs пустое. Переподключите приложение под главным администратором аккаунта, чтобы ключ получил нужные права. Код 402 MARKETPLACE_REQUIRED означает другое: подписка прочитана, и её нет |
| 403 | PORTAL_TARIFF_UNREADABLE |
Тариф аккаунта прочитать не удалось, поэтому какого тарифа не хватает, ответ не называет: поле error.details.requiredTariffs пустое, а кнопка ведёт в поддержку. Покупка тарифа отказ не снимает |
| 403 | INFRA_NOT_PERMITTED |
Инфраструктура отключена на платформе или на портале |
| 403 | SERVER_CREATION_DISABLED |
Создание серверов запрещено политикой портала |
| 403 | MAX_SERVERS_REACHED |
Превышен лимит серверов на API-ключ. Удалите ненужные через DELETE или создавайте новый API-ключ |
| 403 | WRITE_BLOCKED_READONLY_KEY |
У ключа режим «только чтение», а создание сервера — операция записи. Переключите ключ на чтение и запись, порядок — Режим доступа |
| 403 | INFRA_SCOPE_REQUIRED |
У ключа нет скоупа vibe:infra — управление инфраструктурой недоступно. Добавьте скоуп или используйте ключ с правами на инфраструктуру |
| 403 | INFRA_FORBIDDEN_FOR_COWORK_KEY |
Вызов сделан ключом Cowork/Code — такой ключ работает только с данными, изменяющие операции ему закрыты. Что делать — Проектный ключ для деплоя |
| 404 | NO_CREDENTIALS |
Провайдер provider не сконфигурирован на платформе |
| 409 | GALAXY_FULL |
Портал размещает приложения в галактиках, и места под ещё одно приложение нет. Прежде чем отказать, платформа пробует разместить приложение на другой галактике, поэтому этот ответ означает, что места действительно нет. Удалите ненужное galaxy-приложение либо запросите отдельную машину — поле placement со значением dedicated |
| 409 | REISSUE_IN_PROGRESS |
Ключ приложения или его привязка к серверу заняты перевыпуском ключа, доставкой секретов или удалением либо изменились во время запроса. Новая машина не создана; повторите запрос чуть позже |
| 409 | APPLICATION_KEY_RECOVERY_REQUIRED |
Замена API-ключа, которым сделан запрос, не завершена: его перевыпуск закончился ответом 500 или ещё не закончился. Сервер не создан: он оказался бы на ключе с незавершённой заменой. Порядок действий — Менеджмент-ключи, раздел о перевыпуске ключа |
| 409 | APPLICATION_REUSE_CONFLICT |
Пока платформа подбирала существующий сервер для повторного использования, привязку сервера к приложению изменил параллельный запрос. error.retryable: true, повторите запрос |
| 413 | INLINE_SOURCE_TOO_LARGE |
Тело со встроенным source.content больше 96 МБ, то есть около 72 МБ самого архива. Решение принимается по заголовку Content-Length до чтения тела, поэтому отказ детерминированный — то же тело повторной отправкой не пройдёт. Трафик это не экономит: платформа принимает тело целиком, и отказ приходит после того, как загрузка закончилась. В error.hint приходят четыре строки — reason, recovery, recoveryAction и note: рецепт здесь — создать сервер без source, сохранить архив версией на полученном идентификаторе и развернуть её по {"source": {"versionId": "vN"}}, потому что все адреса версионного пути строятся по идентификатору сервера, которого до создания ещё нет |
| 429 | RATE_LIMITED |
Превышен общий лимит запросов платформы |
| 429 | DEPLOY_BACKEND_BUSY |
Запрос нёс архив в source.content, а на бэкенде уже идёт предельное число таких же тяжёлых запросов (общий счётчик с POST /:id/deploy и POST /:id/upload). В ответе заголовок Retry-After: 30 — повторите через полминуты. Чтобы не зависеть от очереди, создайте сервер без source, а код загрузите отдельным запросом со ссылкой {source: {url: ...}} — у этого пути ограничения на одновременность нет |
| 502 | PROVIDER_ERROR |
Облачный провайдер вернул ошибку при создании виртуальной машины. Без заголовка Idempotency-Key запись сервера помечается удалённой, квота не расходуется — можно сразу повторить попытку. Если запрос шёл с этим заголовком, найдите сервер по имени из запроса в списке серверов. Запись со статусом error значит, что облако могло создать машину, хотя ответ потерялся: повтор с тем же Idempotency-Key вернёт эту запись, а не создаст вторую машину — см. Идемпотентность. Записи нет — повторите запрос. Поле message содержит локализованное описание сбоя и код инцидента — сырой ответ провайдера в тело не попадает, он остаётся в логах платформы. Назовите код инцидента поддержке |
| 503 | POOL_EXHAUSTED |
Исход создания неизвестен: ошибка базы могла возникнуть после начала операции. Выдержите Retry-After, проверьте список серверов и повторяйте создание только если убедились, что сервер не появился |
Полный список общих ошибок API — Ошибки.
Подсказка `error.hint`
На портале с размещением в галактике ошибки INVALID_REQUEST и RUNTIME_PARAM_REMOVED дополняются объектом error.hint. Он называет причину отказа и даёт готовое тело запроса. Условие у двух кодов разное. У INVALID_REQUEST подсказка приходит, когда в теле нет ни source, ни обязательной пары provider + plan. Поле region можно опустить, платформа подставит регион провайдера по умолчанию. У RUNTIME_PARAM_REMOVED подсказка приходит, когда передан runtime без source, причём provider и plan при этом могут быть заполнены. На портале с отдельными виртуальными машинами подсказки нет ни в одном из случаев.
На пробном доступе эти ранние подсказки используют ту же предварительную оценку, что и GET /v1/me. Подходящий по сохранённому состоянию хост даёт рекомендацию попробовать одношаговый запрос. При отсутствии хоста двухшаговый путь разрешён, только когда capabilities.servers.create.available равен true. Если существующий хост непригоден, для нового one-shot запроса нужно дождаться восстановления, починить хост либо повысить тариф; после удаления хоста следует заново прочитать GET /v1/me и перейти на объявленный там двухшаговый путь. Подсказка носит рекомендательный характер: окончательное решение принимает POST.
Если запрос с source уже дошёл до фактической проверки и вернул SOURCE_AT_CREATE_GALAXY_ONLY, его error.hint учитывает результат этой проверки. При существующем хосте на пробном доступе подсказка запрещает двухшаговый путь, когда capabilities.servers.create.available равен false: при включённом контроле trial-ограничений он вернёт 402 TRIAL_PORTAL_LIMIT. При отсутствии хоста она разрешает создать отдельную машину без source, а затем выполнить деплой только после положительной проверки этого слота.
Не путайте с data.hint из успешного ответа: там строка про следующий шаг после создания приложения по сценарию 2, здесь — объект внутри error.
| Поле | Тип | Описание |
|---|---|---|
error.hint.reason |
string | Почему запрос отклонён |
error.hint.recovery |
string | Что изменить в запросе, чтобы он прошёл |
error.hint.example |
object | Готовое тело запроса, которое можно взять за основу |
{
"success": false,
"error": {
"code": "INVALID_REQUEST",
"message": "provider: Required; plan: Required",
"hint": {
"reason": "This portal places new apps on shared galaxy hosts, and the request lacked `source` and the required provider/plan pair. `region` is optional and defaults to the provider's region.",
"recovery": "RECOMMENDED: create-and-deploy in ONE call — POST /v1/infra/servers { name, source: { content }, runtime, start }; OMIT provider/plan/region. Two-step also works: pass provider and plan (region is optional and defaults to the provider's region) to create an empty slot, then POST /v1/infra/servers/:id/deploy with the source. See GET /v1/me -> deployment.galaxyApp.checklist. For a deliberate dedicated standalone VM pass placement: \"dedicated\" with provider and plan; region is optional.",
"example": {
"name": "<slug>",
"source": { "content": "<base64 gzip-tar of the app>" },
"runtime": "node20",
"start": "node server.js",
"port": 3000
}
}
}
}
Если в теле передан placement: "dedicated", подсказка другая: она предлагает добавить обязательные provider и plan, сохранив выделенный сервер, а region оставить пустым для выбора региона по умолчанию, а не переводить приложение в контейнер галактики.
Переиспользование сервера
POST /v1/infra/servers не создаёт второй сервер и возвращает существующий в двух случаях. Первый — ключ вызова принадлежит карточке из раздела «Приложения», к которой уже привязан живой сервер. Второй — тот же API-ключ уже создаёт GALAXY_APP в статусе provisioning, у сервера есть живая keyless-карточка, раздел «Приложения» виден порталу, а родительский Galaxy-host по-прежнему жив: не удалён, имеет тип GALAXY и не находится в error/deleted. Второй случай действует при любом размещении, кроме placement: "dedicated", даже если после первого запроса настройки размещения переключились на отдельные машины, и проверяется до fresh-only отказа для тела с source. После выхода такого приложения из provisioning следующий create снова может создать новый сервер.
Имя, которое вы передали в name, в этом решении не участвует — повтор платформа определяет по вызывающему ключу и состоянию сервера, а не по имени.
В reuse-ответе (reused: true) все поля data описывают существующий сервер, а не ваш запрос — status, provider, plan, region, image, createdVia, createdAt относятся к нему. Статус может быть любым, поэтому «дождаться running» не является проверкой того, что сервер ваш. Проверка — это reused и пара name ⊕ requestedName.
Ответ на такой запрос всегда несёт data.reused: true и рядом с data — массив warnings минимум с одной записью. Сравните data.name с data.requestedName: они различаются, если сервер приложения был создан раньше и под другим именем.
| Поле | Тип | Когда |
|---|---|---|
data.reused |
boolean | Всегда на таком ответе. Новый сервер не создан |
data.reusedReason |
string | APPLICATION_ALREADY_HAS_SERVER |
data.requestedName |
string | Эхо вашего name — всегда, даже если совпадает с именем существующего сервера |
data.sourceIgnored |
boolean | Переданный source не развёрнут этим запросом |
data.deploying |
boolean | Переданный source собирается на контейнер приложения прямо сейчас |
data.metaIgnored |
boolean | Переданные displayName/description не применены |
warnings |
array | Рядом с data, не внутри. Минимум одна запись |
Что делать перед деплоем. Запросите GET /v1/infra/servers/:id и посмотрите, что на сервере уже развёрнуто. Деплой заменяет работающий код, он не добавляет к нему. Если это не тот сервер, который вы имели в виду, остановитесь и спросите пользователя, с каким приложением должен работать этот ключ.
Про переданный source. Обычное переиспользование разворачивает исходники в galaxy-приложение только тогда, когда контейнера ещё нет или прошлая сборка упала — в ответе будет deploying: true, опрашивайте GET /v1/infra/servers/:id до running. При схождении на keyless-приложении в provisioning этот запрос никогда не запускает вторую сборку и отвечает sourceIgnored: true. Если ранняя сборка уже идёт, data.next отсутствует: не вызывайте deploy параллельно, дождитесь выхода сервера из provisioning и только потом разворачивайте проигнорированный source через POST /v1/infra/servers/:id/deploy, если замена всё ещё нужна. Для припаркованного приложения без активной сборки ответ сохраняет next: "deploy".
Про переданные displayName и description. Переиспользование никогда не переименовывает сервер, который отдаёт: у него остаются собственные имя и описание, а переданные вами значения отбрасываются — в ответе это видно по data.metaIgnored: true и отдельному предупреждению. Переименуйте осознанно через PATCH /v1/infra/servers/:id, убедившись, что сервер тот.
Про data.next. В reuse-ответе поле приходит только для припаркованного galaxy-приложения без контейнера и без активной сборки, которое прикреплено к galaxy-хосту. Во время уже идущей сборки next намеренно отсутствует: опрашивайте сервер, не запускайте конкурирующий deploy. Если приложение откреплено от хоста или сервер уже может выполнять код, next тоже не приходит. Не трактуйте отсутствие next как ошибку или разрешение перезаписать код.
Как получить для приложения другой сервер. Отдельного вызова, меняющего привязку, нет. Если нужна отдельная виртуальная машина и привязку трогать не надо — создайте её с placement: "dedicated": переиспользование не сработает, но и к приложению новый сервер привязан не будет. Если нужно именно сменить привязанный сервер — удалите текущий через DELETE /v1/infra/servers/:id, и следующий POST /v1/infra/servers тем же ключом снимет устаревшую привязку и привяжет вновь созданный сервер. Удаление необратимо и уничтожает всё, что развёрнуто на сервере, — сначала убедитесь по GET /v1/infra/servers/:id, что это не чужая работа.
Создание с placement: "dedicated" переиспользование не затрагивает.
Идемпотентность
Передайте необязательный заголовок Idempotency-Key, чтобы безопасно повторять зарегистрированное создание standalone-сервера или Galaxy-приложения. Если ответ на первый запрос потерялся (обрыв сети, таймаут балансировщика), повтор с тем же ключом не создаст второй ресурс — вернётся тот же сервер: HTTP-код 201 и заголовок ответа Idempotent-Replayed: true, а поля описывают его состояние на момент повтора.
Повтор возможен в течение 15 минут с момента резервирования ключа (для прежних standalone-записей — создания сервера). После этого окна тот же ключ сервер уже не вернёт: запрос пройдёт как новое создание со всеми проверками прав — и либо получит обычный отказ по правам (402 / 403), либо 409 IDEMPOTENCY_KEY_ALREADY_USED. Если сервер не удаляли, он никуда не делся — текст ответа это скажет.
Важно: повторяйте ТЕМ ЖЕ ключом, а не новым. Для standalone-создания тот же Idempotency-Key вторую машину не создаст: он вернёт либо сам сервер, либо 409 с ответом о его судьбе. Новый Idempotency-Key сам по себе не является повтором прежнего запроса, но обычные правила переиспользования всё равно действуют. В частности, запрос тем же API-ключом при живом keyless GALAXY_APP в provisioning вернёт его с reused: true при любом недедицированном размещении. Поэтому новый ключ не означает, что обязательно будет создан новый сервер: проверяйте data.id, data.reused и GET /v1/infra/servers.
- Ключ — строка 1–255 символов из набора
[A-Za-z0-9_.:-]. Область действия — ваш API-ключ. - При повторе standalone одноразовые SSH-данные не выдаются повторно. В теле ответа
ssh.privateKeyиssh.passwordбудутnull, а полеnoteпояснит это. Сохраняйте данные из ответа первого создания. УGALAXY_APPсвоих SSH-данных нет:sshравенnull, полеnoteне требуется. - Galaxy-создание и переиспользование защищены после включения новой защиты. Ключ резервируется независимо от строки ресурса: несколько разных ключей могут вернуть один переиспользованный слот. Новые fresh, revived и reused результаты запоминают точный
applicationId; если фоновая привязка fresh/revived-сервера находит уже созданную для этого ключа карточку, запись атомарно переключается с предварительно зарезервированного id на id именно этой карточки, после чего он фиксирован. Повтор того же ключа в течение 15 минут принимает только эту точную карточку, а не любую более позднюю карточку того же владельца на том же сервере. Платформа также заново проверяет владельца и портал обеих строк и живой Galaxy-host. Если записанная карточка была удалена, отвязана или заменена, владение изменилось либо host удалён/перешёл вerror/deleted, ключ остаётся израсходованным, но ответ —409 IDEMPOTENCY_KEY_ALREADY_USEDбезdataи прежнего id; в новое создание запрос не проваливается. UUID-only записи до включения защиты остаются legacy. После окна действуют обычные проверки и отказ занятого ключа. До активации первое galaxy-создание по-прежнему не резервирует ключ; уже записанные ключи читаются и после выключения защиты. Старые galaxy-создания без записи ключа восстановить нельзя. - Заголовок несовместим с
graduateFromдля выделенного сервера — вернётся400 IDEMPOTENCY_UNSUPPORTED_WITH_GRADUATION. - Повтор записанного ключа не запускает сборку повторно. После ошибки сборки используйте явный deploy. Fresh/revived Galaxy-результат повторяется обычным create-ответом; semantic reuse снова содержит
reused,reusedReason,requestedName,sourceIgnored/metaIgnored,warnings,hintи применимыйnext. Эти поля учитывают текущее валидированное тело повтора, но новая запись reuse отдельно помнит, принял ли исходный запрос свойsource: пока начатая им сборка активна, повтор отвечаетdeploying: trueбезsourceIgnoredи безnext; после её завершения source также не объявляется проигнорированным и автоматически повторно не разворачивается. У прежней записи формата v1 этого признака нет, поэтому повтор не выдумывает исход: не отдаётsourceIgnoredилиnext, а просит сначала проверить сервер и логи и не запускать deploy автоматически. Запрос с новым ключом проходит обычные правила reuse: пустой или ошибочный слот может начать сборку, а схождение на keyless-приложении с уже активной сборкой не запускает вторую и может вернутьsourceIgnored: true.
| Код | code |
Когда |
|---|---|---|
| 400 | INVALID_IDEMPOTENCY_KEY |
Ключ не проходит валидацию (длина или недопустимые символы) |
| 400 | IDEMPOTENCY_UNSUPPORTED_WITH_GRADUATION |
Ключ вместе с graduateFrom для выделенного сервера |
| 409 | IDEMPOTENCY_KEY_ALREADY_USED |
Ключ израсходован. Текст ответа различает удалённый сервер, повтор позже 15-минутного окна и недоступный прежний результат — в том числе удаление, отвязку или замену точной записанной Galaxy-карточки. В последнем случае ответ не содержит data и прежнего идентификатора и не начинает новое создание. Тот же код приходит и на galaxy-пути, если ключ уже израсходован |
| 409 | IDEMPOTENCY_CONCURRENT_RETRY |
Параллельный запрос с тем же ключом ещё выполняется — повторите чуть позже |
Известные особенности
- Примеры корректных и некорректных имён по паттерну
^[a-z][a-z0-9-]*$:- Правильно:
my-app,bot-1,crm-dashboard. - Неправильно:
My-App(заглавная),bot_1(подчёркивание),my.app(точка),кириллица.
- Правильно:
- Свой
sshPublicKeyна заранее подготовленной машине. Если первый ответ создания пришёл со статусомrunningи безreused: true, платформа выдала заранее подготовленную машину. Если вы передалиsshPublicKey, платформа установила его до ответа: для входа по SSH используйте свой ключ или ключ изssh.privateKey. Смотрите именно первый ответ: повтор с тем жеIdempotency-Keyпоказывает статус сервера на момент повтора. - Когда
regionв ответе отличается от запрошенного. В запрошенной зоне могли кончиться IP-адреса (Address space exhausted) — тогда платформа автоматически пробует следующие зоны в порядке изGET /v1/infra/providers/:providerId/regions, и фиксирует это в аудит-логе событиемSERVER_ZONE_FALLBACK. - Таймаут провижининга — 15 минут. Если
statusдержится вprovisioningдольше, платформа переводит сервер вerrorи заполняетprovisionErrorиprovisionErrorCode. Дальше остаётся вызватьDELETEи создать новый. - Новая обычная машина получает таймаут авто-сна 60 минут. Фактическое сохранённое значение приходит уже в
data.sleepAfterMinutesответа создания и затем вGET /v1/infra/servers/:id. При reuse и idempotency replay это значение существующей записи, поэтому оно может бытьnullили отличаться от 60. Сервер, родившийся на расписании, отмеченном для новых машин, это значение хранит, но оно не действует, пока расписание назначено, — режим виден в поляхrunModeиworkScheduleтого жеGET. Входящие HTTP-запросы и активность по SSH сбрасывают таймер, а cron, фоновые процессы и собственные исходящие запросы приложения — нет. Допустимые значения и осознанное отключение авто-сна черезPATCHсnull— Настроить авто-сон. - Рантайм устанавливается на этапе деплоя. Параметр
runtimeбезsourceвPOST /v1/infra/serversне принимается (вернёт400 RUNTIME_PARAM_REMOVED). Указывайтеruntimeв телеPOST /:id/deploy— для отдельной виртуальной машины начало конвейера идёт в порядкеruntime → stop_existing → clean → download → install. Вместе сsourceрантайм принимается и обязателен: это одношаговое создание galaxy-приложения, гдеruntimeиstartидут в том же запросе. - Кириллица в
displayNameиdescriptionиз Windows PowerShell. Отправленная без явной сериализации в UTF-8, она сохраняется знаками вопроса (?): байты теряются на стороне клиента, до отправки запроса. Готовый вызов сUTF8.GetBytes— Windows / PowerShell и UTF-8.