For AI agents: markdown of this page — /docs-content-en/changelog/2026-08-24.md documentation index — /llms.txt
API changes: August 24, 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
200with 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.