For AI agents: markdown of this page — /docs-content-en/changelog/2026-07-07.md documentation index — /llms.txt
API changes: July 7, 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.