#Выполнить команду

POST /v1/infra/servers/:id/exec

Выполняет shell-команду на BLACKHOLE-сервере через агент туннеля. Полный стандартный вывод (stdout), поток ошибок (stderr) и код возврата передаются клиенту. По умолчанию ответ — JSON после завершения команды (удобно для AI-агентов и скриптов). Если нужен построчный прогресс — передайте ?stream=true и читайте SSE-события stdout/stderr/exit.

Для AI-агентов и MCP-клиентов обязательно используйте JSON-режим (без ?stream=true) — SSE они разбирать не умеют.

#Параметры

Параметр В Тип Обяз. По умолч. Описание
id path string (UUID) да ID BLACKHOLE-сервера, status: running, blackholeStatus: CONNECTED
stream query string нет false true — SSE-режим; иначе — JSON-ответ

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

Поле Тип Обяз. Описание
command string да Shell-команда. 1–10 000 символов
timeout number нет Таймаут выполнения в секундах: 1–600. По умолчанию 300
workdir string нет Рабочая директория. До 500 символов
env object нет Переменные окружения: { "KEY": "value" }. Только строковые значения

#Примеры

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

Terminal
curl -X POST "https://vibecode.bitrix24.tech/v1/infra/servers/SERVER_ID/exec?stream=false" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"command": "ls -la /opt/app", "timeout": 30}'

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

Terminal
curl -X POST "https://vibecode.bitrix24.tech/v1/infra/servers/SERVER_ID/exec?stream=false" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"command": "npm ci --production", "workdir": "/opt/app", "timeout": 180}'

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

javascript
const res = await fetch(
  `https://vibecode.bitrix24.tech/v1/infra/servers/${serverId}/exec?stream=false`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      command: 'node -v',
      timeout: 10,
    }),
  }
)
const { data } = await res.json()
console.log(`exit ${data.exitCode} за ${data.duration}s:\n${data.stdout}`)

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

javascript
// Команда с переменными окружения и рабочей директорией
const res = await fetch(
  `https://vibecode.bitrix24.tech/v1/infra/servers/${serverId}/exec?stream=false`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      command: 'npx tsx scripts/seed.ts',
      workdir: '/opt/app',
      env: { DATABASE_URL: 'postgresql://localhost/mydb' },
      timeout: 60,
    }),
  }
)

#Поля ответа

Поле Тип Описание
success boolean true если команда выполнилась (включая ненулевой exitCode)
data.exitCode number Код возврата процесса
data.stdout string Стандартный вывод команды
data.stderr string Поток ошибок команды
data.duration number Время выполнения в секундах
data.truncated boolean true если stdout/stderr обрезаны по размеру (5 МБ на поток)

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

JSON
{
  "success": true,
  "data": {
    "exitCode": 0,
    "stdout": "Linux epd65hdv07p8g89c0c06 6.8.0-107-generic #107-Ubuntu SMP PREEMPT_DYNAMIC Fri Mar 13 19:51:50 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux\n",
    "stderr": "",
    "duration": 5,
    "truncated": false
  }
}

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

409 — на сервере уже выполняется другая операция:

JSON
{
  "success": false,
  "error": {
    "code": "EXEC_BUSY",
    "message": "Another operation is running on this server"
  }
}

#Ошибки

HTTP Код Описание
400 VALIDATION_ERROR Нарушена схема запроса (пустая команда, неверный таймаут, слишком длинные поля)
400 NOT_BLACKHOLE Сервер в режиме OPEN — Deploy API недоступен
401 MISSING_API_KEY Не передан заголовок X-Api-Key
401 INVALID_API_KEY Неверный или просроченный API-ключ
404 NOT_FOUND Сервер не существует, удалён или принадлежит другому API-ключу
409 EXEC_BUSY На сервере уже выполняется другая /exec или /deploy. Подождите или снимите лок через `/lock`
409 AGENT_NOT_CONNECTED Агент туннеля не в статусе CONNECTED — попробуйте `/repair`
429 RATE_LIMIT_EXCEEDED Превышен лимит 10 операций в минуту на сервер
500 EXEC_FAILED Ошибка выполнения на агенте
502 GATEWAY_ERROR Gateway вернул ошибку при связи с агентом
504 EXEC_TIMEOUT Превышен timeout (или стандартные 300 секунд). Агент убивает процесс

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

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

  • Блокировка на уровне сервера. Пока идёт /exec или /deploy, второй такой вызов вернёт 409 EXEC_BUSY. Если клиент оборвал соединение и не дождался таймаута, снимите зависший лок через `DELETE /lock`.
  • Максимальный размер stdout/stderr — 5 МБ на поток. Если вывод команды больше, приходит truncated: true и хвост обрезается. Команда при этом отработала, exitCode корректный. Для большого вывода перенаправляйте в файл: command: "my-cmd > /opt/app/output.log 2>&1" и потом читайте через /exec cat /opt/app/output.log.
  • .env из /deploy не подхватывается автоматически. Systemd подгрузит .env при старте сервиса, но не для разовых команд через /exec. Если нужны DATABASE_URL / API-ключи — передавайте в поле env: { env: { DATABASE_URL: "..." } }.
  • Два таймаута в сумме дают timeout + 30 секунд. Агент убивает процесс ровно по timeout; Gateway ждёт ещё 30 секунд на финальные события и только потом отдаёт EXEC_TIMEOUT.
  • Поддержание соединения в JSON-режиме. Если команда выполняется дольше 15 секунд, сервер периодически шлёт пробелы в тело ответа — это предотвращает таймауты nginx и промежуточных прокси. JSON-парсер игнорирует начальные и конечные пробелы, так что клиент просто прочитает корректный JSON по окончании.

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