[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"docs-changelog\u002F2026-09-29":3,"docs-tabs-changelog\u002F2026-09-29":6},{"content":4,"lastmod":5},"# API changes: September 29, 2026\n\n[← Changelog](\u002Fdocs\u002Fchangelog) · [September 2026](\u002Fdocs\u002Fchangelog\u002F2026-09)\n\n### NEW-0929-1: Catalog measure and VAT rate reference data\n\nThe Vibecode API now provides `GET`, `POST`, `PATCH`, and `DELETE` for `\u002Fv1\u002Fcatalog-measures` and `\u002Fv1\u002Fcatalog-vat-rates`. Clients can read valid `measure` and `vatId` values before creating a product. Search, fields, and batch are also available for both entities.\n\n### BC-0929-2: employee and requisite sorting now orders by identifier\n\n> Old format supported until: not provided\n\n**Before**\n\n`sort=-id` and `order[id]=desc` did not change the order of employees, requisites, and requisite presets. Sorting employees by another ordinary field could be silently ignored while the request returned HTTP 200 with rows.\n\n**After**\n\nBoth forms sort these lists by `id` in descending order on single endpoints, search, and `POST \u002Fv1\u002Fbatch`. For employees, `id` is the only supported ordinary sort field. Other ordinary fields are rejected with `UNKNOWN_SORT_FIELD`. `UF_*` keeps its previous passthrough on one page and is rejected with `INVALID_SORT_FIELD` for multi-page retrieval. Responses to supported requests remain HTTP 200.\n\n**What integrators need to do**\n\nID sort requests need no changes. Do not use other ordinary employee fields. Keep `UF_*` to single-page requests and remember that its order still depends on Bitrix24.\n\n**Affected endpoints:** [GET \u002Fv1\u002Fusers](\u002Fdocs\u002Fentities\u002Fusers\u002Flist), [POST \u002Fv1\u002Fusers\u002Fsearch](\u002Fdocs\u002Fentities\u002Fusers\u002Fsearch), [GET \u002Fv1\u002Frequisites](\u002Fdocs\u002Fentities\u002Frequisites\u002Flist), [POST \u002Fv1\u002Frequisites\u002Fsearch](\u002Fdocs\u002Fentities\u002Frequisites\u002Fsearch), [GET \u002Fv1\u002Frequisite-presets](\u002Fdocs\u002Fentities\u002Frequisite-presets\u002Flist), [POST \u002Fv1\u002Frequisite-presets\u002Fsearch](\u002Fdocs\u002Fentities\u002Frequisite-presets\u002Fsearch), [POST \u002Fv1\u002Fbatch](\u002Fdocs\u002Fbatch).\n\n### NEW-0929-5: catalog services are available through V1\n\nThe Vibecode API now provides `\u002Fv1\u002Fcatalog-services` for listing, searching, reading, creating, updating, and deleting services. List and search require `filter.iblockId`. Service prices use the existing `\u002Fv1\u002Fcatalog-prices` endpoint.\n\n### NEW-0929-8: connector gateway for Cowork\n\nThe Vibecode API answers `POST \u002Fv1\u002Fconnectors\u002Fmcp`, an MCP gateway through which the Cowork desktop calls tools of connected services. The gateway accepts only the Cowork desktop key, any other key gets `403 CONNECTOR_KEY_NOT_ALLOWED`. While the feature is not enabled, the path answers `404 ROUTE_NOT_FOUND`.\n\n### FIX-0929-9: the Cowork tier change preview quotes the discounted price\n\n**Before**\n\n`GET \u002Fv1\u002Fcowork\u002Fsubscription\u002Fpreview` quoted the plan price for the term in `chargeVibes` and `netVibes` even when a platform discount applied to the purchase: the purchase then charged less than the preview showed.\n\n**After**\n\n`chargeVibes` and `netVibes` include the discount this purchase will receive — exactly the amount that will be charged. Renewing a plan that is already paid and repeating the current plan get no discount, the same as the purchase itself. The response shape is unchanged and the response remains HTTP 200.\n\n### NEW-0929-10: cause and action in Bitrix24 permission and scope refusals\n\n`403 BITRIX_ACCESS_DENIED` responses and `422 BITRIX_ERROR` responses whose `b24Code` is `ACCESS_DENIED_EXTEND` or `NO_AUTH_FOUND` carry new optional fields. `error.cause` distinguishes a refusal by the rights of the Bitrix24 user (`b24_permission`), a scope missing on the key's credential (`b24_scope`) and a cause that cannot be determined (`unknown`). `error.fix` names the action (`action`) and where it is performed (`via`); `error.method` is the Bitrix24 method, at most 100 characters; `error.requiredScope` is the missing scope when it is known; `error.hint` is always present on these refusals. The values of `cause`, `fix.action` and `fix.via` are open sets: read an unknown value as `unknown` or `none`. Response codes and statuses are unchanged. Values explained — [Authorization, keys and permissions](\u002Fdocs\u002Ferrors\u002Fauth#bitrix_access_denied-403).\n\n### FIX-0929-11: a post permission refusal returns an English message\n\n**Before**\n\n[PATCH \u002Fv1\u002Fposts\u002F{id}](\u002Fdocs\u002Ffeed\u002Fposts\u002Fupdate), [DELETE \u002Fv1\u002Fposts\u002F{id}](\u002Fdocs\u002Ffeed\u002Fposts\u002Fdelete) and [POST \u002Fv1\u002Fposts\u002F{id}\u002Fshare](\u002Fdocs\u002Ffeed\u002Fposts\u002Fshare) returned the Bitrix24 account's text as is in `error.message` when Bitrix24 refused access to the post — on a Russian-language account that text was in Russian.\n\n**After**\n\n`error.message` of such a refusal is the fixed English text `Bitrix24 denied access to this post.`, and the response also carries `error.cause`, `error.method`, `error.fix` and `error.hint`. The code and status are unchanged — `403 BITRIX_ACCESS_DENIED`.\n\n**Impact on integrators**\n\nClient code that branches on `error.code` needs no change. Parsing the `error.message` text of this refusal is no longer needed.\n\n### BC-0929-12: File and folder search validates both supplied parent folder IDs\n\n> Old format supported until: not provided\n\n**Before**\n\nIn [POST \u002Fv1\u002Ffiles\u002Fsearch](\u002Fdocs\u002Fentities\u002Ffiles\u002Fsearch) and [POST \u002Fv1\u002Ffolders\u002Fsearch](\u002Fdocs\u002Fentities\u002Ffolders\u002Fsearch), a parent folder ID could be supplied both at the body top level and in `filter`. If one value was valid, a malformed value in the other location could reach the Disk call or go unnoticed.\n\n**After**\n\nBoth supplied values must be non-empty scalars. A request with an object, array, `null`, or an empty string in either location is rejected before the Disk call. Two valid values still use the top-level value.\n\n**What integrators should do**\n\nIf an ID is present in both locations, remove the malformed value and keep the valid `folderId` or `parentId`. Such a request could previously succeed when the valid value was at the top level.\n\n### BC-0929-14: chat read boundaries, file metadata and publication recovery\n\n> Old format supported until: not provided\n\n**Before** A personal `vibe_api_*` key in `READONLY` mode received `403 WRITE_BLOCKED_READONLY_KEY` for [GET \u002Fv1\u002Fchats\u002F{dialogId}\u002Fload](\u002Fdocs\u002Fchats\u002Fmessages\u002Fload), [GET \u002Fv1\u002Fchats\u002F{dialogId}\u002Fmessages?format=v2](\u002Fdocs\u002Fchats\u002Fmessages\u002Flist), and [GET \u002Fv1\u002Fchats\u002Fmessages\u002F{messageId}\u002Fcontext](\u002Fdocs\u002Fchats\u002Fmessages\u002Fcontext).\n\n**After** These employee reads are allowed when the key has the `im` scope and the user has Bitrix24 access, the successful read response remains HTTP 200. If the chat allows auto-join, the call may make the employee a member. Bitrix24 updates presence on these reads. Chat loading may also trigger lazy project conversion. REST parameters cannot disable these effects. The method bodies do not mark messages read. Explicit state-changing commands remain blocked for a read-only key.\n\n**What integrators should do** A personal employee read-only key can perform these named reads without enabling write commands. Guest session authentication is outside this contract. Successful response shapes are unchanged.\n\n**Before** [GET \u002Fv1\u002Fchats\u002Ffiles\u002F{fileId}](\u002Fdocs\u002Fchats\u002Ffiles\u002Ffile-get) accepted an `im`-only key and looked up an arbitrary Disk file ID. Message [PATCH \u002Fv1\u002Fchats\u002F{dialogId}\u002Fmessages\u002F{messageId}](\u002Fdocs\u002Fchats\u002Fmessages\u002Fupdate) and [DELETE \u002Fv1\u002Fchats\u002F{dialogId}\u002Fmessages\u002F{messageId}](\u002Fdocs\u002Fchats\u002Fmessages\u002Fdelete) did not verify that `messageId` belonged to `dialogId`.\n\n**After** READONLY requires an existing chat: `chatN`, or a numeric peer (including a resolved `me`) proved by the same employee’s recent list. The check scans at most 4000 raw rows; an unproved binding receives `403 WRITE_BLOCKED_READONLY_KEY` before a method that could create a chat. Metadata requires both `im` and `disk`, plus the user’s Bitrix24 access to the file. A missing scope returns `403 SCOPE_DENIED` before contacting Bitrix24. A message mutation is permitted only after finding the exact ID in the named dialog’s visible history. A mismatch returns `404 MESSAGE_NOT_FOUND_IN_DIALOG`, a received lookup response that cannot confirm membership returns `503 MESSAGE_MEMBERSHIP_UNAVAILABLE`; other preflight errors retain their ordinary API status and code. Neither refusal sends a mutation. In the [GET \u002Fv1\u002Fchats\u002Frecent](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Frecent), offset counts visible unique rows. Window validation is bounded to 20 pages or 4,000 rows, returning `503 RECENT_WINDOW_UNAVAILABLE` instead of partial success when the budget is exceeded. Metadata contains eight fields: `id`, `name`, `size`, `type`, `detailUrl`, `createdBy`, `createdAt`, `updatedAt`. The former optional `downloadUrl` is removed from metadata and successful file uploads to avoid returning a URL containing Bitrix24 credentials. Successful HTTP 200 message mutation responses are preserved. Chat file upload still requires `im`. In [POST \u002Fv1\u002Fchats\u002Fmessages\u002Fbulk](\u002Fdocs\u002Fchats\u002Fmessages\u002Fbulk), a duplicate computed key (`id`, otherwise `dialogId`) now returns `400 INVALID_PARAMS` before any call to Bitrix24 instead of dropping the first item. Unique string keys, including Object property names, are preserved. Batch cursors accept non-negative safe integers and decimal-digit strings within the same range; null continues to omit a cursor. Validation and normalization run before sending the request to the Bitrix24 account. Incomplete or contradictory batch outcomes and unusable event polling responses return `502 BITRIX_ERROR` instead of a false HTTP 200. An empty recent page claiming continuation, or a row without a confirmed ID, returns `503 RECENT_WINDOW_UNAVAILABLE`; healthy response shapes are preserved.\n\n**What integrators should do** For a read-only key, use an existing `chatN` or a private binding from recent dialogs; handle an unproved-context refusal. Add `disk` to metadata-reading keys. For bytes, replace `downloadUrl` with authenticated [GET \u002Fv1\u002Ffiles\u002F{fileId}\u002Fdownload](\u002Fdocs\u002Fentities\u002Ffiles\u002Fdownload), using `disk` or `crm`. Pass the dialog that contains the message to be changed. Handle membership refusals and do not try to mutate a message through a different dialog. Use the v2 cursor for deep recent-list navigation and handle temporary window-check refusal. The former `im`-only access closes immediately to correct the scope boundary.\n\n**Before** A publication failure after uploading a file to Drive did not explain whether the file remained. Automatic replay or deletion after an ambiguous refusal could create a duplicate or delete an attached file.\n\n**After** [POST \u002Fv1\u002Fchats\u002F{chatId}\u002Ffiles](\u002Fdocs\u002Fchats\u002Ffiles\u002Fupload) does not automatically replay upload or publication. A failure after upload preserves its original status and code and adds `meta.uploadRecovery` with the file and chat IDs and the publication and cleanup outcomes. Deletion is permitted only after a confirmed pre-attachment refusal and affects only this request’s file. An unknown outcome preserves the file. The successful HTTP 201 response contains `fileId`, `name`, `size`, without the former optional `downloadUrl`.\n\n**What integrators should do** Inspect chat history and the named file’s metadata before recovery. Do not automatically replay an upload whose publication outcome is unknown.\n\n**Before** [GET \u002Fv1\u002Fchats\u002F{chatId}\u002Ffolder](\u002Fdocs\u002Fchats\u002Ffiles\u002Ffolder) could initialize a missing Drive folder with a read-only key.\n\n**After** Initialization requires `READWRITE`; closing modes receive `403 WRITE_BLOCKED_READONLY_KEY` before this method is called. File listing, metadata and byte reads retain their read rules.\n\n**What integrators should do** Use a key with write access to retrieve the folder. After upload, verified local refusals before publication dispatch permit deletion of only this request's file; unknown outcomes preserve it. Upload, publication and compensation do not automatically replay after 429 or scope refusals.\n\n**Before** [POST \u002Fv1\u002Fchats](\u002Fdocs\u002Fchats\u002Fmanagement\u002Fcreate) forwarded `users` without local validation; malformed entries could produce a Bitrix24 error or be dropped when creating the chat.\n\n**After** Before `im.chat.add`, a provided list is checked as an array of positive safe integer IDs. Numbers and canonical decimal strings without leading zeros or spaces are normalized to numbers; malformed input receives `400 INVALID_PARAMS` before the method call. An omitted list or an empty array remains valid. The READONLY write refusal still precedes body validation. Entity-binding fields, including opaque `entityId` values such as `DEAL|1663`, are preserved.\n\n**What integrators should do** Send valid participant IDs instead of relying on malformed values being silently dropped. Correct the list shape before retrying after `400 INVALID_PARAMS`.\n\n### NEW-0929-16: catalog SKUs and offers are available through V1\n\nThe API now provides `\u002Fv1\u002Fcatalog-skus` and `\u002Fv1\u002Fcatalog-offers` for listing, searching, reading, creating, updating, and deleting records. List and search require the relevant catalog's `filter.iblockId`. An offer can be free or linked to a parent SKU through `parentId` on creation.\n\n### NEW-0929-17: Chats: dialog list sections, shared chats, changes since a moment, chat pinning and reading\n\nThe chats section gained ten endpoints on the Bitrix24 messenger v2 methods. Dialog list sections are read in pages: [GET \u002Fv1\u002Fchats\u002Frecent\u002Fchannels](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Frecent-channels) returns public channels by the `lastMessageId` cursor, [GET \u002Fv1\u002Fchats\u002Frecent\u002Fcollabs](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Frecent-collabs) returns collab chats, and [GET \u002Fv1\u002Fchats\u002Frecent\u002Fexternal](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Frecent-external) returns the chats of one section by its `type` code, such as task chats or calendar event chats, both by the `lastMessageDate` cursor and the `hasNextPage` flag. [GET \u002Fv1\u002Fchats\u002Fshared](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Fshared) returns the chats shared with the given employee, and [GET \u002Fv1\u002Fchats\u002Fsync](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Fsync) returns changes to chats, messages and pins since the given moment. A chat is pinned in the dialog list with [POST \u002Fv1\u002Fchats\u002F:dialogId\u002Fpin](\u002Fdocs\u002Fchats\u002Fmanagement\u002Fpin), its position among the pinned chats is set with [PUT \u002Fv1\u002Fchats\u002F:dialogId\u002Fpin](\u002Fdocs\u002Fchats\u002Fmanagement\u002Fpin-sort), and the pin is removed with [DELETE \u002Fv1\u002Fchats\u002F:dialogId\u002Fpin](\u002Fdocs\u002Fchats\u002Fmanagement\u002Funpin). [POST \u002Fv1\u002Fchats\u002Fread-all](\u002Fdocs\u002Fchats\u002Fmanagement\u002Fread-all) marks all of the user's chats as read, and [POST \u002Fv1\u002Fchats\u002Frecent\u002Fread](\u002Fdocs\u002Fchats\u002Fmanagement\u002Fread-section) marks the chats of one list section as read. Limits outside the range are clamped with an echo in `meta`, and an unknown or repeated parameter or an extra body field is refused with `400 INVALID_PARAMS`. Pinning, changing the pinned order and marking as read are writes: a read-only key gets `403 WRITE_BLOCKED_READONLY_KEY` for them, as described on the [access rights](\u002Fdocs\u002Faccess-rights) page.\n\n### FIX-0929-18: The legacy chat list supports deep offsets again\n\n[GET \u002Fv1\u002Fchats\u002Frecent](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Frecent) without `format=v2` again forwards a deep `OFFSET` to Bitrix24 and reads one page with a possible refill for a hollow boundary row, as before. Prefix replay, the 4,000-row window and the new `503 RECENT_WINDOW_UNAVAILABLE` refusals were removed. Ordinary keys also retain the original query parameters for legacy message reads; the READONLY protected-selector filter remains.\n\n### NEW-0929-19: write catalog list-property values through V1\n\nThe Vibecode API now supports creating, partially updating, and deleting list-property options: `POST \u002Fv1\u002Fcatalog-product-property-enums`, `PATCH \u002Fv1\u002Fcatalog-product-property-enums\u002F:id`, and `DELETE \u002Fv1\u002Fcatalog-product-property-enums\u002F:id`. A partial update fills omitted Bitrix24-required fields from the existing record.\n\n### NEW-0929-20: cause and a ready transfer step in the BOT_ACCESS_DENIED refusal\n\nThe `403 BOT_ACCESS_DENIED` response (the bot is bound to another API key) carries new optional fields: `error.cause` with the value `bot_other_key`, `error.fix` and `error.hint`. When the calling key can run the transfer to itself, `error.fix` is `{ \"action\": \"transfer_bot\", \"via\": \"same_key\", \"path\", \"body\" }`: `path` is the ready route `POST \u002Fv1\u002Fbots\u002F{botId}\u002Ftransfer` with the bot identifier from the request, and `body` holds the identifier of the calling key itself. The response never names the key the bot is bound to. Otherwise `error.fix.action` is `none`, and `error.hint` names the reason. The code, status and `error.message` are unchanged. Details — [Authorization, keys and permissions](\u002Fdocs\u002Ferrors\u002Fauth#bot_access_denied-403).\n",null,{},1794739481571]