# API changes: October 17, 2026

[← Changelog](/docs/changelog) · [October 2026](/docs/changelog/2026-10)

### BC-1017-1: Message and caption length checks before writing

> Old format supported until: not provided

**Before**

Long text was forwarded to Bitrix24, where it could be truncated. In the legacy mode, several text aliases in the body could override the checked value.

**After**

After the preceding input checks, an outgoing string exceeding 20000 Unicode code points is rejected with `400 MESSAGE_TOO_LONG` before any Bitrix24 call. `error.details` contains only `field: "message"`, `used`, `limit: 20000`, `unit: "unicode-code-points"`. Markup, URLs and mentions count toward the limit. A shorter string is passed unchanged.

In the legacy mode, matching `message`, `MESSAGE`, `Message` and nested `fields.message`, including case variants, resolve to one text. A conflict is rejected with `400 INVALID_PARAMS`. An object is never converted to text. The v2 mode, forwarding and upload publication keep their flat body whitelists. A v2 block-only edit remains unchanged. Empty update text still returns `400 MESSAGE_REQUIRED` before the length check. For forwarding, a wrong comment type, a blank comment and invalid values of other fields still return `400 INVALID_PARAMS` before the length check; omitting the comment still forwards only the messages. A refused caption causes no upload and does not consume `uploadIds`.

**What integrators should do**

Count code points in the outgoing text, for example with `Array.from(message).length` in JavaScript. When the limit is exceeded, show the user an error and keep the draft. Send one `message` field without conflicting aliases and correct the caption before publishing again. There is no automatic truncation, splitting or conversion of long text into a file.

**Affected endpoints:** [POST /v1/chats/{dialogId}/messages](/docs/chats/messages/send), [PATCH /v1/chats/{dialogId}/messages/{messageId}](/docs/chats/messages/update), [POST /v1/chats/{dialogId}/forward](/docs/chats/messages/forward), [POST /v1/chats/{chatId}/files](/docs/chats/files/upload), [POST /v1/chats/{chatId}/files/uploads/publish](/docs/chats/files/upload-publish).

### FIX-1017-2: Empty turns with tools receive an explanation

**Before**

A `POST /v1/chat/completions` request with tools could end without an answer or a call, and the client treated the empty turn as completed work.

**After**

The platform adds a textual explanation for an empty turn or a call finish without a call. Synchronous responses also carry the `TOOL_CALL_MISSING` warning; streams carry a separate text event before the finish. HTTP 200 and `finish_reason: stop` are unchanged; `usage` and charges are preserved. Integrators do not need to change anything.

### NEW-1017-3: Prepare a server for the application database

[GET /v1/infra/servers/{id}/app-db/prepare](/docs/infra/database/prepare) returns preparation state, steps and missing components. Requires the `vibe:infra` scope, application access and the enabled `app-db` feature; READONLY keys can read the status.

[POST /v1/infra/servers/{id}/app-db/prepare](/docs/infra/database/prepare) starts preparation on demand for the application owner or a Bitrix24 account administrator with write access. READONLY keys and frozen billing prevent starting preparation. Returns HTTP 200 when the server is already ready, or HTTP 202 after accepting the request. Poll GET about every three seconds, respecting `Retry-After`, until the state is `ready` or `failed`.

### FIX-1017-4: Catalog sections in the write schema are an array of IDs

**Before**

The `iblockSection` field for products, SKUs, offers and services was described as an object. Create examples showed `{}` instead of an array of section IDs.

**After**

The write schema and examples show an array of numeric section IDs, such as `[47, 48]`. The field is accepted on create and update. The response still represents the primary section as the numeric `iblockSectionId`, and `iblockSection` is not returned.

**Impact on integrators**

Existing requests carrying an array of IDs continue to work. Use an array of IDs from [GET /v1/catalog-sections](/docs/entities/catalog-sections/list).

**Affected endpoints:** [POST /v1/catalog-products](/docs/entities/catalog-products/create), [PATCH /v1/catalog-products/{id}](/docs/entities/catalog-products/update), [POST /v1/catalog-skus](/docs/entities/catalog-skus/create), [PATCH /v1/catalog-skus/{id}](/docs/entities/catalog-skus/update), [POST /v1/catalog-offers](/docs/entities/catalog-offers/create), [PATCH /v1/catalog-offers/{id}](/docs/entities/catalog-offers/update), [POST /v1/catalog-services](/docs/entities/catalog-services/create), [PATCH /v1/catalog-services/{id}](/docs/entities/catalog-services/update).

### FIX-1017-5: a closed application database connection is no longer reported as busy

Reads through [GET /v1/infra/servers/:id/db](/docs/infra/database/info), [GET /v1/infra/servers/:id/db/schema](/docs/infra/database/schema), `POST /v1/infra/servers/:id/db/query` and [GET /v1/infra/servers/:id/db/tables/:table/rows](/docs/infra/database/rows) return `409 APP_DB_WAL_CLOSED` when the application has closed its database connection in WAL mode and both `-wal` and `-shm` are absent. The response includes `details.source: sqlite` and `details.hint`, without `retryable` or `Retry-After`. Configure the application to keep its database connection open so the database can be viewed and copied.

A copy accepted through [POST /v1/infra/servers/:id/db/backups](/docs/infra/database/snapshot) asynchronously ends after one attempt for this reason. In the successful response from [GET /v1/infra/servers/:id/db/backups](/docs/infra/database/backups), it has `status: FAILED` and `errorCode: APP_DB_WAL_CLOSED`.

If a protective copy fails this way before [POST /v1/infra/servers/:id/db/execute](/docs/infra/database/execute) or [row edits](/docs/infra/database), the write returns `409 APP_DB_WAL_CLOSED` with the same safe hint. SQL is not sent, and the write does not enter `APP_DB_WRITE_OUTCOME_UNKNOWN`.

### NEW-1017-6: sign-in source label for device flow

`POST /v1/connect/device/authorize` accepts an optional `login_source` field in JSON and form-urlencoded: an analytics label for the sign-in button, with values defined by the client. The string is trimmed and should match `^[a-z][a-z0-9_]{0,63}$`. An invalid label does not block sign-in or affect permissions or key issuance.

### NEW-1017-7: Key self-description provides the design rule for new UI

[GET /v1/me](/docs/keys-auth/me) returns the new additive `data.uiDesign` block when the feature is available: policy version `policyVersion`, authorized binding `context`, actions `rules`, guidance `instructions` and CSS metadata in `css`. Until the feature is available, the previous response is preserved. Existing clients can continue without reading the block.

For an APP key, `context.status: portal_bound` includes a stable `portalId` and `source: authorized_key_binding`. A MANAGEMENT key always returns `context.status: unresolved`, `portalId: null` and `source: none`. The Bitrix24 account binding does not determine the UI target, prove an iframe request or grant creation, embedding or publication rights. For an internal UI with an unresolved binding, select a Bitrix24 account and read self-description with its APP key rather than choosing the first account in the list.

Policy `policyVersion: 2` handles a standard request to create a new app without a named target separately: with `portal_bound`, the agent uses Bitrix24 design without repeating target or brand questions; with `unresolved`, it selects a Bitrix24 account or clarifies the target. For an external page, the agent asks about branding, while any other task with an unknown target keeps the short target clarification. Existing UI keeps its design, automation without UI does not load CSS, and explicit user preferences take priority. A binding neither grants permissions nor proves an iframe.

The `css` block includes a pinnable `version`, an `href` path for an app and a public `publicHref` for your own hosting. Both addresses identify the same CSS version, available without an API key or session. The `light-desktop` theme uses system font tokens without a network font; include only selected pinned official b24icons locally, not the full catalog. Include CSS once and pin its version for new UI independently of `policyVersion`.

Before choosing the design or creating UI, read the full `/v1/me` response and its `data.uiDesign` block. If the block is absent, unsupported or cannot be read, the agent reports that the rule was not read and clarifies the design with the user.

[GET /v1/app/blueprints/:slug](/docs/app-blueprints) serves Russian and English specs pointing to the full `/v1/me` response before choosing the design. Specs remain markdown; an unknown locale returns English. Blueprint requirements remain separate from UI design: background work, bot messages and generated documents do not automatically receive CSS.

### FIX-1017-8: File search accepts the requested result count

**Before**

`POST /v1/disk/search` rejected every explicit `limit` except `50`, although the schema allowed values from `1` to `1000`.

**After**

`limit` from `1` to `1000` sets an upper bound on the response size. The default remains `50`. A response can contain fewer results: when `hasMore=true`, continue with `nextCursor`, including after an empty page. Continuation preserves the unread remainder. Native Bitrix24 search limits still apply.

**Impact on integrators**

Calls with `limit=10` and other supported values now work. Existing calls with `50` or without `limit` remain valid. Results can shift when the index or access rights change.
