For AI agents: markdown of this page — /docs-content-en/changelog/2026-09-24.md documentation index — /llms.txt
API changes: September 24, 2026
NEW-0924-2: Multiplicity flag for Bitrix24 account fields in the entity fields description
In the GET /v1/{entity}/fields response (for example, GET /v1/deals/fields), a field that comes from the Bitrix24 account now carries multiple: true when Bitrix24 reports that the field accepts several values — for example, a multiple custom field ufCrm_*. Send the value of such a field as an array when creating or updating a record. The absence of multiple does not mean the field is single-valued: the flag is not emitted for fields the platform describes itself, or for fields whose multiplicity the Bitrix24 account did not report.
BC-0924-3: CRM document sorting takes one bracket level only
Old format supported until: not provided
Before
GET /v1/crm-documents accepted a second bracket level under the sorting field name. The spellings order[updateTime][]=desc and order[updateTime][0]=desc answered HTTP 200 and sorted the listing as if order[updateTime]=desc had been supplied — a sort the caller never wrote. The spelling order[updateTime][x]=desc answered HTTP 500.
After
A sorting entry must carry a direction, not a structure. A second bracket level under the field name — order[updateTime][x]=desc, order[updateTime][]=desc, order[updateTime][0]=desc — returns HTTP 400 INVALID_ORDER before Bitrix24 is called. The single-level spelling order[updateTime]=desc and the direction case work as before. An unknown direction is still dropped rather than refused, and a spelling the parser cannot place at all — order=desc, order[]=desc, a third bracket level — still leaves the listing unsorted.
What integrators need to do
Supply sorting with one bracket level: order[updateTime]=desc. If the query string is assembled from an array or an indexed list, convert it to that shape: the former spellings order[updateTime][]=desc and order[updateTime][0]=desc are now refused instead of sorted.
FIX-0924-4: Cowork ERP management status no longer asks for a confirmation code by default
Before
With platform two-factor protection on, GET /v1/cowork/onec/status returned admin.stepUp.required=true and a non-empty channels list to a Bitrix24 account administrator.
After
By default GET /v1/cowork/onec/status returns admin.stepUp={required:false,state:"NOT_REQUIRED",expiresAt:null,freshUntil:null,channels:[]} and does not offer the REQUEST_STEP_UP action. The response remains 200. The contract revision onec-cowork-management/v1-proposed-2026-09-21-r3 and the response shape are unchanged.
FIX-0924-5: the daily call allowance is counted by completed hours
Before
The X-RateLimit-Used and X-RateLimit-Remaining headers were described as including calls from the current hour, accurate to the minute.
After
Both headers count today's usage by completed hours: calls from the current hour are included once that hour ends, so the headers trail reality by up to 70 minutes and early in an hour may not reflect calls already made. The daily allowance size, the X-RateLimit-Quota header and the QUOTA_EXCEEDED refusal code are unchanged, and a call within the allowance still answers HTTP 200. Clients need no changes; if you need the exact remainder, account for your own current-hour calls on your side.
FIX-0924-6: the aggregation reference in GET /v1/guide describes POST aggregation and numeric-function fields by type
Before
The operations.aggregate block in GET /v1/guide described the deprecated GET …/aggregate with the op and field parameters and named aggregatableFields as the source of the field for sum/avg/min/max. For smart-process items (/v1/items/:entityTypeId) it pointed at GET /v1/items/:entityTypeId/aggregate, which does not exist. The 400 INVALID_PARAMS message about an unknown field in POST …/aggregate listed the same aggregatableFields instead of the numeric fields.
After
operations.aggregate describes POST …/aggregate with the aggregate[] array. The field for sum/avg/min/max is any field of type number from …/fields, or a numeric user field where the entity supports them (the ufSupport key is present). aggregatableFields lists the fields for groupBy. The 400 INVALID_PARAMS message lists the numeric fields of the entity, and for an entity without numeric fields it says This entity declares no number-typed field.. Where an entity has no user fields, the ufSupport key is gone, and neither the reference nor openapi.json promises them. The GET /v1/guide response remains HTTP 200, and the aggregation error code and status are unchanged.
Impact on integrators
If a client read params.op and params.field from the reference, switch to params.aggregate and call POST …/aggregate. Calls to the deprecated GET …/aggregate keep working as before.
NEW-0924-7: a default schedule for new machines
An administrator of the Bitrix24 account can mark the work schedule that new machines get by default: PUT /v1/work-schedules/:id/default with the body {"audience": "machines", "enabled": true}. There are two marks: machines covers servers and galaxy applications, agents covers agents and bots. The second one is separate, because an agent on a schedule sleeps outside its windows and answers no messages until the next window opens. Each audience has at most one marked schedule: a new mark moves over from the previous one, and "enabled": false removes it.
A server created through POST /v1/infra/servers without runMode gets the marked schedule. An explicit runMode, IDLE included, still wins over the mark, and machines that already exist keep their mode.
Every row of the library GET /v1/work-schedules now carries defaultForNewMachines and defaultForNewAgents. Only an administrator can change the mark, everyone else gets 403 ADMIN_ONLY.
FIX-0924-8: the run mode named at create now reaches a galaxy application
Before
POST /v1/infra/servers accepted the runMode block, but when the machine was placed in a galaxy the block was silently dropped: the application was created in the default mode. A schedule missing from the account was not refused in that case either.
After
The runMode block applies to a galaxy application too. A missing or empty schedule is refused before the create, exactly as for a standalone server: 400 WORK_SCHEDULE_NOT_FOUND or 400 WORK_SCHEDULE_EMPTY, and no application is created.
Impact on integrators
An integration that passes runMode gets the named mode without a separate PATCH /v1/infra/servers/:id/run-mode call. A missing schedule is now refused on galaxy placement too, as the documentation already promised.
FIX-0924-9: aggregation reports a Bitrix24 account error the same way the list does
Before
POST /v1/{entity}/aggregate and the deprecated GET /v1/{entity}/aggregate returned a
Bitrix24 account refusal without the explanations tied to the called method: the error body carried
no hint with the known limitation of that method and no warning that the same error had
already repeated. The list and search endpoints of the same entity answered the same refusal
with both fields. One Bitrix24 account refusal therefore looked different to a client depending on
which address had been called.
After
Both aggregation endpoints report one cause with the same code and the same explanations as
GET /v1/{entity} and POST /v1/{entity}/search. The error body now carries a hint with
the known limitation of the called Bitrix24 method, and a warning when the refusal repeats.
Successful aggregation responses are unchanged, and their success status codes stay the same.
NEW-0924-10: new refusal code `agent_turn_loop_detected` for a looping agent turn
POST /v1/chat/completions gained the refusal code agent_turn_loop_detected (409) for a looping agent turn. The refusal is not in effect yet: such requests are served as before, and existing integrations keep working unchanged. Enabling the refusal will be announced in a separate BC entry with a date.
Refusal condition once enabled: messages carries 15 or more model answers with the assistant role and no tool_calls after the last message with the user role. Every such answer after the last user message is counted, not only consecutive ones: tool calls in between do not reset the count. Answers with tool_calls are not counted themselves, so a turn in which the model calls tools at every step does not meet the condition. No model call is made for such a request, so the loop does not consume the limit. To continue, send a new user message — the count starts over.
FIX-0924-11: an empty `fields` in a bot request body no longer swallows the flat fields
Before
A body of {"fields": [], "command": "help", "title": "Help"} — how an empty dictionary serialises,
for instance via PHP json_encode([]) — was taken for the Bitrix24 format and reached the Bitrix24 account as
fields: []. The command and title actually sent were dropped in silence, with no warning in the
response. The same on PATCH /v1/bots/{botId} and PATCH /v1/bots/{botId}/chats/{dialogId}, where
null, false, 0 and an empty string posed as an empty wrapper too: the request went to the Bitrix24 account
verbatim, the account answered 200, and nothing changed.
After
An empty fields wrapper no longer counts as a wrapper — the body is read as flat and reaches
Bitrix24 whole. Affects POST /v1/bots/{botId}/commands, PATCH /v1/bots/{botId}/commands/{commandId},
PATCH /v1/bots/{botId} and
PATCH /v1/bots/{botId}/chats/{dialogId}. A non-empty wrapper is still forwarded unchanged. Two
consequences: the fields key no longer shows up in warning.droppedFields, and an unrecognised
top-level key is dropped when the body is folded — it never reached Bitrix24 anyway.
FIX-0924-14: A bot events request with an explicit offset below the stored one no longer moves the cursor
Before
GET /v1/bots/{botId}/events with an explicit offset below the stored position (for example, offset=0 for debugging) moved the stored cursor whenever the response carried events. The next ordinary request without offset went out with the new position, Bitrix24 deleted the events handed to the debug request as acknowledged, and the bot's main loop never received them.
After
An explicit offset below the stored position returns events without moving the cursor, and the response carries persisted: false. An explicit offset equal to or above the stored position moves the cursor as before. Bitrix24 deletes acknowledged events, so offset=0 shows only the events still unacknowledged in the queue, not the full history.
Impact on integrators
No action needed. A debug request with offset=0 no longer takes events away from the main loop, and paging by nextOffset works as before.
NEW-0924-15: resubscribe now reports the event mode Bitrix24 holds
A bot in fetch mode receives events only while Bitrix24 holds that same mode for it. That
value is the authoritative one and it can drift apart from the one the Vibecode platform
stores — and then GET /v1/bots/{botId}/events succeeds, reports
no error, and the queue stays empty indefinitely.
The POST /v1/bots/{botId}/resubscribe response now
carries three new fields. b24EventMode is the mode Bitrix24 held BEFORE the call (null
when Bitrix24 did not report it). diverged says whether it differed from the eventMode
the platform stores. hint says what the call actually did and what to check next.
The distinction matters: Bitrix24 rebinds events only on a REAL mode change. When the modes
already matched, the call rebound nothing, and the former { resubscribed: true } answer
read as a completed recovery. That case is now stated outright, and the hint points at the
causes upstream of the queue — chat membership, and whether a mention-only bot is actually
mentioned.
The hint returned by GET /v1/bots/{botId}/events after a run of empty polls was rewritten
from the same analysis: it labels eventMode as the platform's own value and sends you to
resubscribe for the authoritative one.
NEW-0924-16: sign-in to a deployed app with a Cowork desktop key
The new endpoint POST /v1/cowork/app-login takes the address of a deployed app and returns the same address with an added __gw_token parameter and its lifetime expiresIn. The Cowork/Code built-in browser that opens this address signs in to the app as the key owner, with their Bitrix24 user ID, without a sign-in form. The token opens only this app. The endpoint accepts only a Cowork/Code desktop key with the vibe:cowork scope. An inexact app address is refused with 400 INVALID_APP_URL, every access outcome with a single 404 APP_NOT_AVAILABLE, and an unknown Bitrix24 user ID with 409 B24_USER_UNKNOWN.
BC-0924-17: list methods check the key before reading the body and answer 401 without one
Old format supported until: not provided
Before
On every /v1/lists/* method the key was checked after the platform had read and parsed the request body. A request without a key or with an invalid key therefore got an answer about the body, not about the key: 400 INVALID_JSON_BODY on JSON that failed to parse and 413 PAYLOAD_TOO_LARGE on a body over 1 MB, for example on POST /v1/lists/:iblockId/elements. The server read the whole body for any sender.
After
The key is checked first, before the body is read. A request without a key or with an invalid key on any /v1/lists/* method gets 401 whatever the size and content of the body, and the body is not read. This removes the ability to make the server read a large body without a key — the precondition for letting an element write accept a body of up to 40 MiB. Responses to requests with a valid key are unchanged.
What integrators should do
Nothing, if the key is sent. If your code tells apart responses to a request without a key or with an invalid key by the 400 or 413 codes, switch that check to 401.
FIX-0924-18: a file in a list element property is no longer capped at 1 MB
Before
The value of a "File" property of a list element travels in the request body as base64, and the element write body was capped at 1 MB. The practical ceiling for one file was about 750 KB: POST /v1/lists/:iblockId/elements and PATCH /v1/lists/:iblockId/elements/:elementId with a larger file answered 413 PAYLOAD_TOO_LARGE, and nothing was written. The same file in a deal or contact field went through.
After
The body of a list element create and update is capped at 40 MiB, the same as CRM entity writes — just under 30 MiB of original file after base64. The other list methods and batch calls (POST /v1/batch) keep the previous 1 MB cap, so send a large file in a single call.
An element write with a body over 1 MB shares the limit on concurrently processed large bodies with CRM entity writes: when it is taken, the response is 429 LARGE_BODY_BACKEND_BUSY with a Retry-After: 5 header, the request was not executed, and it has to be retried.
Impact on integrators
No action required: a request that used to get 413 now goes through. The call to Bitrix24 is limited to 15 seconds and is not retried, so a file right at the limit on a slow account may get BITRIX_TIMEOUT — leave some headroom.