# API changes: November 6, 2026

[← Changelog](/docs/changelog) · [November 2026](/docs/changelog/2026-11)

### BC-1106-1: CRM forms preserve the Bitrix24 schema and rules

> Old format supported until: not provided

**Before**

The [form list](/docs/entities/crm-forms/list) returned only active forms and a reduced field set by default. [Form reads](/docs/entities/crm-forms/get) rebuilt fields and consents, added the `title`, `result` and `agreementsSettings` properties and added field options. [Form contract fields](/docs/entities/crm-forms/fields) did not list the `analytics`, `integrations` and `spamProtection` descriptors, and [reading one contract field](/docs/entities/crm-forms/field) by those names answered `400 INVALID_PARAMS`. The `isCallback` filter selected records after fetching a page. A failed additional read after a write appeared as a failed write. [Website widgets](/docs/entities/crm-forms/site-buttons) and [Open Channels](/docs/entities/crm-forms/openlines) answered `UNKNOWN_FILTER_FIELD` for an unknown query parameter, returned a reduced property set per item, applied a page size of 50 with offset 0 and always returned `meta` with `limit` and `offset`. [Embedding codes](/docs/entities/crm-forms/embedding) were rebuilt into a separate shape.

**After**

The list includes active and inactive forms and returns 11 scalar properties by default. `select` supports sections and nested paths, with filtering by `id` and sorting. In `GET /v1/crm-forms`, query parameters other than controls become Bitrix24 filter conditions: an unknown name no longer causes a local refusal, and Bitrix24 decides whether it is valid. `GET /v1/crm-forms/{id}` accepts an optional `select`. The form, website widget and Open Channel lists no longer impose defaults of `limit=50`, `offset=0` or a `limit` range of 1–1000: Bitrix24 validates the values. Without `limit` and `offset`, no pagination is sent. Pagination fields `meta.limit`, `meta.offset` and `meta.total` are no longer guaranteed: they come only from Bitrix24 pagination, and the `meta` object may be absent. Forms retain the Bitrix24 schema, with no rebuilding of fields and consents and no added properties. Form contract fields list every property, including `analytics`, `integrations` and `spamProtection`, reading one contract field by those names returns its descriptor, and both paths accept an optional `select`. Additional field-option lookup and post-fetch `isCallback` filtering have been removed. Ordinary content is preserved, while exact credentials of the current connection are replaced with paths listed in `meta.redacted`.

[Create](/docs/entities/crm-forms/create) and [update](/docs/entities/crm-forms/update) accept a flat body or a `fields` object. `PATCH /v1/crm-forms/{id}` no longer enforces its own writable and read-only property lists: Bitrix24 validates `active` and other supplied properties. A successful write followed by a failed read retains its success status and `data.id`, adding `meta.warnings`. `CRM_FORM_PARTIALLY_CREATED` remains an error with `error.id`, `b24Code` and field errors. Bitrix24 errors include `b24Code`, and insufficient token scope has a distinct `BITRIX_INSUFFICIENT_SCOPE` code. Only an unavailable method becomes `409 CRM_FORM_REST_NOT_ENABLED`. Local request-shape refusals in the described `crm.form.*` methods answer with an `INVALID_PARAMS` code: the `UNKNOWN_FILTER_FIELD`, `UNKNOWN_FIELD`, `READONLY_FIELD`, `INVALID_FILTER_OPERATOR` and `INVALID_FILTER_SHAPE` codes are no longer returned there, and a missing `updatedTime` on a form or embedding update gives `INVALID_PARAMS` instead of `MISSING_REQUIRED_FIELDS`. The `MISSING_REQUIRED_FIELDS` refusal for a missing `entityName` and the `POST /v1/crm-forms/{id}/results` contract remain unchanged. Embedding supports `link` and `code: null`, and deletion accepts `confirmed` as an alias for `confirm`. On the [website widget](/docs/entities/crm-forms/site-buttons) and [Open Channel](/docs/entities/crm-forms/openlines) paths an unknown query parameter gives `INVALID_PARAMS` instead of `UNKNOWN_FILTER_FIELD`, items keep the Bitrix24 schema, `order` and `sort` are accepted, and without `limit` and `offset` no pagination is sent and `meta` carries only what Bitrix24 returned. [Embedding codes](/docs/entities/crm-forms/embedding) keep the Bitrix24 schema as well. In `GET /v1/crm-forms/{id}/embedding`, the values of `variant` and `delay` are no longer validated locally, and `delay` is passed as a query string value. `PATCH /v1/crm-forms/{id}/embedding` no longer uses a local allowlist of body settings: Bitrix24 decides which properties are allowed. A local refusal for these inputs is no longer guaranteed; Bitrix24 may accept them or return its own refusal. Request-shape checks remain. In `PATCH /v1/crm-forms/{id}` and `PATCH /v1/crm-forms/{id}/embedding`, `updatedTime` is still required, but its type is no longer validated locally. For these two paths, as well as `POST /v1/crm-forms/{id}/activate`, `POST /v1/crm-forms/{id}/deactivate` and `DELETE /v1/crm-forms/{id}` with optional `updatedTime`, Bitrix24 accepts or rejects a non-string value instead of a guaranteed local `400 INVALID_PARAMS`. In `POST /v1/crm-forms`, an absent body no longer causes a local refusal: Bitrix24 receives an empty `fields` object and validates it.

**What integrators should do**

Pass `active=true` to retain the previous active-only selection. Use native form sections instead of the added `title`, `result`, `agreementsSettings` and synthetic field properties. Request target entities and responsible users through `select=crm.entityScheme,responsible.userIds`, and use the entity-field dictionary for CRM field options. After a readback warning, perform a `GET` before another change. Replace branching on `UNKNOWN_FILTER_FIELD`, `UNKNOWN_FIELD`, `READONLY_FIELD`, `INVALID_FILTER_OPERATOR`, `INVALID_FILTER_SHAPE` on the described `crm.form.*` paths with an `INVALID_PARAMS` branch; handle a missing `updatedTime` on form and embedding updates the same way. Keep supplying `updatedTime` when updating a form or embedding, and for a non-string value handle the Bitrix24 response instead of relying on the previous local `400 INVALID_PARAMS`. For activation, deactivation, deletion and creation without a body, also handle the Bitrix24 response instead of relying on the previous local refusal. Read the details from `error.message`, `error.b24Code` and `error.validation`. An unknown query parameter in the form list no longer causes a local `UNKNOWN_FILTER_FIELD`: it becomes a filter condition that Bitrix24 accepts or rejects. Do not rely on a guaranteed local refusal. For the form list, also send `limit` and `offset` explicitly to retain the previous 50-item page, and check for `meta` and its fields before reading them. For embedding, handle the Bitrix24 response and `error.b24Code` instead of relying on the previous local refusal for `variant`, `delay` values or the set of settings. For `CRM_FORM_PARTIALLY_CREATED`, read the form at `error.id`, correct or delete it, and do not repeat creation. Do not save a redacted configuration back without restoring the changed values. On the website widget and Open Channel paths, replace the `UNKNOWN_FILTER_FIELD` branch with an `INVALID_PARAMS` branch as well, send `limit` and `offset` explicitly to keep the previous page size, and read item and embedding-code properties from the Bitrix24 response.

### NEW-1106-2: Thread settings and chat features

[PATCH /v1/chats/{chatId}?format=v2](/docs/chats/management/rename) accepts `threadsEnabled` as a boolean and `manageThreadCreate`, `manageThreadPost` as `MEMBER`, `MANAGER`, or `OWNER`. `GET /v1/chats/configuration` returns known chat settings features; an omitted feature means its value is unknown.

### FIX-1106-4: creating an app: a Bitrix24 refusal with an unread plan now returns a clear code

**Before**

`POST /v1/apps` answered `502 CONNECTOR_REST_UNAVAILABLE` when Bitrix24 refused to issue the key and the account plan could not be read.

**After**

The same case returns `403 PORTAL_TARIFF_UNREADABLE`, and `error.details.remedy` says how to repeat the check. When the plan and access are confirmed, the response stays `502 CONNECTOR_REST_UNAVAILABLE`.

### NEW-1106-5: a durable command refused because of the server clock now carries its own code

[POST /v1/infra/servers/{id}/exec](/docs/infra/deploy/exec) in durable mode (`async=true`) now answers HTTP 502 with the code `EXEC_JOB_START_WINDOW` when the server refuses the launch because of its own clock: the clock runs more than a minute ahead of the platform clock or more than thirty seconds behind it. The refusal arrives before the command starts, so once the time on the server is checked the same command may be sent again. Previously this case arrived with the generic `EXEC_JOB_INVALID` code, which did not separate a clock disagreement from the other refusals. The new code is also visible in the operation outcome at [GET /v1/infra/operations/{operationId}](/docs/infra/deploy/operation-status). Every other refusal keeps its previous code.

### FIX-1106-6: a deploy no longer fails because the server clock disagrees

**Before**

Within an hour of a server being created or woken, the `runtime` step of [`POST /v1/infra/servers/{id}/deploy`](/docs/infra/deploy/deploy) was sent to the server as a deferred task with a bounded launch window. If the server clock ran more than a minute ahead of the platform clock or more than thirty seconds behind it, the task was refused, and the deploy ended with an error at that step even though the request and the application code were correct.

**After**

That refusal is now told apart from the other server refusals, and the `runtime` step runs directly, without the deferred task. The deploy goes through whether the server clock runs ahead or behind. The request fields and the response format are unchanged.

**Impact on integrators**

No action is required. A `runtime` step refusal for any other reason still arrives with its previous code.

### FIX-1106-7: `categoryId` is now required by the CRM required-fields contract for every type except leads and quotes

**Before**

The `PUT` schema in `GET /v1/openapi.json` declared `categoryId` optional for every type, and the response example substituted `0` even for leads and quotes. An integrator who built a request from the schema could omit `categoryId` for a deal and get a refusal from Bitrix24.

**After**

[PUT /v1/deals/fields/required](/docs/entities/crm-required-fields/set), together with `PUT /v1/{contacts,companies,invoices}/fields/required` and `PUT /v1/items/{entityTypeId}/fields/required`, lists `categoryId` among the required fields. Leads and quotes carry no such field in the schema at all: these types do not accept it. The response example shows `categoryId: null` when the setting is global. The method behaviour is unchanged: Bitrix24 still checks the rules.

**Impact on integrators**

No action is required: requests that worked keep working. Check your own validation if it treated `categoryId` as optional for deals, contacts, companies, invoices and smart processes.

### NEW-1106-8: aggregation warns about mixed currencies

[POST /v1/deals/aggregate](/docs/entities/deals/aggregate) now adds an `AGGREGATE_MIXED_CURRENCIES` entry to `data.meta.warnings` when `sum`, `avg`, `min` or `max` reads a field stored in the record's own currency (`deals.amount`, `deals.taxValue`, `leads.opportunity`, `leads.amount`, `quotes.amount`, `invoices.opportunity`, `companies.revenue`), the records read span more than one currency, and `groupBy` names no currency field. The values are not converted, so such a number adds different currencies. The warning appears independently of truncation and may come together with `AGGREGATE_TRUNCATED`. The deprecated `GET /v1/{entity}/aggregate` warns the same way. The Bitrix24 accounting-currency fields (`deals.receivedAmount`, `deals.lostAmount`) never raise it.
