# API changes: September 14, 2026

[← Changelog](/docs/changelog) · [September 2026](/docs/changelog/2026-09)

### BC-0914-1: channel recovery may refuse to protect a running operation

> Old format supported until: not provided

**Before**

[`POST /v1/infra/servers/:id/unstick`](/docs/infra/servers/unstick) without `force` could interrupt a long-running operation that the pre-reset check did not detect.

**After**

The method checks server activity more thoroughly. It returns `409 OPERATION_IN_PROGRESS` when an operation lock is detected, or `503 LOCK_STATE_UNAVAILABLE` if the check is unavailable. Neither response resets the channel. `force=true` or `force=1` still allows an intentional interruption.

**What integrators should do**

Handle both refusals. On `409 OPERATION_IN_PROGRESS`, check the operation's state and wait for it to finish. On `503 LOCK_STATE_UNAVAILABLE`, retry later. Add `force=true` or `force=1` only after a deliberate decision to interrupt the operation, never as an automatic retry after a refusal.

### BC-0914-2: storage object delete and list received a per-account request limit

> Old format supported until: not provided

**Before**

`DELETE /v1/storage/objects/{key}` and `GET /v1/storage/objects` accepted requests with no
frequency limit. A client repeating the same call in a loop could sustain thousands of
requests per minute for hours, slowing the API down for every Bitrix24 account on the same site. A
`HEAD` request to the object list was served as a full `GET`: the whole set was read and
only the headers were returned.

**After**

Each of the two operations carries a limit of **600 requests per minute per Bitrix24 account**; all
API keys of one account share one limit, and it is counted separately for each of the two
operations. Take the value actually in force from the `X-RateLimit-Limit` response header
rather than from the number in this text: it can turn out to be lower. Over the limit the
Vibecode API
answers `429 RATE_LIMITED` with the `X-RateLimit-Remaining`, `X-RateLimit-Reset` and
`Retry-After` headers; the delay is not in the response body — take it from the header. The
`HEAD` method on the list address is no longer served — use `GET` with `limit=1` instead.
Successful responses of both operations, their status codes and data format are unchanged,
and the behaviour of every other storage method is unchanged.

**What integrators should do**

1. **Handle `429` on delete and list.** Both operations received a limit they did not have.
   If your code deletes objects in bulk or in a loop, or re-reads the list often, add
   handling for `429 RATE_LIMITED` with a pause based on the `Retry-After` header. The
   budget is shared by the account, so issuing a second key does not widen it.
2. **Do not hard-code the ceiling.** Read `X-RateLimit-Limit` from the response.
3. **Replace `HEAD` on the list** with `GET /v1/storage/objects?limit=1`.
4. **Check your retry loop.** Deleting an already deleted object answers
   `410 STORAGE_OBJECT_DELETED` — that means the object is gone, not that the operation
   should be repeated. Code that retries on `410` will now hit the limit as well.

### FIX-0914-3: updating and deleting a smart process answer the Bitrix24 refusal code, not an internal error

**Before**

`PATCH /v1/smart-processes/{id}`, `DELETE /v1/smart-processes/{id}` and the batch update or delete via `POST /v1/smart-processes/batch` (`action: update` / `delete`) ask Bitrix24 for the smart process's internal id by its `entityTypeId` before writing. When Bitrix24 refused that request — the call limit was exceeded, Bitrix24 was unavailable or did not answer in time — the client got the code `INTERNAL_ERROR` with a status repeating the Bitrix24 one (`429`, `502`, `503` or `504`) and no `Retry-After` header. The same Bitrix24 refusal one step later in the same operations arrived as `429 RATE_LIMITED`, `502 BITRIX_UNAVAILABLE` or `503 BITRIX_TIMEOUT` — a client that retries on those codes did not retry on `INTERNAL_ERROR`.

**After**

A Bitrix24 refusal at this step answers the same way as on any other call to Bitrix24: `429 RATE_LIMITED` (including the limit Bitrix24 sends with status `503`) and `503 BITRIX_TIMEOUT` — with a `Retry-After` header, `502 BITRIX_UNAVAILABLE` — without one. On such a refusal the write is not sent to Bitrix24. The successful response remains `200` (`204` for `DELETE /v1/smart-processes/{id}`). `404 SMART_PROCESS_NOT_FOUND` for an `entityTypeId` Bitrix24 does not know and `400` for an `entityTypeId` that is not a positive integer (`INVALID_ENTITY_TYPE_ID` on the single-record operations, `BATCH_ITEM_VALIDATION` on the batch) are unchanged. Code details — on the [Errors](/docs/errors) page.

### NEW-0914-4: creating a lead now warns when Bitrix24 converted it by itself

On a Bitrix24 account running CRM in simple mode (no leads) Bitrix24 converts the lead right on creation: it comes back `CONVERTED` and closed, with a contact and a deal created from it that the request never asked for — the requested stage is not kept. Vibecode changes nothing in the request: this is Bitrix24's own behaviour. [POST /v1/leads](/docs/entities/leads/create) now adds a `LEAD_AUTO_CONVERTED` warning to `meta.warnings` in that case, with the ids of the contact (`contactId`) and deal (`dealId`) Bitrix24 created; `null` when the record was not created or not found: a contact you bound via `contactId` is reused by Bitrix24. The response stays `201` with the created record; a lead that stays open leaves the response unchanged. There is no warning when `CONVERTED` was requested explicitly.

### BC-0914-5: access-policy refusal identifies the required key

> Old format supported until: not provided

**Before**

`PATCH /v1/infra/servers/:id/access-policy` returned `404 NOT_FOUND` when a key was bound to the application and server but another key managed the server.

**After**

The method now returns `403 SERVER_MANAGING_KEY_REQUIRED` in this case and directs the caller to use the server managing key or the cabinet. Permissions are unchanged; unrelated keys still receive `404 NOT_FOUND`.

**What integrators should do**

Handle `SERVER_MANAGING_KEY_REQUIRED` separately from a missing server and retry the policy change with the managing key.

### BC-0914-6: company search rejects the service index and contacts support category filtering

> Old format supported until: not provided

**Before**

Company filters using `searchContent` were accepted with HTTP 200 and suggested by `UNKNOWN_FILTER_FIELD`, although the service index is not intended for plain-text search. Contact filters using `categoryId` returned HTTP 400 despite Bitrix24 supporting them.

**After**

Company filters using `searchContent` return `400 UNKNOWN_FILTER_FIELD`, and the field is excluded from the list of accepted filters. Reading the field and requesting it through `select` are unchanged. Contact filters using `categoryId` are accepted and listed under `Also filterable` in the error hint.

**What integrators need to do**

Replace text searches using `searchContent` with a `title` filter using `$contains`. The restriction also applies to requests using a prepared service index string. For contact filters, use the exact spelling `categoryId`, for example `{ "filter": { "categoryId": 0 } }`.

**Affected endpoints:** [GET /v1/companies](/docs/entities/companies/list), [POST /v1/companies/search](/docs/entities/companies/search), [GET /v1/contacts](/docs/entities/contacts/list), [POST /v1/contacts/search](/docs/entities/contacts/search). These rules also apply to filters in batch requests and aggregation.

### BC-0914-7: storage object listing no longer counts the full set by default

> Old format supported until: not provided

**Before**

[GET /v1/storage/objects](/docs/storage/objects/list) returned a required exact `total` field on every page. A list with `prefix` was ordered by descending `id`, and an app key without a user token could include employees' personal objects.

**After**

By default, the response contains only `data` and `cursor`. The exact `total` field is returned only with `withTotal=true`. Without `prefix`, descending `id` order is preserved; with `prefix`, the bytewise order is ascending `key` and descending `id`. The new opaque cursor is bound to the owner, prefix, and ordering mode. An app key without a user token lists only the app's shared objects, while a key with a user token lists only the objects of the corresponding Bitrix24 employee.

**What integrators need to do**

Finish a walk only when `cursor` is `null`, and pass a non-null cursor without parsing or modifying it. Restart a prefixed walk that began with an old cursor by omitting the cursor. Send `withTotal=true` only on requests that need an exact count. Request an employee's personal objects with that employee's user token.

### BC-0914-8: creating a document template from a Disk file requires the disk scope

> Old format supported until: not provided

**Before**

[POST /v1/doc-templates](/docs/entities/doc-templates/create) accepted a Disk object ID in `fileId` with only the `documentgenerator` scope and returned `201`, but the created template could not generate a document: the subsequent call returned `422 BITRIX_ERROR` with `b24Code=FILE_NOT_PROCESSABLE`.

**After**

The `fileId` variant creates a renderable document template and requires both `documentgenerator` and `disk` on the key. The file may be up to 2 MiB. The base64 `.docx` content variant in `file` does not require `disk` and continues to work with the `documentgenerator` scope.

**What integrators should do**

Add the `disk` scope to keys that create templates through `fileId`. Keys used with base64 `file` need no change.

### NEW-0914-9: Vibe+ trials grant agent access on the international platform

An active Vibe+ trial grants agent and managed-bot access with one shared VM limit. Paid Vibe+ retains access. Managed bots also require the platform bot feature to be enabled. After the trial ends, access is revoked, the entity is retained, and the VM is frozen during the scheduled check. Starting, waking, rebooting, repairing, resizing or restoring a demo VM, including creating a VM from its backup, can return `VIBE_DEMO_EXPIRED` (HTTP 403). Other regions and existing VMs without demo provenance retain their access model.

### FIX-0914-10: open line queue fields refuse clearly instead of surfacing a Bitrix24 error

**Before**

The field catalogue and the session-less agent discovery path both listed all 95 fields of an
open line configuration, including `queue`, `queueFull`, `queueUsersFields` and `queueOnline`.
Naming one of those four in `select`, `filter` or `sort` on [GET /v1/openline-configs](/docs/openlines/config/list)
or [POST /v1/openline-configs/search](/docs/openlines/config/search) travelled to Bitrix24 and
came back as the Bitrix24 answer `422 BITRIX_ERROR` reading `An unknown field 'QUEUE' is passed
in the PARAMS field 'select'` — in a spelling the client never sent, and with no hint of where
the field can actually be read.

**After**

Both endpoints refuse before the Bitrix24 call with `400 UNSUPPORTED_LIST_FIELD`. The message
names the spelling the client sent, the position (`select`, `filter` or `sort`), all four fields
of the boundary and the route that does serve them — [GET /v1/openline-configs/:id](/docs/openlines/config/get).
The same boundary is now stated in those fields' descriptions in `GET /v1/openline-configs/fields`
and in the entity section of `GET /v1/guide`. The field set of the list and search responses is
unchanged: those four were never in it.

**Impact on integrators**

No action required. A request that used to receive `422` now receives `400` carrying the address
of the working route; successful calls are untouched.

### FIX-0914-11: partner NFR licenses are recognized as commercial

**Before**

When Bitrix24 license sources disagreed, [GET /v1/me](/docs/keys-auth/me) could return a free-plan value in `data.tariff.code` and `data.tariff.isCommercial: false` for a partner NFR license. Commercial capabilities were then reported as unavailable.

**After**

[GET /v1/me](/docs/keys-auth/me) recognizes this license by the `nfr` code, returns `data.tariff.isCommercial: true`, and evaluates capabilities as a commercial plan.

**Impact on integrations**

No client change is required. Refreshing the tariff snapshot automatically removes the incorrect restriction.

### NEW-0914-13: the external application API response carries X-Vibe-Request-Id

A response from `ANY /v1/applications/{id}/api/**` may now carry an `X-Vibe-Request-Id` header
with the end-to-end identifier of the call — the same one the platform writes to its own log.
Quote its value when contacting support.

The header is present exactly when the identifier was issued, that is when the call reached
the tunnel and the tunnel answered: on the application's own response with any status it
returns, and on the `503 APP_API_UNAVAILABLE` and `502 APP_API_RESPONSE_TOO_LARGE` refusals
that came as the tunnel's answer, and on `502 APP_API_BAD_ENVELOPE`.

The header is absent where the identifier did not exist yet or the tunnel's answer never
arrived: `401` and `403` for the key, `429 APP_API_RATE_LIMITED`, `409 APP_API_NOT_ENABLED`,
`403 APP_API_NOT_GRANTED`, `404 APP_API_APP_NOT_FOUND`, `400 APP_API_BAD_PATH`,
`413 APP_API_PAYLOAD_TOO_LARGE`, and also `504 APP_API_TIMEOUT` and the
`503 APP_API_UNAVAILABLE` / `502 APP_API_RESPONSE_TOO_LARGE` refusals the platform decided on
its own (the application is unreachable, the channel is saturated, the tunnel is silent, the
answer did not fit the cap on our side).

Hence the rule for a client: **it is the presence of the header that tells them apart, not the
response code** — the very same `503 APP_API_UNAVAILABLE` arrives both with it and without.
The header is optional, so treat its absence as a normal case.

Everything else in the response is unchanged — the status, the body and the remaining headers
are the same, and a client needs no changes.

### BC-0914-14: `Idempotency-Key` on server creation now has a 15-minute replay window

> Old format supported until: not provided

**Before**

`POST /v1/infra/servers` replayed a create for an `Idempotency-Key` indefinitely: as long as the server row existed, the same key returned `201` with the `Idempotent-Replayed` header no matter how much time had passed. A replay skips the creation-policy pre-check entirely — including refusals that do not depend on machine count: unsupported region, an unreadable Bitrix24 plan, a plan outside the allowed list. An account that had since lost the right to create servers still received `201` for an old key.

**After**

A replay is valid for **15 minutes** from the moment the machine was created. Past that window the same key no longer replays: the request runs as a new create and goes through every policy check — so an account without creation rights now gets a normal refusal (`402` / `403`) instead of a machine.

Re-using an expired key is not possible even when the rights are fine: the key is spent and answers `409 IDEMPOTENCY_KEY_ALREADY_USED`. The message says which case you are in: the server was deleted — pick a new key; the server exists — locate it with `GET /v1/infra/servers` first, or you will pay for a second machine next to the first.

One limitation is unchanged and unrelated to the window: **a FIRST create on galaxy placement is not protected by the key** — it is not reserved there at all. That is a separate known gap, present before this change too. A key already spent by an earlier standalone create is now refused on the galaxy path with `409` instead of being silently ignored.

What to do: when retrying after a long pause, **check `GET /v1/infra/servers` first** to see whether the original request already created the server, and retry only if it is not there. If you do retry blind, send **THE SAME** `Idempotency-Key` rather than a fresh one: for a standalone create it returns either the server itself or `409 IDEMPOTENCY_KEY_ALREADY_USED`, whose message tells you whether the server exists or was deleted. ⚠️ On galaxy placement even that is not enough: a **first** create there does not reserve the key, so a retry with the same key can still produce a second resource — for galaxy the `GET` check is mandatory, not advisable.

### FIX-0914-15: OpenAPI now separates a personal key from an OAuth application key

**Before**

Every operation in `GET /v1/openapi.json` carried a single authorization scheme, `security: [{ apiKey: [] }]`, whose own description says the `X-Api-Key` header accepts a personal key (`vibe_api_…`), an OAuth application key (`vibe_app_…`) and a management key (`vibe_live_…`) alike. For the routes Bitrix24 ties to the APPLICATION that is untrue: the operations of the `bizproc-templates`, `bizproc-robots` and `bizproc-activities` entities answer a personal key with `403 OAUTH_REQUIRED`, and `GET /v1/triggers` answers `403 BITRIX_ACCESS_DENIED`. The refusal codes were already named in the spec, but the key family stayed machine-indistinguishable, so a client generated from the spec learned it only from the refusal.

**After**

Those operations declare an authorization requirement of their own — the pair of schemes `oauthAppKey` (the OAuth application key `vibe_app_…` in the `X-Api-Key` header) and `oauthSession` (the `vibe_session_…` token from `POST /v1/oauth/token` in the `Authorization: Bearer` header); both schemes sit in one requirement object, so both headers are needed on the same call. Operations a personal key may call keep the previous scheme, `POST /v1/triggers/fire` and `GET /v1/workflows` of the same `bizproc` scope among them. The `403` description of `POST /v1/triggers/fire` is corrected alongside: it claimed that firing a trigger also needs an application context, while a personal key works there.

**Impact on integrators**

API behaviour is unchanged: the same calls answer with the same codes as before, and the HTTP 200 response is unchanged. Only the machine contract moved, so a regenerated client asks for the app key with its session token at build time rather than at run time. `GET /v1/me` lists the entities in this class under `api.entityApi.oauthOnlyEntities`.

### FIX-0914-16: native user-field names remain in narrow selections

**Before**

When a CRM entity was requested with `select=id,UF_CRM_...`, the user-field value could be absent from the response even though it was stored in Bitrix24. The rule in [`GET /v1/me`](/docs/keys-auth/me) did not explain that dynamic names are not checked as unknown schema fields.

**After**

A native `UF_CRM_...` name is translated to the spelling accepted by the selected Bitrix24 method and projects the corresponding user-field key. This includes the digit-suffixed names created by the Bitrix24 interface: in camelCase, the underscore before the digits is kept (`UF_CRM_1698325419` → `ufCrm_1698325419`). [`GET /v1/me`](/docs/keys-auth/me) lists the dynamic and method-specific name classes that cannot be checked against the static schema; an absent such key in a narrow selection alone does not mean its stored value is empty or its spelling is valid for the method.

**Impact on integrators**

No request changes are required. A narrow selection using a native `UF_CRM_...` name now returns the stored field value; the response key continues to use the spelling accepted by the selected Bitrix24 method.

### FIX-0914-17: Connect app authorization on self-hosted portals

**Before**

Connecting an app through Connect to a self-hosted portal without a Bitrix24.Network link stopped with `PORTAL_NOT_LINKED`.

**After**

Self-hosted portals issue keys through their portal connector or the user's developer key, without Bitrix24.Network. If the developer key is not configured, the consent screen explains what to configure. Key scopes match the user's consent. Cloud portals retain Bitrix24.Network issuance; `vibe:*`-only scopes require no webhook.

**Impact on integrators**

No changes to Connect app settings or the OAuth flow are required. A self-hosted portal user may need to configure their own developer key in Vibecode.

**Affected endpoints:** [GET /v1/connect/authorize](/docs/partner-connect), [POST /v1/connect/device/authorize](/docs/partner-connect), [POST /v1/connect/token](/docs/partner-connect).

### FIX-0914-18: the dedicated server card returns the installed runtime after a successful deploy

**Before**

After a successful [POST /v1/infra/servers/:id/deploy](/docs/infra/deploy/deploy) with a `runtime` field on a dedicated server, [GET /v1/infra/servers/:id](/docs/infra/servers/get) returned `data.runtimeId: null` even though the `runtime` step had passed and the application responded. The documentation already promised that field to be filled, so a second deploy "to install the runtime" looked necessary even though the runtime was already in place. A galaxy application filled the same field on success.

**After**

After a successful deploy to a dedicated server, `GET` reflects the `runtime` from that request, for example `python311`. The `runtime` field stays optional on a dedicated server, and a request without it does not clear the previous value. A failed deploy still leaves the field empty, even when the `runtime` step did pass. The deploy response remains HTTP 200, the step list is unchanged, and `runtimeStatus` stays deprecated and empty. Values that are already empty are not backfilled by this fix — the next successful deploy carrying `runtime` fills them.

### BC-0914-19: the chat model field no longer matches models by substring

> Old format supported until: not provided

**Before**

[POST /v1/chat/completions](/docs/ai/chat/completions) accepted part of an identifier in `model` and picked the first model in catalog order whose identifier contained that substring. A request could run and be billed on a different model than the one named, and only the `model` field of the response revealed the substitution.

**After**

`model` is matched against the catalog only as a whole. It takes the full identifier or the same identifier without the provider prefix: `bitrixgpt-5.5` finds `bitrix/bitrixgpt-5.5`. A model found by its short name is flagged in the response with the `X-Model-Resolved` header carrying the full identifier. An identifier that is only part of a longer one, and a short name that matches several models, get `404 ai_model_not_found`.

**What integrators should do**

Pass the full identifier from [GET /v1/models](/docs/ai/models/list) in `model`. If responses carry the `X-Model-Resolved` header, replace the short name with its value.

### FIX-0914-20: smart-process custom fields answer the Bitrix24 refusal code, not "not found"

**Before**

The five custom-field operations of a smart process — `GET`, `POST /v1/items/{entityTypeId}/userfields` and `GET`, `PATCH`, `DELETE /v1/items/{entityTypeId}/userfields/{id}` — ask Bitrix24 for the smart process's internal id by its `entityTypeId` before acting. When Bitrix24 refused that request — the call limit was exceeded, Bitrix24 was unavailable or did not answer in time — the client got `404 SMART_PROCESS_NOT_FOUND`, as if the smart process did not exist. A "not found" answer is not one clients retry, and a client could conclude the smart process had been deleted and create it again.

**After**

A Bitrix24 refusal at this step answers the same way as on any other call to Bitrix24: `429 RATE_LIMITED` (including the limit Bitrix24 sends with status `503`) and `503 BITRIX_TIMEOUT` — with a `Retry-After` header, `502 BITRIX_UNAVAILABLE` — without one. On such a refusal the field request is not sent to Bitrix24. The successful response remains `200` (`201` for `POST`, `204` with no body for `DELETE`). `404 SMART_PROCESS_NOT_FOUND` means Bitrix24 does not know this `entityTypeId` or did not return its internal id — not that Bitrix24 was unavailable. The `/v1/userfields/invoices` alias (Smart Invoices) never asks for an internal id and is unchanged. In addition, on every operation that asks for a smart process's internal id (including `PATCH`, `DELETE /v1/smart-processes/{id}` and the batch update or delete via `POST /v1/smart-processes/batch`), a Bitrix24 answer with a `5xx` status is no longer taken for "not found" even when its text contains such words — for example the "page not found" page served by the proxy of an unavailable on-premise portal: such an answer arrives as `502 BITRIX_UNAVAILABLE`. Code details — on the [Errors](/docs/errors) page.

### BC-0914-21: the quote response drops Bitrix24 service fields, the contacts field is marked as not returned

> Old format supported until: not provided

**Before**

[GET /v1/quotes/{id}](/docs/entities/quotes/get) (and the list, search and `include`) returned 17 fields that are in neither the description nor the reference: Bitrix24's full-text index string `searchContent` (carrying the transliterated title and the responsible's name), display copies of dates (`dateCreateShort`, `dateModifyShort`, `begindateShort`, `closedateShort`), the internal codes `contentType`, `termsType`, `commentsType`, `entityTypeId`, an empty `hasProducts` and seven client-requisite columns `clientTitle`, `clientAddr`, `clientContact`, `clientEmail`, `clientPhone`, `clientTpId`, `clientTpaId` — through the API they stay empty even on a quote with a bound company and contact, and a sent value is dropped. The declared `contacts` field never arrived, while `select=contacts` was accepted and answered `200` without that key. [GET /v1/invoices/{id}](/docs/entities/invoices/get) carried the service `entityTypeId`, and `lastActivityTime` came with a `+03:00` offset while every other date of the record was in UTC.

**After**

Seventeen service fields of the quote are excluded from the response; the read response remains `200`. The `contacts` field is marked in the description and the reference as not returned (`notReturned`): the Bitrix24 item API never returns it for quotes, the bound contacts are in `contactIds`; a write of `contacts` still answers `400 READONLY_FIELD`, and `select=contacts` now answers `400 SELECT_FIELD_NOT_RETURNED` instead of `200` without the key. On the invoice, `entityTypeId` is excluded from the response and `lastActivityTime` is declared as a read-only field returned in UTC like every other date of the record; as before, it is not accepted in `filter` or `order`, and a value sent on write — which Bitrix24 never stored — is now refused: create and update answer `400 READONLY_FIELD`, import `400 IMPORT_ITEM_VALIDATION`, entity batch `400 BATCH_ITEM_VALIDATION`, and the global batch `READONLY_FIELD` under the call in `data.errors`.

**What integrators should do**

If you read the quote's service fields (`searchContent`, `*Short`, `contentType`, `termsType`, `commentsType`, `entityTypeId`, `hasProducts`, `client*`) — they are gone; run full-text search through the `title` filter and take the client requisites from the bound [contact](/docs/entities/contacts/get) and [company](/docs/entities/companies/get) by `contactId` and `companyId`. If the quote `select` included `contacts` — remove it (in batch sub-calls too): the field was never returned, the bindings are in `contactIds`. If you sent the invoice's `lastActivityTime` — drop it from the body: Bitrix24 sets it. Sending `client*` on create or update is ignored by Bitrix24 as before — the platform flags it with the `UNRECOGNIZED_WRITE_FIELD` hint.

**Affected endpoints:** [GET /v1/quotes/{id}](/docs/entities/quotes/get), [GET /v1/quotes](/docs/entities/quotes/list), [POST /v1/quotes/search](/docs/entities/quotes/search), [GET /v1/quotes/fields](/docs/entities/quotes/fields), [GET /v1/invoices/{id}](/docs/entities/invoices/get), [GET /v1/invoices](/docs/entities/invoices/list), [POST /v1/invoices/search](/docs/entities/invoices/search), [GET /v1/invoices/fields](/docs/entities/invoices/fields), [POST /v1/invoices](/docs/entities/invoices/create), [PATCH /v1/invoices/{id}](/docs/entities/invoices/update), [POST /v1/{entity}/batch](/docs/batch), [POST /v1/batch](/docs/batch).

### NEW-0914-22: reasoning from earlier responses in the chat completion history

[POST /v1/chat/completions](/docs/ai/chat/completions) accepts the `reasoning_content` field on assistant messages — the model's reasoning from an earlier response, sent back into the conversation history. Some reasoning models in function-calling dialogs read the reasoning of earlier assistant turns and lose the thread between calls without it. Previously the field was silently dropped.

The field reaches the model when its `owned_by` in [GET /v1/models](/docs/ai/models/list) is `bitrix`, `openrouter` or `vibecode`. It is not sent to models of OpenAI, Anthropic and other OpenAI-compatible providers: their APIs do not accept such a field. On messages with other roles the field is ignored, `null` is the same as omitting the field, and an empty string is accepted. A model that reads the reasoning counts it as input tokens. A non-string value or one longer than 4,000,000 characters is rejected with `400 invalid_request`.

### FIX-0914-23: rate limit descriptions state the platform-wide cap and point at the header with the effective value

**Before**

Documentation pages and the machine-readable `GET /v1/openapi.json` schema stated a rate limit as a single number — 60 requests per minute for [`POST /v1/search`](/docs/search/run), 20 for [`POST /v1/research`](/docs/search/research), 30 for [`POST /v1/batch`](/docs/batch), 600 and 120 for reading notifications, 120 for calendar settings, 30 for workday records, 20 for booking resources, 10 and 30 for AI provider keys, 10 for SSH access, the app icon, the port, wake schedules and Deploy API operations, 6 for force-releasing a stuck lock, 60 for polling operation status, 20 for ticket comments and 60 for the public storage link. Requests are served by several platform processes, each holding its own share of the cap, so none of those numbers ever reached the client: the `x-ratelimit-limit` header returned less, and a client that pinned the number from the description hit `429` earlier than expected. Partner Connect stated a single number the same way: 30 requests per minute for `GET /v1/connect/authorize`, 60 for `POST /v1/connect/token` and 60 for `POST /v1/connect/revoke`. The external application API (`ANY /v1/applications/:id/api/*`) stated a single number the same way — 120 requests per minute per key — both in the limits table on its documentation page and in the agent hints of `/v1/guide` and `/v1/me`.

**After**

Every such description states the number as a platform-wide total and points at the source of the effective value — the `x-ratelimit-limit` response header — and says that the cap is divided across platform processes. The same correction was applied to the `429` refusal descriptions in the machine-readable schema. The limit that is NOT divided and reaches the client exactly as stated is marked separately: access token minting `TOKEN_MINT_RATE_LIMIT` (50 per hour per API key). The Marketplace trial activation limit carries no such marker and needs none by construction: its cap is multiplied by the number of platform processes, so the client receives exactly the printed 3 per hour whatever that number is. The schema words it two ways — "3 per hour per portal" and "3 per hour per Bitrix24 account". The Partner Connect descriptions above now point at the header as well, on the documentation page and in the schema, key revocation included. The external application API received the same note, in all three places at once. One more cap that is NOT divided across processes is marked alongside them: the edge rate zone (nginx) on `POST /v1/connect/token` — 20 requests per minute per caller address. It counts before a request is distributed across processes, answers the RFC 6749 envelope and sets no `x-ratelimit-*` header, which is how that header's absence tells it apart from the route's own cap.

**Impact on integrators**

Endpoint behaviour did not change and the responses are the same — the description that disagreed with them was corrected. A client that read `x-ratelimit-limit` changes nothing. A client that pinned the number from the description in code should switch to the header: the platform-wide number is divided across processes and changes without a journal entry.

### FIX-0914-24: the default reasoning step is sent to the model explicitly

**Before**

When a request to [POST /v1/chat/completions](/docs/ai/chat/completions) carried none of `reasoning_effort`, `reasoning` and `chat_template_kwargs`, nothing was added to the call of a model with a reasoning declaration, and the model provider decided the mode. An update of the model on the provider's side could change that mode. The response's `reasoning` field still reported the `default` step from the declaration.

**After**

The platform sends the model the `default` step from the `reasoning` field of the [GET /v1/models](/docs/ai/models/list) response explicitly, so the behavior of a request without the parameter does not depend on updates on the provider's side. An explicitly requested step still takes precedence over `default`. The response's `reasoning` field and the `X-Reasoning-Applied` and `X-Reasoning-Native` headers describe the step that was sent. Nothing changes for models with `reasoning: null`.

**Impact on integrators**

No action is needed. To enable reasoning in a request, pass `reasoning_effort` or the `reasoning` object. The model's `reasoning.default` shows the step applied without the parameter.

### BC-0914-25: the application external API answers a timeout with 503 instead of 504

> Old format supported until: not provided

**Before**

The application failed to answer within the overall call ceiling and [ANY /v1/applications/{id}/api/**](/docs/applications/external-api) returned `504` with the code `APP_API_TIMEOUT` and no `Retry-After` header.

**After**

The same outcome arrives as `503` with the code `APP_API_TIMEOUT` and a `Retry-After` header in seconds. The refusal code is unchanged, so a timeout is still distinguishable from `APP_API_UNAVAILABLE`, which means an unreachable or saturated channel. This address no longer answers `504` at all: seeing one means it came from an intermediate node on the way to the platform, not from the platform.

**What integrators should do**

Move the timeout branch from the status to the refusal code: read `error.code` rather than `504`. A client that already branches on `error.code` needs no change. A client that treated `503` as unconditionally retryable now gets a `Retry-After` on a timeout — but retrying a non-idempotent call stays risky: the application may have completed the work after the channel stopped waiting.
