[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"docs-changelog\u002F2026-08-10":3,"docs-tabs-changelog\u002F2026-08-10":6},{"content":4,"lastmod":5},"# API changes: August 10, 2026\n\n[← Changelog](\u002Fdocs\u002Fchangelog) · [August 2026](\u002Fdocs\u002Fchangelog\u002F2026-08)\n\n### NEW-0810-1: issuing a share link is recorded in the account access journal\n\nThe [POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Faccess-tokens](\u002Fdocs\u002Finfra\u002Faccess-tokens) response is unchanged — what changes is what happens on the account side.\n\n**Before**\n\nIssuing a `mode=share-url` link left no trace in the account oversight layer: an administrator could not see who opened an application with a link, or when.\n\n**After**\n\nAfter a link is issued, the platform records the exposure change in the account journal, and — when the link does not require a Bitrix24 sign-in (`identityBound=false`) and the application was not already open to outsiders — sends the account administrators a chat-bot message linking to the list of open applications.\n\n**Impact on integrators**\n\nThe request format, the response and the error codes are unchanged — no client change is needed. Note that every open link you issue is now visible to the account administrators.\n\n### BC-0810-2: a filter error in POST \u002Fv1\u002F{entity}\u002Fbatch is now a per-sub-call error, not a whole-request one\n\n> Old format supported until: 04.02.2027\n\n**Before**\n\nOne bad filter key in any sub-call of [POST \u002Fv1\u002F{entity}\u002Fbatch](\u002Fdocs\u002Fbatch) cancelled the\nwhole request: `400`, the code in `error.code`, and the results of every other sub-call\ndiscarded. The global [POST \u002Fv1\u002Fbatch](\u002Fdocs\u002Fbatch) behaved differently — it placed the error\nnext to the sub-call that caused it and ran the rest.\n\n**After**\n\nBoth surfaces behave the same way. The response is `200`, the refusal code sits in\n`data[i].error.code` for the sub-call that caused it, and the remaining sub-calls run and\nreturn their data. The set of refusals and their codes is unchanged — only the blast radius\nis: `UNKNOWN_FILTER_FIELD`, `INVALID_FILTER_OPERATOR`, `INVALID_FILTER_FIELD`,\n`UNSUPPORTED_FILTER`.\n\nThe message used to be prefixed with `Call at index N:` — the sub-call's position is now\nvisible from its place in the `data` array, so the prefix is gone.\n\n**Integrator migration**\n\nIf your code reads a filter refusal as `HTTP 400` with `error.code`, add handling for `200`\nwith `data[i].error.code` — otherwise a sub-call whose filter was refused will read as\nsuccessful. Check each `data` element for an `error`, exactly as you already do for the\nglobal `POST \u002Fv1\u002Fbatch`.\n\n### BC-0810-3: batch reads no longer bypass an operation the entity turns off\n\n> Old format supported until: 04.02.2027\n\n**Before**\n\nAn entity can turn a single operation off — usually because the generic handler is wrong for\nit: the real list lives on its own route with a different envelope, or the Bitrix24 method\nignores the filter and returns the whole table. The single routes honoured that, and so did\nbatch writes, but batch reads did not. So [POST \u002Fv1\u002F{entity}\u002Fbatch](\u002Fdocs\u002Fbatch) and\n[POST \u002Fv1\u002Fbatch](\u002Fdocs\u002Fbatch) with `action` `list`, `get`, `search` or `fields` answered\n`200` where the same operation answers `404` on its own route — serving exactly the result the entity\nturned the operation off to avoid.\n\nSeparately, the legacy `GET \u002Fv1\u002F{entity}\u002Faggregate` never asked whether the entity has an\naggregate at all. For an entity whose every numeric field is an identifier,\n`POST \u002Fv1\u002F{entity}\u002Faggregate` answers `404` while this address answered `200`.\n\n**After**\n\nBoth batch surfaces answer a disabled operation with `400 ACTION_NOT_SUPPORTED` before any\nBitrix24 call: on the per-entity batch that is the whole request, on the global one it is a\nper-sub-call error and the remaining sub-calls still run. The legacy\n`GET \u002Fv1\u002F{entity}\u002Faggregate` is registered by the same predicate as its `POST` sibling, so an\nentity without an aggregate now answers `404` on both.\n\n**Integrator impact**\n\nOnly the entity-and-operation pairs whose answer was already wrong are affected. Check all\nfour reads — `list`, `get`, `search`, `fields`: six entities disable `search` while keeping a\nworking `list`, so a batch that used to go through whole now answers `ACTION_NOT_SUPPORTED`\non that sub-call. The full\nset of actions is in `operations.batch` of the `GET \u002Fv1\u002Fguide` response and in the OpenAPI\ndescription; `data.batch` of `GET \u002Fv1\u002F{entity}\u002Ffields` lists WRITE actions only and cannot\nanswer the question about reads. An entity with every\noperation off keeps its route, but every action answers `ACTION_NOT_SUPPORTED` — the refusal\nnames the action, which a `404` on the path cannot.\n\n### BC-0810-4: a `filter` that is not an object is refused instead of being lost\n\n> Old format supported until: 04.02.2027\n\n> As in the sibling entry about an unknown field name, \"the old format\" here means a wrong\n> answer, not a working one.\n\n**Before**\n\n`filter` is an object of conditions, but nothing stopped a client sending a string, a number,\na boolean or an array instead. A string and an array went to Bitrix24 as they were, a number\nand a boolean became an empty filter — and in every case the request answered `200` with the\nWHOLE collection:\n\n```\nPOST \u002Fv1\u002Ftasks\u002Fsearch   { \"filter\": [{ \"responsibleId\": 1 }] }   ->  200, every task on the account\n```\n\n**After**\n\nSuch a request is refused before the Bitrix24 call — `400` with the code\n`INVALID_FILTER_SHAPE`; the message says what arrived instead of an object and shows the\ncorrect form.\n\nThis applies on every entity and every surface where `filter` arrives in a body: search,\naggregate and both batches.\n\n**Integrator migration**\n\nSend `filter` as an object. The query string is a separate story: conditions are written in\nthe bracket form there (`?filter[responsibleId]=1`), and a `filter` JSON-encoded as one string\nis no longer dropped as of this release — it is parsed and applied, where it used to be lost\nsilently and return the whole collection.\n\n### BC-0810-5: an unknown filter field name is refused on fifteen more entities\n\n> Old format supported until: 04.02.2027\n\n> Until now such a filter answered `200` with the whole collection — so \"the old format\" here\n> means a wrong answer, not a working one.\n\n**Before**\n\nA filter on a name the entity does not have was sent to Bitrix24. Bitrix24 does not refuse\nsuch a key — it drops it silently and answers `200` with the WHOLE collection. A typo in a\nfield name therefore looked like a successful request with an implausibly large result:\n\n```\nGET \u002Fv1\u002Ftasks?filter[responsable]=1     →  200, every task on the account\n```\n\nThat was the behaviour of [tasks](\u002Fdocs\u002Fentities\u002Ftasks\u002Flist),\n[users](\u002Fdocs\u002Fentities\u002Fusers\u002Flist), [workgroups](\u002Fdocs\u002Fentities\u002Fworkgroups\u002Flist),\n[requisites](\u002Fdocs\u002Fentities\u002Frequisites\u002Flist), [bank details](\u002Fdocs\u002Fentities\u002Fbank-details\u002Flist),\n[requisite presets](\u002Fdocs\u002Fentities\u002Frequisite-presets\u002Flist),\n[addresses](\u002Fdocs\u002Fentities\u002Faddresses\u002Flist), [sites](\u002Fdocs\u002Fentities\u002Fsites\u002Flist),\n[pages](\u002Fdocs\u002Fentities\u002Fpages\u002Flist), [timeline comments](\u002Fdocs\u002Fentities\u002Ftimelines\u002Flist),\n[workflow templates](\u002Fdocs\u002Fentities\u002Fbizproc-templates\u002Flist), Open Channels configs and\nuniversal-list elements.\n\n**After**\n\nSuch a request is refused before the Bitrix24 call — `400` with the code\n`UNKNOWN_FILTER_FIELD` and the available names listed in the message — that list IS the\nprecise answer to \"what can I filter by\".\n\nOnly the NAME is checked: operators, ranges, `$in`\u002F`$nin` and AND logic behave as before.\nBesides declared fields it accepts custom fields (`UF_*`, `ufCrm*`), and the `id` key on the\nentities that declare one.\n\nSeparately, for [workflow activities](\u002Fdocs\u002Fentities\u002Fbizproc-activities\u002Flist) and\n[workflow robots](\u002Fdocs\u002Fentities\u002Fbizproc-robots\u002Flist) the Bitrix24 method accepts no filter in\nany form, so any filter key there is refused with the code `UNSUPPORTED_FILTER`.\n\nFull description — [Filtering and search](\u002Fdocs\u002Ffiltering#an-unknown-filter-field-name).\n\n**Integrator migration**\n\nCheck the field names in your filters against the list in the error message. A request that used\nto \"work\" but returned more records than it should will now answer `400` naming exactly which\nfield was not found — which is the mistake it always contained. Other filters are unaffected.\n\n### FIX-0810-6: a host out of free disk space is a distinct retryable deploy failure, not a broken app\n\n**Before**\n\nWhen the shared host of a galaxy app ran out of free disk space, the build failed and [POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fdeploy](\u002Fdocs\u002Finfra\u002Fdeploy\u002Fdeploy) answered `502 GALAXY_APP_BUILD_FAILED` — the same code as an error in the app's own source. The app was marked broken even though it never stopped working: the failure happened during the build, before the container was replaced, so the previous version went on answering requests. Telling a full disk apart from a genuine build error was only possible from the log tail in `buildLog`, and re-sending the same deploy produced the same result.\n\n**After**\n\nThe same case returns `502 GALAXY_LOW_DISK` with `retryable: true` and a structured `error.hint`: the cause, what to do, and a warning not to delete the slot. The app is not marked broken — the slot, its container and its data volume are intact, and the version already running keeps serving traffic. Re-send the deploy once space has been freed on the host: disk is not reclaimed on its own, so an immediate retry hits the same refusal. The new code is listed in the machine-readable deploy contract returned by [GET \u002Fv1\u002Fme](\u002Fdocs\u002Fquickstart) and `GET \u002Fv1\u002Fopenapi.json`.\n\n**Impact on integrators**\n\nNothing to change: successful deploys are unaffected. Keep your branch on `GALAXY_APP_BUILD_FAILED` — it still arrives for genuine build errors, while a full disk now has its own code that makes clear the problem is not in your source. An automatic retry happens only where the platform rebuilds an app that already exists: there attempts continue without client involvement until the wait budget runs out. When an app is created together with its source in one step, the refusal arrives right away and is not retried — the decision to retry is yours.\n\n### FIX-0810-7: A catalog launch now warns that the app is not authorized\n\n**Before**\n\nAn app opened from the Bitrix24 app catalog by a user who had not granted it access yet started as usual, but the gateway did not set the `X-Vibe-Authorization` header. API calls answered `401`, and the app displayed the text our own documentation prescribed for a `401` — \"re-open the app from the Bitrix24 menu\". That advice led nowhere: the user had just done exactly that, and a catalog launch does not grant access.\n\n**After**\n\nThe platform now intercepts such a launch and shows a screen with an \"Authorize the app\" button; the second route is to open the app once through a placement in the Bitrix24 menu. The same screen carries an unobtrusive \"open without authorizing\" link to the very same launch address, so an app that does not need the session opens exactly as before. The screen appears only where the button has somewhere to lead: a cloud account, an app key, and a registered OAuth application. Every other launch behaves as before.\n\n**Impact on integrators**\n\nNo code changes are required, and no launch becomes unavailable. Only your own `401` message is worth revising: the status has two causes — an expired session and access that was never granted — so \"re-open from the menu\" as the single wording misleads the user. The recommendation is updated in [App runtime](\u002Fdocs\u002Finfra\u002Fapp-runtime).\n\n### NEW-0810-8: CRM document list now present in the machine-readable OpenAPI schema\n\nThe [GET \u002Fv1\u002Fcrm-documents](\u002Fdocs\u002Fentities\u002Fdocuments\u002Fcrm-list) endpoint is now described in the OpenAPI schema served at `\u002Fv1\u002Fopenapi.json`. The call itself already worked, but clients and AI agents that build integrations from the machine-readable description treated it as non-existent. The description states the required `entityTypeId` parameter, the optional `entityId`, `select`, `order` and `start`, the required `crm` access, the response shape with the document array and the `meta` block holding `total`, `start` and `next`, plus the refusal codes `MISSING_PARAMS`, `INVALID_ENTITY_ID`, `INVALID_START`, `TOKEN_MISSING` and `SCOPE_DENIED`. The endpoint takes no page-size parameter and the description declares none: for the next page pass the `meta.next` value as `start`. The behaviour of the endpoint itself is unchanged.\n\n### FIX-0810-9: a direct-link visit now carries the visitor's name and access token\n\n**Before**\n\nAn app opened by its direct address (rather than from its tile inside Bitrix24) received the visitor's name from their Vibecode account instead of their employee card: someone who belongs to several Bitrix24 accounts saw the name they hold in a different one. The `X-Vibe-Authorization` header did not arrive on this path at all, so the app could not call Bitrix24 on the visitor's behalf.\n\n**After**\n\n`X-Vibe-User-Name` and `X-Vibe-User-Name-Encoded` carry the name from the employee card of the Bitrix24 account that owns the app — the same as on the tile path. The `X-Vibe-Authorization` access token is resolved by the employee id, so it arrives here too.\n\n**Impact on integrators**\n\nThe header format is unchanged, no client work is needed. When the employee card cannot be read, the name stays as before, taken from the Vibecode account: the header is never delivered empty.\n\n### FIX-0810-10: invoice user fields\n\n**Before**\n\nInvoice user fields could not be read or created through either path.\n[GET \u002Fv1\u002Fuserfields\u002Finvoices](\u002Fdocs\u002Fuserfields\u002Fsmart-processes) answered `UNKNOWN_ENTITY`, and\n[GET \u002Fv1\u002Fitems\u002F31\u002Fuserfields](\u002Fdocs\u002Fuserfields\u002Fsmart-processes) answered with a Bitrix24 access\nerror, because the invoice was addressed the same way as an ordinary smart process.\n\n**After**\n\nBoth paths work and return the same result: six operations (list, type catalog, read, create,\nupdate, delete) over invoice user fields. The `\u002Fv1\u002Fuserfields\u002Finvoices` path is there for callers\nwho prefer the entity name over the numeric type id.\n\n**Impact on integrators**\n\nNo action required. This covers invoices in their current form; legacy invoices remain\nunavailable through the API.\n\n### BC-0810-11: The product-row field reference now describes what the responses actually contain\n\n> Old format supported until: not provided\n\n**Before**\n\n[GET \u002Fv1\u002Fdeals\u002F{id}\u002Fproducts\u002Ffields](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-fields) returned the Bitrix24 field set verbatim, and it disagreed with the product-row responses in three places at once. The discount amount was called `discountSum` in the reference but `discount` in the data and on write. The external code and the account-currency price arrived in every row yet were missing from the reference. Owner, owner type and warehouse were the other way round: present in the reference, stripped from the responses.\n\nWorse, a client that generated its writer from this reference sent `discountSum` — the wrapper did not recognise the name, answered `201 Created` and discarded the discount silently. Any other unknown field behaved the same way: success reported, data not written.\n\n**After**\n\nThe reference is derived from the same tables that build the responses, so the two can no longer drift apart. The discount is called `discount`, matching the data, the write contract and the documentation. The previous name `discountSum` did not go away: it remains a deprecated alias, still returned by the reference and still accepted on write, so code written against the old field list keeps working — except that the discount now actually lands instead of being dropped silently. Product rows themselves carry only `discount`. `priceAccount` and `xmlId` were added — Bitrix24 returns them in rows but does not describe them in its own field set. `ownerId`, `ownerType` and `storeId` now arrive in the [list](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-get) and [single row](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-get-single) responses; `storeId` is `null` when inventory management is off.\n\n`isReadOnly` and `isRequired` describe this API's contract rather than the Bitrix24 one: `ownerId`, `ownerType`, `customized` and `measureName` are marked read-only because the wrapper cannot write them, and `ownerId` and `ownerType` are no longer required — they are taken from the request path. `id` gained a description: it is read-only as an attribute, and inside [PUT \u002Fproducts](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-set) items it is accepted. **Correction of 2026-08-18:** a live check showed that echoing `id` back does not preserve row identity — a row whose fields are unchanged keeps its `id` even with no `id` in the body, and a modified row comes back with a new `id`. To edit a row and keep its identifier, use `PATCH \u002Fv1\u002Fdeals\u002F:id\u002Fproducts\u002F:rowId`.\n\nA write carrying an unknown field name no longer reports success: [POST](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-add), [PUT](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-set) and [PATCH](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-update) return `400 INVALID_PARAMS` and list the writable fields. Read-only fields are still accepted and ignored, so an object read back via GET can be sent as is.\n\nA body `id` is accepted only inside [PUT \u002Fproducts](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-set) items. On [create](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-add) and [update](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-update) it is dropped: the row is identified by the request path there, and a body carrying the id of an existing row is exactly what you get by sending back an object read via GET.\n\nOn write, `taxIncluded` accepts a boolean again: `true` and `false` reach Bitrix24 as `Y` and `N`. The boolean used to be forwarded as is, leaving the row's tax inclusion effectively unset — so a row read via GET and sent straight back lost the flag. If you worked around this by sending `\"Y\"` and `\"N\"` as strings, nothing changes: that form is still accepted.\n\nWhen Bitrix24 returns incomplete metadata the reference still comes back complete, but the response now carries `meta.warnings[].code = \"fields_partial\"` — previously such an answer was indistinguishable from a healthy one. The warning text distinguishes two cases: no metadata arrived at all, or only some fields were left undescribed (it then names them).\n\n**What integrators should do**\n\n**What breaks is a write carrying a foreign key in the body.** Check that creating or updating a product row sends nothing beyond the writable fields — your own bookkeeping markers, leftovers from an internal model, Bitrix24 upper-case names (`PRICE_ACCOUNT`, `XML_ID`). Such a request used to answer `201 Created` and discard the value silently; it now answers `400 INVALID_PARAMS` and lists what is accepted. There is deliberately no support window for the old behaviour: it was the defect this change exists to fix, and keeping it alongside means keeping silent data loss. The full list of writable fields comes back in the refusal and in the [field reference](\u002Fdocs\u002Fentities\u002Fdeals\u002Fproducts-fields).\n\nNothing else needs changing. `discountSum` is still returned and still accepted — move to `discount` at your own pace, that is the name product rows carry, while the alias lives only in this reference. If you branch on `isReadOnly` or `isRequired`, re-check the new values for `ownerId`, `ownerType`, `customized` and `measureName`. If you replace rows wholesale, note that the identifiers of modified rows change: re-read the set via GET after the write.\n\n### FIX-0810-12: server member lookup no longer comes back empty because of a recent key without Bitrix24 access\n\n**Before**\n\nWhen a server's managing key granted no Bitrix24 access, `GET \u002Fv1\u002Finfra\u002Fservers\u002F{id}\u002Fb24-users`\nand the member lookup in the interface fell back to the server owner's personal keys, but checked\nonly one — the most recently created eligible key. If that key had neither a webhook nor an\ninstalled application token, the response came back empty (`data: []` with a hint) even though the\nowner had another active key with the required rights. Keys the platform issues itself for tasks\nthat never call Bitrix24 are always the most recent ones, so the lookup could stay broken\nindefinitely.\n\n**After**\n\nAll eligible personal keys of the owner are checked, newest to oldest, and the first one that\nreally has Bitrix24 access is used. Keys without access are skipped, and Bitrix24 still receives a\nsingle request. Key requirements are unchanged: as before, only an active, non-expired personal key\nof the server owner in the same account qualifies, and it must not be bound to an application.\n\nThe `hint` text is corrected as well: it used to name only an unauthorized app and a revoked key, so\nan active key looked revoked. A third reason is now named — no key grants Bitrix24 access — together\nwith the action to take, issuing a personal key with the required scope. The response shape is\nunchanged.\n\n### FIX-0810-13: placement bind names the install-rights refusal instead of a generic gateway error\n\n**Before**\n\nBitrix24 refused the embedding install and the account's plan state could not be confirmed at that moment — [POST \u002Fv1\u002Fplacements\u002Fbind](\u002Fdocs\u002Fapps\u002Fplacements\u002Fbind) answered `502 BITRIX_UNAVAILABLE` and put the Bitrix24 code into `details`. There was no named code in the answer, and no hint about what to do next. The refusal reached accounts whose plan already allowed the install.\n\n**After**\n\nWhen the check cannot be performed and the account is already on record as entitled in Vibecode, the same refusal arrives as `403 B24_EMBEDDING_INSTALL_DENIED` with `details.remedy` set to `install-rights`. No upgrade link is attached: the entitlement is there, what is missing is the right to install local applications. With no live entitlement from either source the answer stays `502 BITRIX_UNAVAILABLE`.\n\n**Impact on integrators**\n\nNothing to change. Your branch on `502 BITRIX_UNAVAILABLE` keeps working for the other refusals, while this case leaves it for `403`. Retrying it is pointless — the developer key has to belong to a user allowed to install local applications and holding access to the application.\n\n### BC-0810-14: commands, deploys and file uploads addressed by a galaxy host id are refused\n\n> Old format supported until: 07.08.2026\n\n**Before**\n\nA galaxy is a single machine that hosts the applications of several keys of one Bitrix24 account, each in its own container. The server list returns both the applications (`kind=GALAXY_APP`) and the machine carrying them (`kind=GALAXY`), and calling [POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fexec](\u002Fdocs\u002Finfra\u002Fdeploy\u002Fexec), [POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fdeploy](\u002Fdocs\u002Finfra\u002Fdeploy\u002Fdeploy) or [POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fupload](\u002Fdocs\u002Finfra\u002Fdeploy\u002Fupload) with the id of that machine ran on the machine itself, that is outside the caller's own container.\n\n**After**\n\nThe same call against a `GALAXY` machine is refused: commands return `403 GALAXY_HOST_EXEC_FORBIDDEN`, deploys and file uploads return `400 GALAXY_HOST_NOT_A_DEPLOY_TARGET`. The refusal names the replacement: address the application by its own id (`kind=GALAXY_APP`). Nothing changes for `STANDALONE` machines or for galaxy applications.\n\n**What integrators should do**\n\nTake your application's row from the server list (`kind=GALAXY_APP`) and use its id. If the flow relied on reaching the machine to learn how much disk space is left, that figure is now available as data rather than as the output of a command.\n\nThere is no support window for the previous behaviour: the refusal applies from the moment this ships. The reason is that the previous behaviour opened access to a machine carrying other keys' containers, and access like that cannot be kept alive for six months for the sake of compatibility.\n\n### NEW-0810-15: galaxy host disk usage is exposed in the server list\n\nA galaxy host row (`kind=GALAXY`) in [GET \u002Fv1\u002Finfra\u002Fservers](\u002Fdocs\u002Finfra\u002Fservers\u002Flist) and in the single-server response now carries four fields: `diskTotalMb` and `diskFreeMb` — size and free space in mebibytes, `diskState` — the verdict (`ok`, `warning`, `critical`, or `unknown` when nothing has been measured yet), `diskProbedAt` — the measurement time in ISO-8601.\n\nThe platform keeps both lines well clear of the edge: `warning` means space is running out, `critical` means less is left than the platform considers safe; both light up before a deploy actually runs out of room. The measurement refreshes on its own while the machine is awake; a sleeping machine shows the last known value together with its timestamp.\n\nFor `STANDALONE` machines and for galaxy applications (`kind=GALAXY_APP`) all four fields are `null`: the former are never probed, the latter have no disk of their own.\n\n### NEW-0810-16: agent model bitrix\u002Fbitrixgpt-5.6-agent\n\n[GET \u002Fv1\u002Fmodels](\u002Fdocs\u002Fai\u002Fmodels\u002Flist) now lists a new agent model, `bitrix\u002Fbitrixgpt-5.6-agent`, with a 1,048,576-token context. It supports streaming, tool calls (`tools`) and schema-constrained output — `response_format` with `type: \"json_schema\"`. The model public id is part of the `ai.structuredOutputs.models` list returned by [GET \u002Fv1\u002Fme](\u002Fdocs\u002Fkeys-auth\u002Fme).\n\nThe model is additive and replaces nothing: existing calls are unaffected.\n\n**Affected endpoints:** [GET \u002Fv1\u002Fmodels](\u002Fdocs\u002Fai\u002Fmodels\u002Flist), [POST \u002Fv1\u002Fchat\u002Fcompletions](\u002Fdocs\u002Fai\u002Fchat\u002Fcompletions), [GET \u002Fv1\u002Fme](\u002Fdocs\u002Fkeys-auth\u002Fme)\n\n### NEW-0810-17: bitrix\u002Fbitrixgpt-5.5-agent is deprecated\n\nResponses from [POST \u002Fv1\u002Fchat\u002Fcompletions](\u002Fdocs\u002Fai\u002Fchat\u002Fcompletions) for `bitrix\u002Fbitrixgpt-5.5-agent` now carry `Deprecation: true`, `X-Model-Replacement: bitrix\u002Fbitrixgpt-5.6-agent` and a `Link` header pointing at the successor (`rel=\"successor-version\"`).\n\nThe model keeps working without restrictions and stays in the [GET \u002Fv1\u002Fmodels](\u002Fdocs\u002Fai\u002Fmodels\u002Flist) listing. No shutdown date is set — the `Sunset` header is not sent, and no integration changes are required. The successor for new integrations is `bitrix\u002Fbitrixgpt-5.6-agent`.\n\n### FIX-0810-18: a transient database transaction failure no longer returns 500 with an internal engine code\n\n**Before**\n\nWhen a database transaction closed or expired before the operation finished, the request answered `500` and put the engine's internal code in the body — `{\"error\":{\"code\":\"P2028\"}}`. That code appears on no documentation page, the response carried no `Retry-After` header, and nothing in it said the request was worth repeating. It showed up most often on `DELETE \u002Fv1\u002Fapps\u002F{id}`: the application stayed in place and a retry looked pointless.\n\n**After**\n\nThe same class of failure returns `503` with code `DB_TRANSIENT`, an `error.retryAfter` field, and a `Retry-After` header — the same retry posture as `POOL_EXHAUSTED`. The change applies neither partially nor fully on such a failure, so a straight retry after a few seconds is safe. On the AI routes (`\u002Fv1\u002Fai\u002F*`, `\u002Fv1\u002Fchat\u002F*`, `\u002Fv1\u002Faudio\u002F*`, `\u002Fv1\u002Fmodels`) the code arrives lowercased — `db_transient` — in the OpenAI-compatible envelope. The engine's internal code no longer appears in the response body.\n\n**Impact on integrators**\n\nNothing to change. If your handler treated `500` as a terminal refusal, this case now arrives as `503` with a stated delay and falls into your retry branch instead. No special handling of the `DB_TRANSIENT` code is required: honouring `Retry-After` on any `503` is enough.\n\n### FIX-0810-19: preserveEnv no longer loses .env when a deploy fails after the directory is cleaned\n\n**Before**\n\nWith `cleanDeploy: true` together with `preserveEnv: true` the existing `.env` was read before the\nclean but written back only at the `env` step — after the runtime and the dependencies were\ninstalled. If the deploy aborted earlier, [POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fdeploy](\u002Fdocs\u002Finfra\u002Fdeploy\u002Fdeploy)\nanswered `DEPLOY_FAILED` and the directory was left with no `.env` at all. The application\nsettings had to be uploaded again by hand.\n\n**After**\n\nThe saved copy is put back on disk on any abort after the clean — on dependency install, on the\nruntime, on the archive download, on the clean itself, and when the connection to the server\ndrops. The restore is best-effort and adds no separate step to the response. The precedence rule\nis unchanged: an `env` passed in the same request still wins, and an explicit empty `env: {}`\nmeans \"clear it\" and does not bring the saved copy back. A successful deploy behaves exactly as\nbefore, including the time-zone injection for wake schedules. The flag still applies to a\ndedicated virtual machine only (`kind: \"STANDALONE\"`).\n\n**Impact on integrators**\n\nNothing to change on your side. The `DEPLOY_FAILED` response shape and the set of steps in\n`data.steps` are unchanged. If you worked around this defect by re-uploading `.env` by hand after\nevery failed deploy, that workaround is no longer needed.\n",null,{},1794739474414]