Для AI-агентов: markdown этой страницы — /docs-content/infra/database/query.md индекс документации — /llms.txt
Выполнить SQL-запрос на чтение
POST /v1/infra/servers/:id/db/query
Выполняет один SQL-запрос на чтение к SQLite-базе приложения и возвращает колонки и строки результата. Подходит для выборок с условиями, соединениями и агрегатами, которых нет у чтения строк одной таблицы.
Условия доступа к базе и лимиты запросов — Когда база доступна и Лимиты. Изменить данные — Выполнить SQL на запись.
Параметры
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
Параметрid (path) |
Типstring (UUID) | Обяз.да | ОписаниеID приложения с kind равным GALAXY_APP. Список: GET /v1/infra/servers |
Поля запроса (body)
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
Полеsql |
Типstring | Обяз.да | ОписаниеОдна SQL-инструкция на чтение, до 16 384 байт в UTF-8. Значения подставляются через позиционные маркеры ? |
Полеparameters |
Типarray | Обяз.нет | ОписаниеЗначения для маркеров ? по порядку, до 256 штук. Каждое — строка до 16 384 символов, конечное число или null. Логические значения не принимаются, вместо них передавайте 1 и 0. По умолчанию [] |
Полеfile |
Типstring | Обяз.нет | ОписаниеПуть к файлу базы относительно /data, до 1024 байт в UTF-8. Список файлов — data.files[].file в GET /db. По умолчанию — data.defaultFile оттуда же |
Другие поля тела дают 400 VALIDATION_ERROR. Тело — до 64 КиБ.
Пагинация. Курсора и номера страницы у эндпоинта нет: при data.truncated: true строки сверх лимита отбрасываются. Остаток забирается следующим запросом: добавьте в sql устойчивую сортировку ORDER BY и LIMIT с OFFSET либо условие по ключу последней полученной строки, например WHERE id > ?.
Примеры
curl — личный ключ
curl -X POST "https://vibecode.bitrix24.tech/v1/infra/servers/APP_ID/db/query" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sql": "SELECT id, name, email FROM customers WHERE id > ? ORDER BY id",
"parameters": [1]
}'
curl — OAuth-приложение
curl -X POST "https://vibecode.bitrix24.tech/v1/infra/servers/APP_ID/db/query" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"sql": "SELECT id, name, email FROM customers WHERE id > ? ORDER BY id",
"parameters": [1]
}'
JavaScript — личный ключ
const res = await fetch(
`https://vibecode.bitrix24.tech/v1/infra/servers/${appId}/db/query`,
{
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
sql: 'SELECT id, name, email FROM customers WHERE id > ? ORDER BY id',
parameters: [1],
}),
}
)
const { success, data, error } = await res.json()
if (!success) throw new Error(`${error.code}: ${error.details?.reason ?? error.message}`)
// Строки — позиционные массивы в порядке data.columns
const rows = data.rows.map(r => Object.fromEntries(data.columns.map((c, i) => [c, r[i]])))
console.log(rows, data.truncated ? 'результат обрезан' : '')
JavaScript — OAuth-приложение
const res = await fetch(
`https://vibecode.bitrix24.tech/v1/infra/servers/${appId}/db/query`,
{
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
sql: 'SELECT id, name, email FROM customers WHERE id > ? ORDER BY id',
parameters: [1],
}),
}
)
const { success, data, error } = await res.json()
if (!success) throw new Error(error.code)
console.log(data.columns, data.rows)
Поля ответа
| Поле | Тип | Описание |
|---|---|---|
Полеsuccess |
Типboolean | Описаниеtrue при успешном ответе |
Полеdata.file |
Типstring | ОписаниеПуть прочитанного файла относительно /data |
Полеdata.columns |
Типarray | ОписаниеИмена колонок результата по порядку. Одинаковые имена, например после соединения таблиц, остаются отдельными элементами |
Полеdata.rows |
Типarray | ОписаниеСтроки результата, до 500. Каждая строка — массив значений в порядке data.columns |
Полеdata.rows[][] |
Типstring | number | null | object | ОписаниеЗначение ячейки. Текст — строкой, числа — числом, SQL NULL — null. Значения, которые нельзя передать числом или строкой JSON, приходят объектом с полем type — см. три строки ниже |
Полеdata.rows[][] с type: "blob" |
Типobject | ОписаниеДвоичные данные, поле base64 — содержимое в кодировке Base64 |
Полеdata.rows[][] с type: "integer" |
Типobject | ОписаниеЦелое число больше 9 007 199 254 740 991 по модулю, поле value — число строкой |
Полеdata.rows[][] с type: "float" |
Типobject | ОписаниеБесконечность или не-число, поле value — Infinity, -Infinity или NaN |
Полеdata.rowCount |
Типinteger | ОписаниеЧисло строк в data.rows |
Полеdata.truncated |
Типboolean | Описаниеtrue, если результат обрезан: строк больше 500 или ответ приблизился к 1 МиБ. Строки сверх лимита не возвращаются |
Полеdata.durationMs |
Типnumber | ОписаниеВремя чтения на хосте в миллисекундах |
Пример ответа
{
"success": true,
"data": {
"file": "app.db",
"columns": ["id", "name", "email"],
"rows": [
[2, "Customer B", "b@example.com"],
[3, "Customer C", null]
],
"rowCount": 2,
"truncated": false,
"durationMs": 0.75
}
}
Пример ответа при ошибке
422 — запрос пытается изменить данные:
{
"success": false,
"error": {
"code": "APP_DB_SQL_ERROR",
"message": "SQL operation is not permitted",
"details": {
"reason": "not_permitted"
}
}
}
Ответ на SQL-ошибку не содержит ни текста запроса, ни значений, ни исходного сообщения SQLite — причину называет только error.details.reason.
Ошибки
| HTTP | Код | Описание |
|---|---|---|
| HTTP400 | КодVALIDATION_ERROR |
ОписаниеНет sql, передано неизвестное поле, parameters длиннее 256 элементов или содержит недопустимое значение, sql или file превышает допустимую длину |
| HTTP400 | КодAPP_DB_INVALID_FILE |
Описаниеfile — абсолютный путь, содержит . или .., ведёт через символьную ссылку или указывает не на базу SQLite |
| HTTP400 | КодAPP_DB_UNSUPPORTED_PLACEMENT |
ОписаниеПриложение размещено не в Галактике |
| HTTP401 | КодMISSING_API_KEY |
ОписаниеНе передан заголовок X-Api-Key |
| HTTP401 | КодINVALID_API_KEY |
ОписаниеКлюч не опознан |
| HTTP402 | КодBILLING_FROZEN |
ОписаниеХост галактики спит, а баланс заморожен — разбудить хост нельзя |
| HTTP403 | КодINFRA_SCOPE_REQUIRED |
ОписаниеУ ключа нет скоупа vibe:infra |
| HTTP403 | КодAPP_DB_DISABLED |
ОписаниеРабота с базой не включена для портала |
| HTTP403 | КодSERVER_WAKE_BLOCKED |
ОписаниеХост галактики спит, и пробуждение для него запрещено |
| HTTP404 | КодNOT_FOUND |
ОписаниеПриложение не существует, удалено или недоступно этому ключу |
| HTTP404 | КодAPP_DB_NOT_FOUND |
ОписаниеНет тома /data или файла базы — приложение ещё не создало базу |
| HTTP409 | КодAPP_DB_WAL_CLOSED |
ОписаниеБаза в режиме WAL, а файлов -wal и -shm нет: работающее приложение закрыло соединение. Заголовка Retry-After нет |
| HTTP409 | КодAPP_DB_BUSY |
ОписаниеХост занят другой операцией, не подключился за 10 секунд или база заблокирована записью приложения. Ответ несёт заголовок Retry-After |
| HTTP413 | КодPAYLOAD_TOO_LARGE |
ОписаниеТело запроса больше 64 КиБ, или запрос вместе со служебными данными превышает 96 КиБ |
| HTTP422 | КодAPP_DB_SQL_ERROR |
Описаниеerror.details.reason равен not_permitted: инструкция пытается изменить данные или схему, управлять транзакцией, подключить другую базу, выполнить PRAGMA или загрузить расширение, вызвать readfile или writefile |
| HTTP422 | КодAPP_DB_SQL_ERROR |
Описаниеerror.details.reason равен syntax_error: ошибка синтаксиса SQL |
| HTTP422 | КодAPP_DB_SQL_ERROR |
Описаниеerror.details.reason равен no_such_table: таблицы из запроса нет в базе |
| HTTP422 | КодAPP_DB_SQL_ERROR |
Описаниеerror.details.reason равен no_such_column: колонки из запроса нет в таблице |
| HTTP422 | КодAPP_DB_SQL_ERROR |
Описаниеerror.details.reason равен type_mismatch: значение несовместимо с типом |
| HTTP422 | КодAPP_DB_SQL_ERROR |
Описаниеerror.details.reason равен other: прочие ошибки выполнения, в том числе несколько инструкций в одном sql |
| HTTP422 | КодAPP_DB_QUERY_TIMEOUT |
ОписаниеЗапрос не уложился в 5 секунд |
| HTTP422 | КодAPP_DB_CORRUPT |
ОписаниеПроверка целостности базы не пройдена |
| HTTP429 | КодRATE_LIMITED |
ОписаниеПревышен лимит запросов на чтение для портала — Лимиты. Пауза — в заголовке Retry-After |
| HTTP503 | КодAPP_DB_TOOL_UNAVAILABLE |
ОписаниеХост не подготовлен к чтению базы или временно недоступен. Ответ несёт заголовок Retry-After. Подготовка — Подготовить хост |
| HTTP503 | Кодuser_self_deletion_pending |
ОписаниеВладелец ключа удаляет свой аккаунт на этом портале |
Полный список общих ошибок API — Ошибки.
Известные особенности
- Изменить базу запрос не может. Соединение открывается только на чтение, и кроме проверки инструкции на сервере SQLite сам отклоняет запись. Поэтому, в отличие от SQL на запись,
POST /db/queryне создаёт защитную копию перед выполнением. - SQL и данные не сохраняются в журнале аудита. В журнал попадают операция, число строк и длительность. Текст
sql,parametersи строки результата там не хранятся.