For AI agents: markdown of this page — /docs-content-en/changelog/2026-07-31.md documentation index — /llms.txt
API changes: July 31, 2026
BC-0731-1: source uploads require Content-Length
Old format supported until: 30.01.2027
The source-upload endpoints — POST /v1/apps/{id}/sources and POST /v1/infra/servers/{id}/sources — now accept a body only with the Content-Length header. A request without it (chunked transfer, Transfer-Encoding: chunked) gets 411 with code MISSING_CONTENT_LENGTH.
The reason: the archive body is no longer assembled in memory in full — it is forwarded to storage as it arrives, and that requires the length to be known up front.
The vast majority of clients already send the header: curl --data-binary, fetch with a buffer body and any HTTP client posting a whole file all set it. Only clients that deliberately stream a body of unknown length are affected.
Re-saving an identical archive also costs a little more now: the content match is determined after the body has been received, so the response comes slightly later and the volume counts toward storage operations. The outcome is unchanged — deduplicated: true and the same version.
What integrators should do
Send the archive as a whole (--data-binary @file in curl, a buffer or a file as the request body) rather than as a stream of unknown length. If your client streams the body itself, compute the size up front and set Content-Length.
FIX-0731-2: tariff name in GET /v1/me comes from the platform edition catalogue, in English
Before
The data.tariff.name field came from a stored tariff snapshot: the licence name as the account reported it, or — when the account reported none — a value from an internal dictionary that had no language awareness. On some accounts it was not a tariff name at all: the response carried either a Russian-language plan name on a non-Russian account, or the licence code itself, such as pro100, presented as a human-readable name.
After
The name is resolved at response time. When the tariff code is known to the platform edition catalogue, the field comes from there in English, so an account now receives Demo period; the name reported by the account is not used in that case, so the label can also change where nothing was wrong. When the code is not in the catalogue, the field still carries the name reported by the account, verbatim and in its own language. Only when there is no name at all, or the only candidate is the licence code itself, is the field null — the licence code is never substituted for a name. The field type is unchanged: string or null, and the code itself is still available in data.tariff.code.
Three edition labels were also renamed to fuller forms: the demo plan is now Demo period, the legacy free plan is now Project — legacy free, and the partner licence is now NFR — partner licence. Their previous values were the short Russian-language forms, so a client comparing this field by string should re-check the comparison.
FIX-0731-3: server user search returns active employees only
Before
GET /v1/infra/servers/:id/b24-users could return inactive users and users who are not employees.
After
The endpoint returns only users confirmed as active Bitrix24 employees. No integration changes are required.
NEW-0731-4: an app now decides for itself whether the placement iframe auto-height is on
Apps gained an optional placementResizeEnabled field (defaults to false). It controls whether the platform serves a wrapper page on a placement open that fits the iframe height to your app's content.
The field is returned by GET /v1/apps and GET /v1/apps/:id and accepted by PATCH /v1/apps/:id. Existing calls keep working unchanged: every existing app carries false, so the placement open behaves exactly as before.
Turn it on only together with a change on the app side. The wrapper opens the app in a nested iframe on the platform origin, so the app gains a new ancestor origin. If your app sends its own Content-Security-Policy header with a frame-ancestors directive, add the platform origin to it — otherwise the browser refuses to open the app. Apps without their own frame-ancestors directive need no change.
If your app already had the auto-height working, turn the field on to keep the previous behaviour. Note that the field is a necessary condition, not the only one: the capability itself is rolled out account by account.
To report its height, the app posts a { type: 'vibe:resize', height } message to the parent window — the contract is described in App inside Bitrix24.
FIX-0731-5: an empty body with the JSON header is no longer rejected on the infrastructure routes
Before
An operation that needs no body answered 400 with the FST_ERR_CTP_EMPTY_JSON_BODY code when a client sent the Content-Type: application/json header with no body. Clients that attach this header to every request do that — axios and PowerShell Invoke-RestMethod, for example. The refusal happened while parsing the body, that is, before the key was checked, so the response gave no way to tell what was wrong with access. It affected DELETE /v1/infra/servers/:id/access-tokens/:tokenId, POST /v1/infra/servers/:id/wake and the rest of the body-less server operations.
After
An empty body is accepted as {}, and the operation answers on the merits — 401 on a wrong key, 404 on a server that does not exist, 200 on success. The former workaround of passing an explicit {} body keeps working. An unparsable body on these routes now returns the INVALID_JSON_BODY code instead of FST_ERR_CTP_INVALID_JSON_BODY — the same code the neighbouring operations of the same server already returned, including deploy, exec and lock.