For AI agents: markdown of this page — /docs-content-en/changelog/2026-07-07.md documentation index — /llms.txt

API changes: July 7, 2026

← Changelog · July 2026

FIX-0707-1: smart-processes: linkedUserFields accepts Y/N and boolean values

Before

POST /v1/smart-processes and PATCH /v1/smart-processes/:entityTypeId with linkedUserFields only worked when the flag value was strictly "true"/"false". A value in the "Y"/"N" convention (used by every other smart-process field) or a boolean true/false was silently ignored: the request returned success: true, but the display in the user field was not enabled.

After

linkedUserFields values are normalized the same way as the nested relations[].isChildrenListEnabled flag: true/"Y"/"yes"/1 → enabled, false/"N"/"no"/0 → disabled. Existing calls with "true"/"false" keep working unchanged.

Impact on integrators

No action needed — calls that previously "silently did nothing" with "Y" are now applied correctly.

BC-0707-2: Order-card nested fields normalized

Old format supported until: 06.01.2027

Before

GET /v1/orders/{id} returned the nested clients, payments, basketItems arrays in raw Bitrix24 shape: boolean fields as "Y" and "N" strings (payments[].paid, clients[].isPrimary, basketItems[].vatIncluded, and others), dates inside payments and basketItems with a +03:00 offset, and companyId set to 0 when no company is bound. The accountNumber field was silently ignored on create and update.

After

Nested Y/N fields now arrive as boolean (true or false); nested dates are normalized to UTC (ending in Z); companyId is null when no company is bound instead of 0; accountNumber became read-only — sending it on create or update returns 400 with code READONLY_FIELD.

What integrators should do

Read nested Y/N fields as boolean instead of comparing to the string "Y"; treat null instead of 0 as "no company bound"; stop sending accountNumber in the create and update body — the number is assigned automatically.

FIX-0707-3: The /v1/openapi.json spec now matches actual runtime

Before

The machine OpenAPI spec was generated from static entity metadata and drifted from real responses: no field was marked nullable, nested order-card arrays were typed as a string, list methods were missing filter and select, and operations declared only success codes and 403.

After

The spec now reflects the contract. Nullable fields are emitted as type: ["<type>", "null"]. Object and array-of-object fields are typed honestly, including the nested clients, payments, basketItems, propertyValues of GET /v1/orders/{id}. List methods declare the filter and select query params. Operations carry the standard error codes 400, 401, 404, 422 in the single { success:false, error:{ code, message } } envelope. *Input schemas declare create-required fields. Additionally GET /v1/orders/fields returns clients as an array instead of object. An SDK generated from the spec now types responses correctly.

BC-0707-4: /search: auto-windowed search now returns the real Bitrix24 error on total failure

Old format supported until: 07.09.2026

Before

Any failed auto-windowed POST /v1/{entity}/search returned 502 { "error": { "code": "WINDOWED_SEARCH_FAILED" } } with a generic "add autoWindow:false".

After

The response matches the same query at a narrow range — the real code and message: a rejected filter/sort field → 400 UNKNOWN_FILTER_FIELD / 400 INVALID_PARAMS; no access → 403; request limit / queue overload → 429 + Retry-After; timeout → 503; Bitrix24 unavailable → 502 BITRIX_UNAVAILABLE. Partial window failure (status 200) now carries meta.windowErrorSample { code, message }.

What integrators must do

If you branched on error.code === "WINDOWED_SEARCH_FAILED" (e.g. to retry with autoWindow:false) — branch on the real codes instead. The autoWindow:false workaround remains; it is useful where it actually helps (the 429 QUEUE_TIMEOUT hint names it). The total-failure response no longer carries the meta block (autoWindowed/windowCount/windowErrors) — the signal is now in the error code/message itself; meta.windowErrorSample remains on partial failure (status 200).

FIX-0707-5: lists on an account without the module return 409 consistently, not 429

Before

On an account where the Universal Lists module is disabled, calls to /v1/lists returned the clear 409 LISTS_MODULE_NOT_ENABLED only for the first few requests. After that the built-in error-loop protection tripped and every subsequent call returned 429 ERROR_LOOP_DETECTED, hiding the real cause (the module is not installed).

After

The "method unavailable on this account" signal is no longer counted by the error-loop protection, so lists.* calls on a module-off account return 409 LISTS_MODULE_NOT_ENABLED consistently no matter how many times they repeat. The response stays actionable: enable the module in the account and retry.

NEW-0707-6: error.hint on the 400 for a server create missing source and provider/plan/region

POST /v1/infra/servers, when rejected with 400 INVALID_REQUEST because provider/plan/region are missing (and no source was passed) on a galaxy-placement account, now additionally returns an error.hint object with reason (why the request was rejected on this account), recovery (the recommended one-shot path plus the working two-step alternative) and example (a paste-ready one-shot body skeleton). error.code and error.message are unchanged — the hint is strictly additive; accounts without galaxy placement get the previous response, without hint.

The hint is also returned on 400 RUNTIME_PARAM_REMOVED (a create with runtime but no source on a galaxy-placement account), and a body carrying placement: "dedicated" gets a separate hint variant — for a dedicated server, keeping the intent and adding the missing provider/plan/region tuple, instead of steering the caller into a galaxy container.

FIX-0707-7: Galaxy deploy checklist in /v1/me now matches the actual contract

Before: step 2 of deployment.galaxyApp.checklist instructed POST /v1/infra/servers { name } with no source and no provider/plan/region — that call always failed with 400 INVALID_REQUEST. The CREATE rule did not explain that the two-step path requires the full provider/plan/region tuple, and newAppPlacement.note promised a dedicated standalone VM where the create actually returns a galaxy slot with next: "deploy". The favicon guide pointed to the same broken order; the never-deployed-slot reap window was stated as "~12-20 min" versus the actual ~20-25.

After: the recommended path is a single call — POST /v1/infra/servers { name, source, runtime, start } (omit provider/plan/region). The two-step path is documented truthfully: a create without source requires the full provider/plan/region tuple (values are informational for a galaxy — the app inherits its host), and on galaxy placement returns a slot with next: "deploy"; a never-deployed slot is reaped to ERROR after ~20 min (swept every 5 min). Favicon: the primary path is a self-hosted /icon.svg inside the archive (no id needed); the platform-hosted URL remains an alternative via the two-step order or a re-deploy. The status-polling step gained a status=error branch → provisionError/buildLog → re-deploy.

Impact on integrators: agents following the checklist now deploy on the first call. Endpoint behavior is unchanged — only the /v1/me texts and the /v1/openapi.json description were updated; existing integrations keep working as is.

NEW-0707-8: Company AI quota is available via the API

The new GET /v1/ai/quota endpoint returns the monthly AI quota state of your Bitrix24 account: the percentage of the limit consumed (pctUsed, an honest value — above 100 on overspend), the exhaustion flag (exhausted), the reset date (resetAt, a rolling 30-day window), and a per-model breakdown — request counts, tokens, and each model's share of the monthly limit (byModel[].pctOfLimit). Absolute limit values in Vibe credits are not exposed — percentages only, same as the dashboard. Requires the vibe:ai scope.