For AI agents: markdown of this page — /docs-content-en/changelog/2026-08-24.md documentation index — /llms.txt

API changes: August 24, 2026

← Changelog · August 2026

BC-0824-1: activity type can no longer be changed after creation

Old format supported until: not provided

Before

PATCH /v1/activities/:id accepted the typeId field. The value never reached storage: an activity type is fixed at creation, so it was discarded. A request carrying typeId as its only field ended up with an empty field set and returned the opaque refusal Fields is not specified., which gives no hint that immutability of the type is the reason. A request that also carried at least one writable field answered with success, so the caller believed the type had changed.

After

typeId is declared as a field that is set only on creation. PATCH /v1/activities/:id carrying it returns 400 READONLY_FIELD and names the field. Both batch update operations answer the same way. POST /v1/activities still accepts the field, where it stays mandatory. In the GET /v1/activities/fields output, typeId now carries the createOnly marker.

What integrators should do

Remove typeId from the body of PATCH /v1/activities/:id. If the type genuinely has to change, create an activity with the required type and delete the previous one — the type of an existing activity cannot be edited. The createOnly marker in the GET /v1/activities/fields response lets you tell such fields apart before sending a request.

FIX-0824-2: paid accounts no longer receive an error asking them to pay again

Before

POST /v1/apps could return a 403 error asking a paid account to upgrade when application installation through Bitrix24 failed.

After

When Bitrix24 confirms that the plan is paid, the method returns the technical error 502 CONNECTOR_REST_UNAVAILABLE with a safe reason and no upgrade prompt. A confirmed unpaid plan still returns a 403 plan error.

Impact on integrations

Requests require no changes. The technical error can be retried, while the plan error requires an upgrade.

BC-0824-3: the deployment block changes shape for Belarusian accounts along with their access model

Old format supported until: not provided

Before

An account licensed in Belarus landed in the limited-access bucket under three conditions at once: it held a demo subscription, it held no paid subscription, and it had no history of commercial payments. Its Bitrix24 plan — paid or free — did not affect membership, whereas an account that had ever paid before did not land in the bucket at all. In GET /v1/me such an account received a deployment block with no galaxyApp sub-block, with primary = standalone and with a placementNote field explaining that no galaxy host of its own is created for it and that an app must be deployed in two steps. A one-shot create carrying source answered 400 SOURCE_AT_CREATE_GALAXY_ONLY.

After

The plan-based model has no limited-access bucket at all, so a Belarusian account leaves it in both directions at once: on a paid or demo Bitrix24 plan it gets full access, on a free plan it is denied. In both cases the deployment block changes shape the same way — provided galaxy placement is open to the account and it does not yet have a galaxy of its own (both carve-outs are named below): the deployment.galaxyApp sub-block appears, the deployment.placementNote field disappears, and deployment.primary switches from standalone to galaxyApp. For an account with full access a one-shot create carrying source starts working.

What integrators should do

Detect the placement model by the PRESENCE of the deployment.galaxyApp sub-block, exactly as the response reference prescribes. Rewrite any branch keyed on the presence of placementNote or on the value of primary: both fields move with the account's access model, not only with its plan. Read the permission to create a server separately, from capabilities.servers.create: the deployment block describes the placement CONTRACT and is present for a denied account too, while POST /v1/infra/servers answers such an account with 402. Two carve-outs where the response shape does not change at all. The first is an account with galaxy placement switched off: neither field is present before or after. The second is an account that already has a galaxy: placementNote explained the absence of a galaxy of its own, so the owner of a live galaxy host received galaxyApp and no placementNote while in the bucket too. The change reaches an account at the moment it is moved onto the plan-based model, so both response shapes occur side by side across accounts.

NEW-0824-4: the Bitrix24 plan becomes the access condition for accounts licensed in Belarus

Vibecode admits an account to the infrastructure either by its Bitrix24 plan or by a subscription, depending on the licence region the account belongs to. Accounts licensed in Belarus — served by a separate Vibecode deployment, not by this one — move onto the plan-based model: a paid or a demo Bitrix24 plan grants access there, and an account with neither is declined. The move is staged, account by account.

Nothing changes on this deployment and no action is required. Access here has always been granted by the Bitrix24 plan alone: a commercial plan grants full access, a demo plan grants a limited trial, and on a free plan POST /v1/infra/servers — like an app publish, a wake of a sleeping machine or the issuance of a new key — is still declined with 402 and INT_TARIFF_REQUIRED, which GET /v1/me also reports in capabilities.servers.create.reason. No new field, no new denial code and no new branch appear in the contract you consume here.

FIX-0824-5: the server-creation hint in the key response no longer leads nowhere

Before

An account whose access is granted by a Bitrix24 plan rather than a subscription received a capabilities.servers.create slot in GET /v1/me carrying a generic wording: servers are available on commercial plans or during an active trial. That was wrong twice over. Such an account is not entitled to the trial — the entitlement is computed on the subscription model — and the address where a plan is chosen was not named at all. Separately, for accounts licensed in Belarus the alternatives[].url field pointed at the subscription checkout inside the account itself, and would have kept pointing there after the account moved onto the plan-based model, where a subscription no longer resolves the denial.

After

The slot names the working paths and the address: a paid or demo Bitrix24 plan, and for Belarus a paid subscription as well. The text in capabilities.servers.create.userMessage now matches the 402 body that POST /v1/infra/servers returns for the same account — one denial code no longer says different things on two surfaces. For accounts licensed in Belarus that have moved onto the plan-based model, alternatives[].url points at the plan-selection page instead of the subscription checkout.

Impact on integrators

No action required: a text field and a URL changed value, the response structure is unchanged. The fix reaches Kazakhstan and Uzbekistan at once, and Belarus as each account is moved onto the plan-based model. If you render your own copy instead of userMessage, review it: the promise of a trial is wrong for these accounts.

FIX-0824-6: the denial text for Kazakhstan and Uzbekistan no longer offers a subscription

Before

On the deployment that serves Kazakhstan and Uzbekistan an account on a free plan was refused with the subscription-model text and was asked to activate a subscription that is not sold in those countries. The action named in the text could not be performed, and the working paths to access — a paid or a demo Bitrix24 plan — were not named at all, nor was the address where a plan is chosen.

After

Such an account is now refused with the plan-based code of its own region, and the text names both working paths and the address. The subscription brand is gone from it. The correction reaches every surface where an access denial is visible to the client: server creation (POST /v1/infra/servers), an app publish, a wake of a sleeping machine and the issuance of a new key, as well as capabilities.servers.create.reason in GET /v1/me.

Nothing changes on this deployment and no action is required here. Access on this surface is granted by the Bitrix24 plan alone, a free-plan denial is still answered with 402 and INT_TARIFF_REQUIRED, and neither the request nor the shape of the response changes. The regional denial codes corrected above are reachable only on the deployment named there.

BC-0824-7: bot re-authorization is now explicit and safe

Old format supported until: not provided

Before

POST /v1/bots/:botId/reauth could clear any disabled bot state, while 410 BOT_DISABLED did not tell clients whether automatic recovery was allowed.

After

410 BOT_DISABLED includes boolean error.details.reauthAllowed. Call POST /v1/bots/:botId/reauth automatically only when reauthAllowed=true; the server emits that signal only for writable bots disabled by authentication failures and enables it gradually. A manual call also remains the credential probe for an active bot after ownership transfer. Other disabled states now fail immediately with 409 BOT_REAUTH_NOT_ALLOWED; a concurrent state change returns 409 BOT_REAUTH_STATE_CHANGED. Update clients that called re-authorization for every BOT_DISABLED response.

FIX-0824-8: galaxy application deploy warns when environment variables are reset

Before

A successful /deploy without user env recreated the galaxy application without previous variables but did not report that in the response.

After

The response includes a warnings[] entry asking callers to send the complete env on every deploy. A development-team member's deploy, where the owner's variables are preserved, receives no false warning.

Impact

The deploy status and behaviour are unchanged; clients should read the existing warnings[] array.

NEW-0824-9: task dependencies are now available through the API

Before

The Bitrix24 task card shows a "Related tasks" block, but there was no way to read those links through the API: no dependency fields in the task list, none in a task read by id, nothing about them in the task field description, and no dedicated endpoint. A dashboard that needed the dependency graph could not build it.

After

Two read-only endpoints were added. GET /v1/tasks/:taskId/dependencies returns the dependencies of one task as an array of id-and-title pairs, sorted by id. POST /v1/tasks/dependencies/bulk takes up to 50 tasks and answers per task: successes in results, failures in errors, counters in meta.

The bulk call answers 200 even when every sub-call failed — partial failure is the whole point of it, so what has to be read is errors, not only results. Duplicate ids collapse silently and the requested counter counts unique ids, so "requested" always equals "succeeded" plus "failed".

Boundaries, stated explicitly

Only predecessors are returned — the tasks the requested one depends on. Bitrix24 exposes no reverse direction through the API, so a dashboard builds it by inverting the pairs it collected. The link type is readable by no Bitrix24 method, so it is absent from the response entirely: an empty or guessed value in a contract is worse than a missing field.

Links added through the Gantt chart are invisible to these endpoints: Bitrix24 keeps them separately and returns them from no read method. Telling "there are no links" apart from "there are links, in the invisible store" is impossible here and in raw REST alike.

A task carrying more dependencies than the endpoint returns gets an explicit refusal rather than a truncated list: the response is either complete or a refusal.

Impact on integrators

There are no breaking changes — both routes are new. Writing dependencies did not get an endpoint of its own: the set is still changed through the DEPENDS_ON field on task update, and the semantics there are a full replacement of the set rather than an addition.

FIX-0824-10: international bot access keeps the Bitrix24 plan model

Before

The international instance already governed account access through the Bitrix24 plan model. Bot permission failures returned 403 BITRIX_ACCESS_DENIED.

After

There is no change to that .com contract: bot access stays on the international plan model. GET /v1/me?refresh=tariff continues to refresh the account's Bitrix24 plan state after an upgrade.

What integrators should do

Keep handling international access through the existing plan errors. No new bot error branch is required on .com.

BC-0824-11: opening a workday no longer confirms an expired state

Old format supported until: not provided

Before

POST /v1/workday/open returned 200 success:true when Bitrix24 left the workday in the EXPIRED status. No new workday was opened.

After

An unchanged EXPIRED status is returned as HTTP 409 with success:false and the WORKDAY_EXPIRED code. The instructions say to read status for the same user, close the expired day using its timeStart date and a report, and then retry open.

What integrators should do

Handle success:false and HTTP 409 as an explicit signal that the workday was not opened; resolve the previous day's state using the response hint first.

NEW-0824-12: calendar events can be linked to CRM elements

A calendar event now carries a crmFields field — the link between a meeting and CRM elements: deals, leads, contacts and companies. The field is readable and writable, is declared in GET /v1/calendar-events/fields, and is available in select.

The value is an array of typed references: D_<id> deal, C_<id> contact, L_<id> lead, CO_<id> company. On create and update the value must be an array; [] clears every link, and omitting the field from the body keeps the stored ones. Clearing with an empty array works on POST and PATCH; in a batch request an empty array is refused rather than silently succeeding — a batch sub-call cannot carry one. On POST /v1/batch that is INVALID_PARAMS in data.errors under the call's id; on POST /v1/calendar-events/batch it is 400 BATCH_ITEM_VALIDATION for the whole batch, with the name INVALID_PARAMS and the item index inside message. An event with no links reads back as [] — the empty value never arrives as null or an empty string, so a crmFields.length check is always safe. An unknown prefix, or a reference to a record that does not exist, is rejected.

Affected endpoints: GET /v1/calendar-events, GET /v1/calendar-events/:id, POST /v1/calendar-events/search, POST /v1/calendar-events, PATCH /v1/calendar-events/:id, GET /v1/calendar-events/fields.

FIX-0824-13: an application on a galaxy host that does not boot can be deleted without a live tunnel

Before

DELETE /v1/infra/servers/{id} on a galaxy application answered 502 with the code GALAXY_HOST_UNREACHABLE whenever the host was offline, whatever the reason. When the host guest operating system does not boot at all (the provisionErrorCode field of the server record equals GUEST_NOT_BOOTING), the tunnel will never come back, so retrying helped neither a minute later nor a day later. Deleting the host itself was blocked too: it answered 409 with the code GALAXY_HAS_APPS, because its applications formally remained alive. The owner ended up in a closed loop, still holding a quota slot with a machine that no longer runs.

After

Once the platform has proven that the host guest operating system does not boot, an application on that host is deleted without contacting the host: DELETE /v1/infra/servers/{id} answers 200, the application record is closed, and its access tokens, domain and catalog item are released. After deleting the applications one by one, the owner deletes the host itself with the regular call — the GALAXY_HAS_APPS refusal no longer appears. The GALAXY_HOST_UNREACHABLE code keeps its previous meaning for every other case: the host is temporarily offline and retrying makes sense. Important: the does-not-boot mark alone does not guarantee the 200: before deleting without contacting the host, the platform also confirms through the gateway that no live tunnel exists. That check is fail-safe — an unreachable gateway, an answer without a connection list, or a host that came back meanwhile all keep the answer at 502. Clients need no changes — the retry loop for this state simply stops being necessary.

BC-0824-14: an unknown select field name is refused with 400 on almost every entity

Old format supported until: 18.02.2027

Until now such a request answered 200 with the requested field simply missing from the records — so the "old format" here means an incomplete answer, not a working one.

Before

A field name the entity does not have went into the selection silently. The request ran, the field was absent from the records, and the explanation sat in meta.warnings — where nobody looks. A typo in select therefore looked like a successful request with mysteriously incomplete records:

GET /v1/deals?select=id,titel      →  200, records carry only id

Only calendar events answered such a name with an error.

After

The request is refused before the Bitrix24 call — 400 with the UNKNOWN_SELECT_FIELD code and the list of accepted names in the message. That list is the precise answer to "what may I ask for".

It applies to the entities whose field set has been verified against Bitrix24: deals, contacts, companies, leads, quotes, activities, addresses, smart processes, products and product sections, catalogs with their products and sections, orders and order statuses, statuses, currencies, calendar sections, files, folders, storages, departments, workgroups, document templates. Everywhere else the behaviour is unchanged — a warning in meta.warnings.

A separate class is a name the entity DOES have but never returns: GET /v1/{entity}/fields shows such a field with notReturned: true. In this cohort that is, for example, currencyId on products and sort on product sections. It is refused with a 400 too, but under its own SELECT_FIELD_NOT_RETURNED code and a message that names the reason. The separate code is deliberate: UNKNOWN_SELECT_FIELD claims the name does not exist, while the entity's own field catalogue publishes it — a client that honestly took the name from there would otherwise read the answer as "the catalogue is lying".

Only the name is checked. Custom fields (UF_*, ufCrm*) are accepted as before on every entity; product properties are each accepted on THEIR OWN entity: PROPERTY_295 on products, property295 on catalog products, where their numbers are assigned by Bitrix24; the other spelling is not understood by the method and the gate rejects it. A * (or UF_*) value still means "return every field", and a typo next to it causes no refusal — a warning arrives instead. In both batch calls — the global one and the per-entity one — the selection refuses only its own sub-call while neighbouring ones still run.

What integrators should do

Check the field names in your select against the list in the error message or against the GET /v1/{entity}/fields schema. A request that used to "work" but returned records missing some of the requested fields will now answer 400 naming exactly which name was not found — which was its original mistake.

FIX-0824-15: the `datePeriod` field schema is now visible in `GET /v1/bookings/fields`

Before

The datePeriod field was described as "type": "object" with no nested schema. The shape of the object could not be learned from the contract itself — a client would send {} or a date string, get 422 BITRIX_ERROR, and could only guess the required keys from the error text.

After

Fields of type object with a known nested shape now carry a properties key holding a recursive schema of the nested keys. For datePeriod that is from and to, each with timestamp (number, Unix seconds) and timezone (string, an IANA zone name). The same key now appears for requisiteLink in GET /v1/orders/fields, and on both surfaces at once — fieldsDetailed in GET /v1/guide carries it too, so the shape is visible without Bitrix24 tokens. Arrays of objects still carry no element schema. The change is additive: existing field-description keys stay in place, and create-time validation was not tightened.

NEW-0824-16: Scrum kanban stages and sprint listing in the API

Four operations for working with the columns of a Scrum board. Stages belong to a sprint rather than to a workgroup — different sprints of one project hold independent sets of columns — so the collection is addressed through the sprint.

GET /v1/scrum/sprints returns the sprints of a project. It is the only way to obtain the sprintId the other three operations need; without the groupId parameter it returns every sprint the key can see.

GET /v1/scrum/sprints/:sprintId/stages returns the columns of a sprint, converting id, sort and sprintId to numbers. POST /v1/scrum/sprints/:sprintId/stages creates a column and returns it re-read in full, including the defaults Bitrix24 substitutes. PATCH /v1/scrum/stages/:stageId renames, recolours and reorders a column.

Platform-side validation closes the places where Bitrix24 answers with success and stores something else: a name longer than 255 characters, a colour longer than six characters and a type outside NEW, WORK, FINISH now get a clear refusal instead of a silent substitution. A colour may be sent with a leading #, which is stripped.

Moving a column to another sprint is not exposed: sprintId in the request body is rejected. Updating a stage that does not exist, or that belongs to a project the key cannot access, answers STAGE_NOT_FOUND_OR_NO_ACCESS — the two cases cannot be told apart, because Bitrix24 answers both identically.

FIX-0824-17: ACCOUNT_FROZEN is now documented on server creation

The 402 response of POST /v1/infra/servers listed only the plan, trial and Marketplace-subscription refusals. It omitted ACCOUNT_FROZEN, the code the platform answers to an account whose wallet is frozen, even though the endpoint already returned it: the balance check runs ahead of the handler, and server creation is not exempt from it.

Because of the omission, a client generated from /v1/openapi.json treated the code as impossible and dropped a refusal that has a clear remedy — top up the balance. Endpoint behaviour is unchanged; only the description was.