# API changes: October 6, 2026

[← Changelog](/docs/changelog) · [October 2026](/docs/changelog/2026-10)

### BC-1006-1: Comment files return only current metadata

> Old format supported until: not provided

**Before**

[GET /v1/posts/comments](/docs/posts/comments/read) returned file metadata together with any additional fields in the Bitrix24 response.

**After**

`files` retains `id`, `date`, `type`, `name`, `size`, `image`, `authorId`, `authorName`, `urlPreview`, `urlShow`, `urlDownload`. `image` retains only `width` and `height`. Unknown fields and values with incorrect types are omitted. Links containing credentials remain redacted.

**What integrators should do**

Use only the listed fields with their primitive types; remove reads of additional fields and nested objects. Current file metadata and the array or dictionary shape are preserved. No support window is provided for additional fields: the closed DTO applies immediately.

### NEW-1006-2: site actions and data

Added `POST /v1/sites/:id/publication`, `POST /v1/sites/:id/unpublish`, `POST /v1/sites/:id/trash` and `POST /v1/sites/:id/restore` with site state read back. Reads: `GET /v1/sites/:id/public-url`, `GET /v1/sites/:id/preview`, `GET /v1/sites/:id/settings`, `GET /v1/sites/:id/export`, `GET /v1/sites/:id/my-permissions`. Export is limited to 8 MiB; excess returns `413 SITE_EXPORT_TOO_LARGE`. `PUT /v1/sites/:id/permissions` fully replaces rights with a non-empty dictionary; `DELETE /v1/sites/:id/permissions` explicitly clears them. `my-permissions` shows current-user operations, not assigned roles. All operations require `landing` scope and support `scope`.

### NEW-1006-3: Page actions and template discovery

Added site page actions: [POST /v1/pages/:id/trash](/docs/entities/pages/trash), [POST /v1/pages/:id/restore](/docs/entities/pages/restore), [POST /v1/pages/:id/copy](/docs/entities/pages/copy) and [POST /v1/pages/:id/move](/docs/entities/pages/move). Actions return the page read back. Moving requires an explicit destination, and copying an active page may publish its copy immediately under Bitrix24 rules.

[POST /v1/pages/from-template](/docs/entities/pages/from-template) creates a page using a code from [GET /v1/page-templates](/docs/entities/page-templates). [GET /v1/pages/:id/public-url](/docs/entities/pages/public-url), [GET /v1/pages/:id/preview](/docs/entities/pages/preview), [GET /v1/pages/:id/settings](/docs/entities/pages/settings) and [GET /v1/pages/resolve](/docs/entities/pages/resolve) obtain addresses, settings and a page ID from its public path. Every route requires the `landing` scope, with the optional `scope` query parameter for knowledge bases and groups.

### NEW-1006-4: Site folders

Added `GET|POST /v1/sites/:id/folders`, `PATCH /v1/sites/:id/folders/:folderId` and `POST` actions `trash`, `restore`, `publication`, `unpublish`. Requires `landing` scope; pass `scope` for non-default site types. Writes return the folder read back. Partial PATCH preserves the parent; `parentId: null` moves the folder to root. Publication and unpublication affect the parent chain; trash unpublishes pages in the folder and descendants, restore does not republish them.

### BC-1006-5: galaxy host without an agent gets the AGENT_NEVER_CONNECTED code

> Old format supported until: not provided

**Before**

When the agent never came up on a galaxy host (`kind: "GALAXY"`), the platform moved the host to `error` with a text reason in `provisionError`, but `provisionErrorCode` stayed `null`. The case could not be told apart by code, and [`POST /v1/infra/servers/:id/start`](/docs/infra/lifecycle/start) accepted the request: the host went back to `running`, billing resumed, and there was still no agent.

**After**

A newly judged host in this state gets `provisionErrorCode: "AGENT_NEVER_CONNECTED"`, the same code a standalone server gets. Existing `ERROR` rows with the old reason text keep `provisionErrorCode: null`; `/start` and `availableActions` recognize that exact legacy text and expose the same repair path. `POST /start` on either form answers `422` with the code, and `error.availableActions` carries `repair` and `delete`.

**What integrators should do**

If you restart galaxy hosts in `error` on a schedule, treat `AGENT_NEVER_CONNECTED` or the exact legacy reason `Galaxy host booted but its agent never connected — the on-boot Docker/agent install failed. Delete and recreate the host, or repair it.` as a signal to call [`POST /v1/infra/servers/:id/repair`](/docs/infra/lifecycle/repair), not to retry the start.

### BC-1006-6: whitespace-only names of a key and of an AI credential are rejected

> Old format supported until: not provided

**Before**

A value made only of spaces, tabs or line breaks (for example `"   "`) passed the "at least one character" check. A key and an AI credential were accepted with such a name and stored with no visible character at all.

**After**

Such a value is rejected before anything is written:

- [POST /v1/keys](/docs/management-keys) and [PATCH /v1/keys/{id}](/docs/management-keys) — field `name`, response `400 VALIDATION_ERROR`;
- [POST /v1/ai/credentials](/docs/ai/credentials/create) and [PATCH /v1/ai/credentials/:id](/docs/ai/credentials/update) — field `name`, response `400 INVALID_REQUEST`.

On the write paths of an application name and a placement title (`title`, `catalogTitle`) the same refusal has been in force since 16.09 — record **BC-0916-20**; nothing changed for them here.

An accepted name is still stored exactly as sent, as before: edge spaces are not trimmed, and only a name with no non-whitespace character at all is rejected. Requests with a regular name, and requests that omit `name` where it is optional, work as before.

**What integrators should do**

Only callers that put a whitespace-only string into `name`, for example untrimmed user input, need a change: check that the name holds at least one non-whitespace character before sending the request.

### FIX-1006-7: `GET /v1/chats/:dialogId/messages`: the `limit` ceiling applies to any spelling of the name

**Before**

A `LIMIT` (or `Limit`) query parameter sent without a lowercase `limit` reached Bitrix24 as is: the 200 ceiling and the `meta.appliedLimit` echo were not applied.

**After**

Every spelling of `limit` is folded into one value (lowercase wins), clamped to 200 and sent as `LIMIT`; when clamped, the response carries `meta.requestedLimit` and `meta.appliedLimit`. Other query parameters pass through unchanged.

### NEW-1006-8: System pages and template areas

VibeCode API supports reading and assigning system pages through `/v1/sites/:id/system-pages`, reading a role URL through `/v1/sites/:id/system-pages/:type/url` and explicitly clearing site or page roles. `/v1/site-templates` returns layout templates. `/v1/sites/:id/template-areas` and `/v1/pages/:id/template-areas` support GET, merging PATCH and DELETE to clear all areas. Omitted areas remain, null removes one area. Requires landing scope. Writes verify persisted state; silent Bitrix24 refusal is returned as 422 BITRIX_ERROR.

### BC-1006-9: the refusal for a server with no cloud VM names only the endpoints the caller may call

> Old format supported until: not provided

**Before**

A server with no cloud VM answered `422 VM_MISSING` on wake via `POST /v1/infra/servers/{id}/wake` — including the automatic wake
inside `POST /v1/infra/servers/{id}/deploy`, `/exec`, `/upload` and
`GET /v1/infra/servers/{id}/logs`: all four share one preamble, and it wakes the same way. The hint was the same for every caller and
advised two endpoints: `DELETE /v1/infra/servers/{id}`, then `POST /v1/infra/servers`. A
read-only key is allowed to deploy, yet both advised calls answer it
`403 WRITE_BLOCKED_READONLY_KEY`: the platform printed an instruction it forbids itself. The
same applied to a key without the `vibe:infra` scope, a development-team member on someone
else's server, and an owner whose account is pending deletion.

**After**

An endpoint reaches the hint only when it is available to that caller. A key refused the
delete or the create is given the reason and the recipe instead of the address — what to
change (switch the key's access mode, grant the `vibe:infra` scope, ask the server owner);
when both halves are closed by different doors, both reasons are named. The half of the
recipe that is available is still named by its endpoint.

For a galaxy app (`kind: GALAXY_APP`) the same response advises redeploying with `POST
/v1/infra/servers/{id}/deploy` instead of deleting and creating. That endpoint is now also
named only when deploying is open to the caller. In practice this affects one case: a
development team member reads `GET /v1/infra/servers/{id}/logs` with their own key while their
Bitrix24 account has the galaxy pilot switched off — they get the reason and the recipe instead
of the endpoint. The server owner, a development team key issued for this server and a caller
linked through an application do not receive this response: their requests to a galaxy app are
served by a separate branch.

TWO body fields change for such a caller: `error.hint` and `error.message` — the latter no
longer says "delete this server and create a new one", since the caller has no way to do it.
A third field, `error.userMessage`, is no longer sent to them at all: it is localized and
unconditional, and it ordered the very deletion the neighbouring hint had just declared
unavailable. The previous wording of all three fields is preserved for a read+write key that
owns the server. The code (`VM_MISSING`) and the status (`422`) did not change for anyone.

The `VM_MISSING` responses of `POST /v1/infra/servers/{id}/start`, `/stop` and `/reboot` now
use the same hint and carry an `error.hint` field for the first time — the field is additive,
existing clients ignore it.

**Affected endpoints:** `POST /v1/infra/servers/{id}/wake`, `/deploy`, `/exec`, `/upload`,
`/start`, `/stop`, `/reboot` and `GET /v1/infra/servers/{id}/logs`.

**What integrators should do**

A client that displayed ONLY `error.userMessage` on `422 VM_MISSING` gets no text at all on a
refusal. Do not rely on `error.userMessage` being present in this response: read
`error.message` and `error.hint` — they carry the reason and what to change.

### BC-1006-10: a smart process can no longer be re-attached to a workspace through customSectionId

> Old format supported until: not provided

**Before**

`PATCH /v1/smart-processes/:id` accepted the field `customSectionId`. The value reached Bitrix24
and was discarded there: the type update method does not change the attachment of a type to a digital
workspace, only the workspace side changes it. The request answered with success, and the caller believed the
smart process had been moved to another workspace while nothing had changed. In
`GET /v1/smart-processes/fields` the field looked like an ordinary writable one.

**After**

`customSectionId` is no longer accepted when a type is updated. `PATCH /v1/smart-processes/:id` carrying it
answers `400 READONLY_FIELD` and names the field; both batch update operations answer the same way.
`POST /v1/smart-processes` accepts the field as before. In `GET /v1/smart-processes/fields` the field
carries the `readonlyOnUpdate` flag: the value can only be passed on creation, but after creation it
changes along with the attachment. Its label and description mark it deprecated.

**What integrators should do**

Drop `customSectionId` from the body of `PATCH /v1/smart-processes/:id` — otherwise the whole request
gets `400 READONLY_FIELD` instead of the former "success". This matters most when your code reads a
record with `GET` and sends the whole object back: such a call is now refused. Change the attachment
from the workspace side instead — `PATCH /v1/automated-solutions/:id` with the complete `typeIds` set
(the set is overwritten in full, so send the whole list). The `readonlyOnUpdate` flag in
`GET /v1/smart-processes/fields` lets you tell such fields apart before sending a request.

### NEW-1006-11: digital workspaces are now an entity — /v1/automated-solutions

The entity `/v1/automated-solutions` is available with seven operations:
`GET /v1/automated-solutions`, `GET /v1/automated-solutions/:id`, `POST /v1/automated-solutions`,
`PATCH /v1/automated-solutions/:id`, `DELETE /v1/automated-solutions/:id`,
`GET /v1/automated-solutions/fields`, `POST /v1/automated-solutions/batch`. The `crm` scope is
required. Until now there was no programmatic way to create a digital workspace and attach
smart processes to it.

A record carries three fields: `id` (read-only), `title` (required on creation) and `typeIds` — an
array of the `entityTypeId` values of the attached smart process types. The attachment is written
from the workspace side: on `PATCH` the `typeIds` set is overwritten in full, so send the complete
list or omit the key altogether.

List filtering and sorting are limited to `id` and `title` — a limitation of the Bitrix24 method. A
request naming any other field is refused before the Bitrix24 call (`400 UNKNOWN_FILTER_FIELD` or
`400 UNKNOWN_SORT_FIELD`) instead of quietly returning the whole collection.

A new error code `403 B24_AUTOMATED_SOLUTION_LIMIT_EXCEEDED` reports that the Bitrix24 account has used up
its allowance of digital workspaces; in the cloud the ceiling depends on the Bitrix24 plan. Retrying will
not help — free a slot or raise the plan. Bitrix24's refusal to delete a non-empty workspace
arrives as a `422` with `b24Code: "HAS_BOUND_TYPES"` and a hint naming the order of steps: move the
attached types first, then repeat the deletion.

### NEW-1006-12: landing blocks over the API: a page can now be filled with content

Until now the API could create a site, create a page and publish it — but nothing could put a
single block on that page, so a programmatically assembled site stayed empty. Six routes now
cover the whole scenario.

- **Block catalog** — [GET /v1/block-repository](/docs/api-reference) returns the block codes
  available on the account. The catalog is account-wide and is not paginated: narrow it with
  the `section` parameter.
- **Blocks of a page** — [GET /v1/pages/{pageId}/blocks](/docs/api-reference). It reads the
  page DRAFT by default rather than the published version, because draft identifiers are what
  every write accepts. Read the published tree with `version=published`; block markup is
  returned only when `content=true` is asked for. The response states the version it resolved,
  both once and on every block.
- **Add and edit** — [POST /v1/pages/{pageId}/blocks](/docs/api-reference) puts a block from
  the catalog on the page, [PATCH /v1/pages/{pageId}/blocks/{blockId}](/docs/api-reference)
  replaces its markup wholesale. Both writes land in the draft, and the response says so:
  visitors see the change after the page is published.
- **Deletion is reversible** —
  [DELETE /v1/pages/{pageId}/blocks/{blockId}](/docs/api-reference) moves the block to the page
  trash and [POST /v1/pages/{pageId}/blocks/{blockId}/restore](/docs/api-reference) brings it
  back; the restore address arrives in the deletion response itself. Permanent deletion is
  deliberately absent from the API, so a mistake can always be undone. A trashed block is
  listed with `deleted=true`.

A write addressed to an identifier that is not in the page draft is refused BEFORE Bitrix24 is
called — HTTP 404 with the code `BLOCK_NOT_IN_DRAFT`. That is done for determinacy: otherwise
such a write could report success while changing nothing.

Boolean body fields (`active` on add, `designed` on markup replacement) accept only
`true`/`false` (and the strings `"1"`/`"0"`). Anything else is refused with HTTP 400 and the
code `INVALID_ACTIVE` / `INVALID_DESIGNED` rather than read as a silent «no»: otherwise the
block would be created HIDDEN while the response said 201, and nothing would tell that apart
from the block that was asked for.

`content` on create is type-checked too: a non-string is refused with HTTP 400
`INVALID_CONTENT` rather than silently falling back to the repository markup. The field stays
optional.

All six routes require the `landing` scope. Knowledge-base, group and vibe pages additionally
need the `scope` parameter — without it Bitrix24 answers that the page does not exist even
though it does.

A page cannot be assembled in one batch call: blocks are added one at a time, and the page is
published once at the end.

### FIX-1006-13: the reaction add and remove response is documented as `data.result`

**Before**

The API reference said that `POST /v1/chats/messages/:messageId/reactions` and `DELETE /v1/chats/messages/:messageId/reactions/:reaction` return `{ "success": true, "data": true }`. The `422 BITRIX_ERROR` refusal of `GET /v1/chats/:dialogId/pins/count` was not documented.

**After**

The reference describes the actual response of both reaction methods: `{ "success": true, "data": { "result": true } }`. Read the success flag from `data.result`. For `GET /v1/chats/:dialogId/pins/count` the `422 BITRIX_ERROR` refusal with `error.b24Code` `CHAT_NOT_FOUND` for a missing chat is documented. The methods themselves are unchanged, and the HTTP 200 response is unchanged.

### NEW-1006-14: Drive file search, synchronization and saving

The Vibecode API allows clients to search files available to the user across Drive through `POST /v1/disk/search`.
`GET /v1/disk/capabilities` reports the capabilities supported by the connected Bitrix24 account.
File search and saving are available independently of synchronization support.

The `/v1/disk/sync/*` methods allow clients to retrieve a metadata snapshot, resume interrupted synchronization
and read subsequent changes. `POST /v1/disk/sync/check` checks the current state of objects
and the user's access to them.

`POST /v1/disk/uploads/reserve` and `POST /v1/disk/uploads` allow clients to create a file or save a new
version of an existing file. `GET /v1/disk/uploads/:operationId` returns the operation status.
If the write outcome is unknown, the client checks its status before submitting it again.
Checking a file version does not guarantee protection from concurrent changes by another user.

### FIX-1006-15: typing indicator response example now matches the actual response

**Before**

The response example of [POST /v1/chats/:dialogId/typing](/docs/chats/messages/typing) in the specification and the API reference showed `data: true`.

**After**

The example shows the actual response: `data` is an object with a `result` field, `{ "success": true, "data": { "result": true } }`. The response itself did not change, it already arrived in this shape.

**Impact on integrators**

If your code checked `data === true` following the old example, check `data.result` instead.

### BC-1006-16: feedback attachments now accept documents, not just images

> Old format supported until: not provided

A ticket can now carry text, a spreadsheet, a saved web page or an archive — the upload used to accept images only.

The file type is decided by the FILENAME EXTENSION, not by the part's `Content-Type` header: browsers report these formats incorrectly — `.md` arrives with an empty type, `.zip` on Windows arrives as `application/x-zip-compressed`, and `.csv` with an office suite installed arrives as a spreadsheet type. Accepted extensions are `txt`, `md`, `csv`, `html`, `htm`, `xlsx`, `zip` alongside the existing `png`, `jpg`, `jpeg`, `webp`, `gif`. The limits are unchanged: 10 MB per file, 5 files per message, 25 per ticket.

An image is still re-encoded by the platform and shown as a thumbnail. A document is stored byte for byte and is always served as a download, so it has no thumbnail: the [POST /v1/feedback/attachments](/docs/feedback) response carries `kind: "DOCUMENT"`, `thumbnailUrl: null`, and `width` and `height` are zero. The thumbnail address of a document answers `404`. An image carries `kind` of `IMAGE`.

The `kind` field was also added to the attachment lists of every ticket read operation, and the list of accepted extensions arrived as `attachmentAllowedExtensions` in `GET /v1/me`. The neighbouring `attachmentAllowedMime` there grew: besides the four image types it now lists `text/plain`, `text/markdown`, `text/csv`, `text/html`, `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` and `application/zip`. It is a reference list of types, not the acceptance rule: the filename extension decides, and only images are accepted by declared type when the name is not recognised.

Upload refusals: a name that is not recognised (no extension, or one outside the list) with a `Content-Type` that is not one of the four image types is `400 INVALID_MIME`, content that does not match the extension (an archive with no signature) is `400 MIME_MISMATCH`, and an empty file is `400 INVALID_FILE_EMPTY`.

⚠️ **Image uploads narrowed in two places.** The attachment class is now decided by the filename extension, and where the extension and the declared type disagree the answer changed:

**Before**

Image class was decided by the declared `Content-Type`, so a filename extension that disagreed with it was ignored.


**After**

The extension decides, and the two disagreeing cases answer differently:

- `photo.zip` with `Content-Type: image/png` and PNG bytes used to be accepted as an image (`200`, `kind: IMAGE`); it now answers `400 MIME_MISMATCH`;
- `shot.txt` with `Content-Type: image/png` used to become an image with a thumbnail; it is now accepted as a document (`kind: DOCUMENT`) and gets no thumbnail.

What did not narrow: a part whose name is not recognised — no extension (`blob`, the name `FormData.append` gives it) or an extension outside both lists (`report.pdf`) — is still accepted as an image when its `Content-Type` is one of the previously accepted image types and its bytes really are an image. Conversely, a PNG with an EMPTY `Content-Type`, refused before, is now accepted by its filename extension.

**What integrators should do**. Send a filename whose extension matches the content. If you built the part by hand and gave it a name with an unrelated extension, relying on `Content-Type`, fix the name — that pair is exactly what stopped being accepted.

### BC-1006-17: reading, updating and deleting a smart process field check that the field belongs to the smart process in the path

> Old format supported until: not provided

**Before**

[GET /v1/items/:entityTypeId/userfields/:id](/docs/userfields/smart-processes/get), [PATCH /v1/items/:entityTypeId/userfields/:id](/docs/userfields/smart-processes/update) and [DELETE /v1/items/:entityTypeId/userfields/:id](/docs/userfields/smart-processes/delete), as well as the invoice short addresses `/v1/userfields/invoices/:id`, found the field by its id alone and did not match it against `:entityTypeId`. A request through the invoice path with the id of a deal field read that field and answered `200`. A field that no longer exists answered `422 BITRIX_ERROR` with a permission-refusal message, including a repeated `DELETE`.

**After**

Before reading, updating or deleting, the platform checks that the smart process in the path has a field with this id. A field of another entity and a deleted field get the same answer: `404 NOT_FOUND` for `GET`, `404 ENTITY_NOT_FOUND` for `PATCH` and `DELETE`. Update and delete then send nothing to Bitrix24. `422 BITRIX_ERROR` remains for a field deleted between the check and the request itself.

**What integrators should do**

Move the "field is missing" branch from `422 BITRIX_ERROR` to `404`: `NOT_FOUND` for reading, `ENTITY_NOT_FOUND` for updating and deleting. A repeated `DELETE` answering `404` means the field is already gone. If an integration reached a field through the path of another entity, use the path of the entity the field belongs to: for a deal field, `/v1/userfields/deals/:id`. Each of the three operations takes one extra request to Bitrix24.

### FIX-1006-18: the business-process editor spec names when the section is unavailable

**Before**

The OpenAPI specification described the `/v1/workflow-designer` methods as an available contract and did not name `DESIGNER_NOT_RELEASED`. `GET /v1/workflow-designer/capabilities` did not name that reason.

**After**

The response remains `200` on `GET /v1/workflow-designer/capabilities`: while the section is not released for this key, `available` is false and `reason` is `DESIGNER_NOT_RELEASED`. The other methods of the section still answer `403 DESIGNER_NOT_RELEASED` and do not call Bitrix24. The specification now names the same fact. Once the section is released for the key, the methods are served on the merits and this code is not returned.

### NEW-1006-19: Continue note search and list documents

`GET` and `POST /v1/note/documents/search` accept an optional `offset` from 0 to 10000 to fetch the next result page. While `meta.hasMore` is `true`, increase `offset` by `limit`; if the next `offset` exceeds 10000, use the list for a complete traversal. The new `GET /v1/note/documents` returns a flat document list and `meta.nextCursor`. Send that cursor as URL-encoded JSON in the next request's `afterCursor` query parameter until it becomes `null`, including after an empty page. The knowledge-base contents remain a tree, not a list page.

### FIX-1006-20: A missing payment product returns 404 regardless of the Bitrix24 account language

**Before**

Adding a nonexistent product row through `POST /v1/crm-payments/{id}/products` could return `422 BITRIX_ERROR` instead of `404 ENTITY_NOT_FOUND` in Bitrix24 accounts using some languages.

**After**

When Bitrix24 confirms that the product row is absent, the API returns `404 ENTITY_NOT_FOUND` regardless of the message language. If the row cannot be checked, the original add error is preserved.

### BC-1006-21: Galaxy app deploy validates env line size

> Old format supported until: not provided

**Before**

Galaxy app deploy accepted `env` without limiting the length of the complete variable line.

**After**

On [POST /v1/infra/servers/:id/deploy](/docs/infra/deploy/deploy), Galaxy requests whose full UTF-8 `KEY=VALUE\n` line exceeds 65536 bytes now receive `400 GALAXY_DEPLOY_INVALID_ENV`. The same env limits apply when creating through [POST /v1/infra/servers](/docs/infra/servers/create). Values containing `\r`, `\n`, NUL, or malformed Unicode surrogates receive `400 VALIDATION_ERROR` on deploy and `400 INVALID_REQUEST` on create.

**What integrators should do**

Before sending a request, check each Galaxy env line in UTF-8 including the key, `=`, and trailing newline; do not send forbidden characters.

### BC-1006-22: reading post comments returns only valid identifiers and file fields

> Old format supported until: not provided

**Before**

[GET /v1/posts/comments](/docs/posts/comments/read) could return fractional comment and attachment identifiers. The response schema did not enumerate the available file fields.

**After**

The successful HTTP 200 response is preserved. Comment and attachment identifiers are returned only as integers, and files contain only the documented optional fields. `data.files` can still be an array or a dictionary keyed by numeric IDs.

**Impact on integrations**

This narrows the previously published native `data.files` response: fields outside the listed allow-list are no longer returned. Integrations that used those undocumented fields must migrate to the documented fields (`id`, `date`, `type`, `name`, `size`, `image`, `authorId`, `authorName`, `urlPreview`, `urlShow`, `urlDownload`); there is no compatibility mode that preserves the old field set. Invalid identifiers are still omitted from the response.

**What integrators should do**

Review `data.files` handling and replace reads of undocumented fields with the listed allow-list; treat unsupported fields as absent.

### NEW-1006-23: Copy, move, reorder and delete page blocks

Added POST actions copy, move, up, down, show, hide, purge under `/v1/pages/:pageId/blocks/:blockId/` and bulk-purge under `/v1/pages/:pageId/blocks/`. Requires landing. Block ownership is checked before writing. Order and visibility are read back. purge and bulk-purge irreversibly delete blocks and their files; bulk-purge requires non-empty blockIds, at most 50 blocks and 50 images. Surviving blocks return 422 BITRIX_NO_EFFECT with error.blockIds. Order boundaries return 409 BLOCK_WRONG_SORT.

### FIX-1006-24: server rename updates the application placement label

**Before**

[PATCH /v1/infra/servers/:id](/docs/infra/servers/update) with a new `displayName` copied the name to the server's application, but the label of its Bitrix24 placement — a CRM card tab or a left menu item — kept the old name.

**After**

When the server's application has placements, changing `displayName` first rebinds them with the new title and only then saves the name. If Bitrix24 did not confirm the binding, the name stays unchanged on both the server and the application, and the call can be retried: `502 BITRIX_PARTIAL_REBIND` with the placement codes in `error.unbound` / `error.restored`, `400 NO_USER_TOKEN` when the application is not authorized in Bitrix24, `400 BOX_NO_DEVELOPER_KEY` / `APP_NOT_INSTALLED_ON_BOX` on a self-hosted Bitrix24, `409 APPLICATION_OP_IN_PROGRESS` while another operation on the application is running. A key that may not change Bitrix24 data gets `403 WRITE_BLOCKED_READONLY_KEY` under the same conditions as an application rename through `PATCH /v1/apps/:id`. Renaming a server without an application or an application without placements, and editing only the description, work as before; the response remains HTTP 200.

**Impact on integrators**

A client renaming the server of an application with placements should handle these refusals: the name is not saved in that case, and retrying the call is safe.

### NEW-1006-25: Read page blocks and catalog samples

Added `GET /v1/pages/:pageId/blocks/:blockId`, `GET /v1/pages/:pageId/blocks/:blockId/content`, `GET /v1/block-repository/:code/content` and `GET /v1/block-repository/:code/manifest`. Requires the `landing` scope; READONLY keys can read. Optional query `scope=KNOWLEDGE|GROUP|MAINPAGE` selects the page context.

Reads include drafts. A block from another page, missing sample or manifest returns `404 ENTITY_NOT_FOUND`. URL-encode the block code in the path. Application blocks `repo_N` have no manifest file. Manifest `nodes` and `cards` keys are selectors. Content returns HTML and a narrow set of data without the full manifest; `php: true` denotes a code block with restricted content editing. Block dates are ISO wall clocks without an invented timezone. Credential-bearing strings are replaced with `[REDACTED]`, including the entire HTML string if it contains a secret.
