For AI agents: markdown of this page — /docs-content-en/infra/database/query.md documentation index — /llms.txt

Run a read-only SQL query

POST /v1/infra/servers/:id/db/query

Runs one read-only SQL query against the application's SQLite database and returns the result columns and rows. Use it for queries with conditions, joins and aggregates that reading the rows of a single table does not support.

Database access conditions and request limits — When the database is available and Limits. To change data — Run write SQL.

Parameters

Parameter Type Required Description
Parameterid (path) Typestring (UUID) Requiredyes DescriptionID of an application with kind equal to GALAXY_APP. List: GET /v1/infra/servers

Request fields (body)

Field Type Required Description
Fieldsql Typestring Requiredyes DescriptionOne read-only SQL statement, up to 16,384 bytes in UTF-8. Values are bound through positional ? placeholders
Fieldparameters Typearray Requiredno DescriptionValues for the ? placeholders in order, up to 256 items. Each is a string up to 16,384 characters, a finite number or null. Booleans are not accepted; pass 1 and 0 instead. Default: []
Fieldfile Typestring Requiredno DescriptionDatabase file path relative to /data, up to 1024 bytes in UTF-8. File list — data.files[].file in GET /db. Default — data.defaultFile from the same response

Other body fields return 400 VALIDATION_ERROR. The body is limited to 64 KiB.

Pagination. The endpoint has no cursor or page number: with data.truncated: true, rows beyond the limit are dropped. Fetch the rest with the next query: add a stable ORDER BY sort and LIMIT with OFFSET to sql, or a condition on the key of the last row received, for example WHERE id > ?.

Examples

curl — personal key

Terminal
curl -X POST "https://vibecode.bitrix24.com/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 application

Terminal
curl -X POST "https://vibecode.bitrix24.com/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 — personal key

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/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}`)
// Rows are positional arrays in data.columns order
const rows = data.rows.map(r => Object.fromEntries(data.columns.map((c, i) => [c, r[i]])))
console.log(rows, data.truncated ? 'result truncated' : '')

JavaScript — OAuth application

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/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)

Response fields

Field Type Description
Fieldsuccess Typeboolean Descriptiontrue on success
Fielddata.file Typestring DescriptionPath of the file read, relative to /data
Fielddata.columns Typearray DescriptionResult column names in order. Duplicate names, for example after a join, remain separate items
Fielddata.rows Typearray DescriptionResult rows, up to 500. Each row is an array of values in data.columns order
Fielddata.rows[][] Typestring | number | null | object DescriptionCell value. Text as a string, numbers as a number, SQL NULL as null. Values that cannot be passed as a JSON number or string come as an object with a type field — see the three rows below
Fielddata.rows[][] with type: "blob" Typeobject DescriptionBinary data; the base64 field holds the Base64-encoded content
Fielddata.rows[][] with type: "integer" Typeobject DescriptionAn integer with absolute value greater than 9,007,199,254,740,991; the value field holds the number as a string
Fielddata.rows[][] with type: "float" Typeobject DescriptionInfinity or not-a-number; the value field is Infinity, -Infinity or NaN
Fielddata.rowCount Typeinteger DescriptionNumber of rows in data.rows
Fielddata.truncated Typeboolean Descriptiontrue if the result was truncated: more than 500 rows or the response approached 1 MiB. Rows beyond the limit are not returned
Fielddata.durationMs Typenumber DescriptionRead time on the host in milliseconds

Response example

JSON
{
  "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
  }
}

Error response example

422 — the query tries to change data:

JSON
{
  "success": false,
  "error": {
    "code": "APP_DB_SQL_ERROR",
    "message": "SQL operation is not permitted",
    "details": {
      "reason": "not_permitted"
    }
  }
}

An SQL error response contains neither the query text, nor the values, nor the original SQLite message — only error.details.reason names the cause.

Errors

HTTP Code Description
HTTP400 CodeVALIDATION_ERROR Descriptionsql is missing, an unknown field was passed, parameters has more than 256 items or contains an invalid value, sql or file exceeds the allowed length
HTTP400 CodeAPP_DB_INVALID_FILE Descriptionfile is an absolute path, contains . or .., goes through a symbolic link or does not point to an SQLite database
HTTP400 CodeAPP_DB_UNSUPPORTED_PLACEMENT DescriptionThe application is not hosted in Galaxy
HTTP401 CodeMISSING_API_KEY DescriptionThe X-Api-Key header is missing
HTTP401 CodeINVALID_API_KEY DescriptionThe key is not recognized
HTTP402 CodeBILLING_FROZEN DescriptionThe galaxy host is asleep and the balance is frozen — the host cannot be woken
HTTP403 CodeINFRA_SCOPE_REQUIRED DescriptionThe key lacks the vibe:infra scope
HTTP403 CodeAPP_DB_DISABLED DescriptionDatabase access is not enabled for the portal
HTTP403 CodeSERVER_WAKE_BLOCKED DescriptionThe galaxy host is asleep and waking it is blocked
HTTP404 CodeNOT_FOUND DescriptionThe application does not exist, was deleted or is not accessible to this key
HTTP404 CodeAPP_DB_NOT_FOUND DescriptionThere is no /data volume or database file — the application has not created a database yet
HTTP409 CodeAPP_DB_WAL_CLOSED DescriptionThe database is in WAL mode, but the -wal and -shm files are missing: a running application has closed the connection. There is no Retry-After header
HTTP409 CodeAPP_DB_BUSY DescriptionThe host is busy with another operation, did not connect within 10 seconds, or the database is locked by an application write. The response carries a Retry-After header
HTTP413 CodePAYLOAD_TOO_LARGE DescriptionThe request body exceeds 64 KiB, or the request together with service data exceeds 96 KiB
HTTP422 CodeAPP_DB_SQL_ERROR Descriptionerror.details.reason is not_permitted: the statement tries to change data or the schema, control a transaction, attach another database, run PRAGMA or load an extension, or call readfile or writefile
HTTP422 CodeAPP_DB_SQL_ERROR Descriptionerror.details.reason is syntax_error: an SQL syntax error
HTTP422 CodeAPP_DB_SQL_ERROR Descriptionerror.details.reason is no_such_table: a table from the query does not exist in the database
HTTP422 CodeAPP_DB_SQL_ERROR Descriptionerror.details.reason is no_such_column: a column from the query does not exist in the table
HTTP422 CodeAPP_DB_SQL_ERROR Descriptionerror.details.reason is type_mismatch: a value is incompatible with the type
HTTP422 CodeAPP_DB_SQL_ERROR Descriptionerror.details.reason is other: other execution errors, including several statements in one sql
HTTP422 CodeAPP_DB_QUERY_TIMEOUT DescriptionThe query did not finish within 5 seconds
HTTP422 CodeAPP_DB_CORRUPT DescriptionThe database integrity check failed
HTTP429 CodeRATE_LIMITED DescriptionThe read request limit for the portal was exceeded — Limits. The pause is in the Retry-After header
HTTP503 CodeAPP_DB_TOOL_UNAVAILABLE DescriptionThe host is not prepared for database reads or is temporarily unavailable. The response carries a Retry-After header. Preparation — Prepare the host
HTTP503 Codeuser_self_deletion_pending DescriptionThe key owner is deleting their account on this portal

Full list of common API errors — Errors.

Known specifics

  • The query cannot change the database. The connection is opened read-only, and in addition to the server-side statement check, SQLite itself rejects writes. That is why, unlike write SQL, POST /db/query does not create a protective backup before running.
  • SQL and data are not stored in the audit log. The log records the operation, the row count and the duration. The sql text, parameters and result rows are not stored there.

See also