Для AI-агентов: markdown этой страницы — /docs-content/infra/database/execute.md индекс документации — /llms.txt
Выполнить SQL на запись
POST /v1/infra/servers/:id/db/execute
Выполняет SQL-выражения на запись в SQLite-базе приложения одной транзакцией: изменяет строки, создаёт и меняет таблицы, индексы и представления.
Перед каждым вызовом платформа сохраняет отдельную защитную копию базы — см. Защитные копии перед записью. Условия доступа — Когда база доступна.
Параметры
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
Параметрid (path) |
Типstring (UUID) | Обяз.да | ОписаниеID приложения с kind равным GALAXY_APP. Список: GET /v1/infra/servers |
Поля запроса (body)
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
Полеfile |
Типstring | Обяз.нет | ОписаниеПуть к файлу базы относительно тома /data, до 1024 байт UTF-8. Абсолютный путь, сегменты . и .. не принимаются. По умолчанию — значение VIBE_DB_PATH контейнера приложения, а без него app.db. Список файлов: GET /db |
Полеsql |
Типstring | Обяз.да | ОписаниеОт 1 до 16384 байт UTF-8. До 64 выражений, разделённых ;. Выражения выполняются по порядку |
Полеparameters |
Типarray | Обяз.нет | ОписаниеЗначения для заполнителей ?, до 256 штук. Элемент — null, строка до 16384 байт UTF-8 или конечное число. Целое число — не больше 2⁵³−1 по модулю, точное 64-битное целое передайте литералом в sql. Логические значения не принимаются — передайте 1 или 0. Допустимы, только когда в sql одно выражение. По умолчанию [] |
Неизвестное поле тела отклоняется с 400 VALIDATION_ERROR.
В sql отклоняются с 422 APP_DB_SQL_ERROR и причиной not_permitted: управление транзакциями и точками сохранения (BEGIN, COMMIT, ROLLBACK, SAVEPOINT), ATTACH и DETACH, PRAGMA, создание и удаление виртуальных таблиц, обращение к схемам кроме main, включая временные таблицы, функции load_extension, readfile, writefile и fts3_tokenizer. VACUUM тоже не выполняется: вызов идёт внутри транзакции, и выражение отклоняется с 422 APP_DB_SQL_ERROR.
Примеры
curl — личный ключ
curl -X POST "https://vibecode.bitrix24.tech/v1/infra/servers/APP_ID/db/execute" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sql":"UPDATE notes SET body = ? WHERE id = ?","parameters":["updated",1]}'
curl — OAuth-приложение
curl -X POST "https://vibecode.bitrix24.tech/v1/infra/servers/APP_ID/db/execute" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"sql":"UPDATE notes SET body = ? WHERE id = ?","parameters":["updated",1]}'
JavaScript — личный ключ
const url = `https://vibecode.bitrix24.tech/v1/infra/servers/${appId}/db/execute`
const headers = { 'X-Api-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }
const body = JSON.stringify({ sql: 'UPDATE notes SET body = ? WHERE id = ?', parameters: ['updated', 1] })
// Повторяется только 409 APP_DB_BACKUP_NOT_READY: в этом ответе SQL ещё не выполнялся
const deadline = Date.now() + 180_000
let result
while (Date.now() < deadline) {
const res = await fetch(url, { method: 'POST', headers, body })
result = await res.json()
if (res.status !== 409 || result.error?.code !== 'APP_DB_BACKUP_NOT_READY') break
const seconds = Number(res.headers.get('Retry-After')) || 1
await new Promise(resolve => setTimeout(resolve, Math.max(seconds, 3) * 1000))
}
if (!result.success) throw new Error(result.error.code)
console.log(result.data.rowCount, result.data.backupId)
JavaScript — OAuth-приложение
const url = `https://vibecode.bitrix24.tech/v1/infra/servers/${appId}/db/execute`
const headers = {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
}
const body = JSON.stringify({ sql: 'UPDATE notes SET body = ? WHERE id = ?', parameters: ['updated', 1] })
const deadline = Date.now() + 180_000
let result
while (Date.now() < deadline) {
const res = await fetch(url, { method: 'POST', headers, body })
result = await res.json()
if (res.status !== 409 || result.error?.code !== 'APP_DB_BACKUP_NOT_READY') break
const seconds = Number(res.headers.get('Retry-After')) || 1
await new Promise(resolve => setTimeout(resolve, Math.max(seconds, 3) * 1000))
}
if (!result.success) throw new Error(result.error.code)
Поля ответа
| Поле | Тип | Описание |
|---|---|---|
Полеsuccess |
Типboolean | Описаниеtrue, если транзакция зафиксирована |
Полеdata.file |
Типstring | ОписаниеФайл базы относительно тома /data, к которому применён SQL |
Полеdata.rowCount |
Типinteger | ОписаниеЧисло строк, изменённых выражениями INSERT, UPDATE и DELETE напрямую. Изменения, сделанные триггерами, не учитываются. Выражение, которое меняет схему базы, например CREATE TABLE … AS SELECT, в счёт не входит |
Полеdata.statementCount |
Типinteger | ОписаниеЧисло выполненных выражений, от 1 до 64 |
Полеdata.durationMs |
Типnumber | ОписаниеВремя выполнения SQL на хосте в миллисекундах, с дробной частью |
Полеdata.backupId |
Типstring | ОписаниеID защитной копии, сохранённой перед этим вызовом. Список копий: GET /db/backups |
Пример ответа
{
"success": true,
"data": {
"file": "app.db",
"rowCount": 1,
"durationMs": 0.933,
"statementCount": 1,
"backupId": "d5e1b7a9-0f42-4c8d-9a3e-6b21c4f80e57"
}
}
Пример ответа при ошибке
422 — выражение PRAGMA journal_mode=DELETE запрещено, транзакция откачена:
{
"success": false,
"error": {
"code": "APP_DB_SQL_ERROR",
"message": "SQL operation is not permitted",
"details": {
"reason": "not_permitted"
}
}
}
Ошибки
| HTTP | Код | Описание |
|---|---|---|
| HTTP400 | КодVALIDATION_ERROR |
ОписаниеТело не прошло проверку: неизвестное поле, пустой или длиннее 16384 байт sql, некорректный file, больше 256 элементов или логическое значение в parameters |
| HTTP400 | КодAPP_DB_INVALID_FILE |
ОписаниеФайл не является базой SQLite, путь к нему проходит через символическую ссылку, или значение VIBE_DB_PATH контейнера не указывает внутрь /data |
| HTTP400 | КодAPP_DB_UNSUPPORTED_PLACEMENT |
ОписаниеПриложение размещено не в Галактике |
| HTTP401 | КодMISSING_API_KEY |
ОписаниеНе передан заголовок X-Api-Key |
| HTTP401 | КодINVALID_API_KEY |
ОписаниеКлюч не опознан |
| HTTP402 | КодBILLING_FROZEN |
ОписаниеСчёт портала заморожен |
| HTTP402 | КодBILLING_INSUFFICIENT |
ОписаниеБаланса портала не хватает на хранение защитной копии |
| HTTP403 | КодINFRA_SCOPE_REQUIRED |
ОписаниеУ ключа нет скоупа vibe:infra |
| HTTP403 | КодAPP_DB_DISABLED |
ОписаниеРабота с базой приложения не включена для портала |
| HTTP403 | КодAPP_DB_READONLY_KEY |
ОписаниеКлюч в режиме только чтения |
| HTTP404 | КодNOT_FOUND |
ОписаниеПриложение не найдено, удалено или недоступно этому ключу |
| HTTP404 | КодAPP_DB_NOT_FOUND |
ОписаниеУ приложения нет тома /data или файла базы: приложение её ещё не создало |
| HTTP409 | КодAPP_DB_BACKUP_NOT_READY |
ОписаниеЗащитная копия ещё готовится, SQL не выполнялся. Повторите запрос после паузы из заголовка Retry-After |
| HTTP409 | КодAPP_DB_BUSY |
ОписаниеИдёт деплой, перенос или восстановление приложения, хост занят другой операцией, база занята записью самого приложения, или пробуждение приложения либо хоста галактики запрещено. SQL не выполнен. Повторите после паузы из Retry-After |
| HTTP409 | КодAPP_DB_WAL_CLOSED |
ОписаниеЗащитная копия не создана: работающее приложение закрыло соединение с базой в режиме журнала упреждающей записи (WAL). SQL не отправлялся, заголовка Retry-After нет. Настройте приложение так, чтобы соединение оставалось открытым |
| HTTP413 | КодPAYLOAD_TOO_LARGE |
ОписаниеТело больше 64 КиБ, или полный вход служебного процесса на хосте больше 96 КиБ |
| HTTP422 | КодAPP_DB_SQL_ERROR |
ОписаниеSQL не выполнен, транзакция откачена. Причина в details.reason: syntax_error, not_permitted, no_such_table, no_such_column, type_mismatch, constraint_failed или other. Причина other приходит и на параметры при нескольких выражениях, и на больше 64 выражений |
| HTTP422 | КодAPP_DB_QUERY_TIMEOUT |
ОписаниеВыполнение заняло больше 30 секунд, транзакция откачена |
| HTTP422 | КодAPP_DB_CORRUPT |
ОписаниеПроверка целостности базы перед записью не прошла, либо защитная копия не создана из-за повреждения базы |
| HTTP422 | КодAPP_DB_BACKUP_TIMEOUT |
ОписаниеЗащитная копия не создана за отведённое время, SQL не отправлялся |
| HTTP422 | КодAPP_DB_BACKUP_INVALID |
ОписаниеЗащитная копия не прошла проверку, SQL не отправлялся |
| HTTP429 | КодRATE_LIMITED |
ОписаниеПревышен лимит запросов на запись для портала — Лимиты. Пауза — в заголовке Retry-After |
| HTTP503 | КодAPP_DB_PRE_CHANGE_FAILED |
ОписаниеЗащитная копия не создана по другой причине, SQL не отправлялся |
| HTTP503 | КодAPP_DB_WRITE_OUTCOME_UNKNOWN |
ОписаниеSQL отправлен, но результат не получен, details.retryable равен false. Изменение могло сохраниться. Ключа идемпотентности нет, поэтому не повторяйте запрос автоматически: сначала прочитайте данные через POST /db/query |
| HTTP503 | КодAPP_DB_TOOL_UNAVAILABLE |
ОписаниеХост не подготовлен или служебный канал к нему недоступен. Готовность хоста — GET /app-db/prepare |
| HTTP503 | Кодuser_self_deletion_pending |
ОписаниеВладелец ключа удаляет свой аккаунт на портале |
Полный список общих ошибок API — Ошибки.
Известные особенности
- Первый вызов только готовит защитную копию. Пока свежей копии для этого файла нет, вызов ставит её создание в очередь и отвечает
409 APP_DB_BACKUP_NOT_READYсdetails.backupId,details.retryAfterSecondsи заголовкомRetry-After. Повторяйте тот же запрос: когда копия готова, повтор выполняет SQL и возвращает вdata.backupIdтот же ID. Готовая копия ждёт повтора 10 минут, позже следующий вызов готовит новую. Устройство защитных копий — Защитные копии перед записью. - Повторы расходуют лимит записи. Каждый повтор после
409учитывается в лимите запросов на запись (Лимиты), поэтому держите паузу не короче трёх секунд, даже когдаRetry-Afterравен1. - Отказ копии приходит один раз. Если защитная копия не создалась, ближайший вызов получает причину с
details.retryable: false, а следующий вызов уже ставит в очередь новую копию. - Весь вызов — одна транзакция. Ошибка любого выражения или превышение 30 секунд откатывает все выражения вызова. Строки, которые возвращают
SELECTиRETURNING, читаются до конца и отбрасываются: в ответ они не попадают. SQL и значения параметров в журнал аудита не записываются. - Внешние ключи проверяются всегда. На время вызова платформа включает проверку внешних ключей, даже если само приложение её не включает. Нарушение ссылочной целостности откатывает вызов с причиной
constraint_failed. - Контейнер приложения не запускается. SQL выполняет служебный контейнер на хосте с тем же томом
/data. - Инструмент для AI-агентов повторяет только неготовую копию. Инструмент
manage_app_dbиз MCP-сервера Вайбкод сaction: "execute"принимаетserverId,file,sql,parametersи сам повторяет только409 APP_DB_BACKUP_NOT_READY. Общий срок ожидания — 180 секунд, пауза — поRetry-After, но не короче трёх секунд. Сетевую ошибку иAPP_DB_WRITE_OUTCOME_UNKNOWNинструмент не повторяет. Отмена ожидания не доказывает, что уже отправленная запись откатилась.