For AI agents: markdown of this page — /docs-content-en/changelog/2026-08-31.md documentation index — /llms.txt
API changes: August 31, 2026
FIX-0831-1: a server whose agent never came up is no longer reported as running
Before
When the on-boot agent install aborted, the VM still reached running and the server stayed
there. The server card and the server list returned status: "running" with provisionError
and provisionErrorCode both empty — nothing in those responses told a working server from a
broken one, and billing kept accruing.
{ "status": "running", "blackholeStatus": "NONE", "provisionError": null, "provisionErrorCode": null }
After
Such a server moves to error with an explanation and a new
provisionErrorCode: "AGENT_NEVER_CONNECTED", and its billing is closed out.
{ "status": "error", "blackholeStatus": "NONE", "provisionError": "The server booted, but its agent never connected — …", "provisionErrorCode": "AGENT_NEVER_CONNECTED" }
Impact on integrators
Nothing to change: error is an existing status and no field was added. Worth knowing:
- A readiness wait now terminates —
runningwithblackholeStatus: "NONE"no longer lasts forever. If you poll forrunning+CONNECTED, add an exit onerror. - Recovery is
POST /v1/infra/servers/:id/repair, which reinstalls the agent over SSH. Recreate the server only if repair does not help. POST /v1/infra/servers/:id/starton such a server answers422with the codeAGENT_NEVER_CONNECTED. The status did not change: this machine already got a422from/start(SERVER_WRONG_STATE, since it counted asrunning) — the code changes, not the status. Starting it fixes nothing and erases the explanation, which is why it is refused. A client that restarts failed servers on a schedule must read the code and call repair instead.- Three lifecycle operations on such a server turn from a success into a refusal, because they
require
running:POST /v1/infra/servers/:id/stopandPOST /v1/infra/servers/:id/rebootanswer422with the codeSERVER_WRONG_STATE, andPOST /v1/infra/servers/:id/sleep-nowanswers400withNOT_RUNNING. Stopping such a machine is not needed either: billing is closed out with the verdict, so a scheduled stop saves nothing on it. The working actions arerepairandDELETE /v1/infra/servers/:id— the same pair the response lists inavailableActions. - The verdict applies to newly created servers and never touches ones already running. The
platform checks with the gateway first, so a live tunnel whose notification was lost is
healed rather than failed. If the agent connects later, the server returns to
runningon its own and both fields are cleared.
FIX-0831-2: key issuance on a free plan now names the cause instead of "retry in a minute"
Before
When Bitrix24 refused REST because the account's Bitrix24 plan does not permit it, key issuance and app installation answered 502 CONNECTOR_REST_UNAVAILABLE with the text "Bitrix24 did not issue the key. Retry in a minute". Retrying never helped: the plan gate does not clear on its own, and the response never said what did block the call.
After
The same situation answers 402 with a dedicated paywall code. The userMessage field states that a paid Bitrix24 plan is what unlocks the action. Successful responses are unchanged and still return HTTP 200, and every other refusal reason still answers 502 CONNECTOR_REST_UNAVAILABLE.
FIX-0831-3: search and research through the Linkup provider
Before
Every POST /v1/search or POST /v1/research call with provider: "linkup" was rejected by the provider: the platform did not send the required outputType field. For the same reason a Linkup key could not be connected — adding a BYOK key returned INVALID_CREDENTIAL with the text HTTP 400 even for a working key.
After
Linkup calls go through, and connecting a BYOK key reflects the real state of that key: a working key is stored, a non-working one is rejected.
In /v1/search the answer field is filled when include_answer: true and is null when include_answer: false; in that case the page text arrives in results[].content. The results[].published_date field is always null for Linkup — the provider returns no publication date, and the capability matrix in GET /v1/search/providers now reports that honestly.
FIX-0831-4: seamless dashboard sign-in from a signed Bitrix24 form
Before
Opening the dashboard from the Bitrix24 app catalog launched the platform address in a new tab. The user landed on the sign-in screen and then on the account picker, even though they had just clicked a button inside their own Bitrix24 account.
After
The licence-signed channel gained a second transition surface, cabinet. The Bitrix24-side module posts a signed form carrying BX_VIBE_SURFACE=cabinet to the new endpoint POST /microservice/open-cabinet (the trailing-slash variant is accepted too), and the user arrives in the dashboard already signed in, with no sign-in screen and no account picker.
Surface fields: BX_VIBE_AUD — the platform address the form is addressed to (mandatory, compared verbatim); BX_USER_EMAIL — the Bitrix24 user's email; BX_VIBE_NETWORK_STATE — the network-state hint, self-hosted only; BX_VIBE_TARGET — an optional relative path inside the dashboard, /dashboard by default. The signed field set and its order, the requirement on each field and the refusal codes are in the integration contract.
The session cookie is not set in response to a cross-site request: a successful response is a page on the platform domain with an auto-submitting form that exchanges a one-time code for the cookie same-site at POST /api/cabinet/handoff and forwards the user to the destination path. The code lives 120 seconds and is spent exactly once.
The issued session is an ordinary one but is bound to the Bitrix24 account it came from: switching the active account is refused, and the account listing serves only that one. Two-factor verification, terms consent, account access mode and blocks behave exactly as on an ordinary sign-in.
The surface sits behind a switch and is off by default: while it is off the endpoint answers 404. The app surface (POST /microservice/open-app) is unchanged.
FIX-0831-5: opening an application from the Bitrix24 catalog always acts as an account
Before
A Bitrix24 employee with no Vibecode account opened an application on the strength of the Bitrix24 account's signature alone: the platform issued a one-time init code carrying an empty Vibecode user id, and the application received an identity backed by no platform record at all. On a self-hosted portal such an employee opened as a guest, with the name and departments read out of Bitrix24; on cloud the platform asked Bitrix24 user.get before the redirect to confirm the employee was live.
After
Every open now has an account, and __init always carries a non-empty user. On cloud the account is created from the signed BX_NETWORK_USER_ID and BX_USER_EMAIL. On a self-hosted portal the employee confirms the identity themselves: the platform serves a server-rendered screen for the code mailed to the address from the signed form, and on a correct code the same request links the Bitrix24 member to the Bitrix24.Network profile and opens the application. The outbound user.get before the redirect is gone.
The e-mail code is now sent AND checked by Bitrix24.Network itself, through two trusted operations. The first takes the address: the Network finds or creates the profile behind it and mails the code as its ordinary e-mail confirmation. The second takes the same address plus the code and returns the profile for the confirmed address. The platform mails nothing and stores no code. Code lifetime and attempt count are the Network's; the platform keeps its own send-rate caps on top.
BX_USER_EMAIL moved out of the cabinet surface fields into the common part of the signed set: both platforms send it on both surfaces, right after BX_NETWORK_USER_ID (or after BITRIX_USER_ID when there is no network id) and before BX_VIBE_SURFACE. The field is optional — a form without it is served exactly as before, so an older module keeps working with no changes. The successful response is still a 302 to the application address carrying __init.
The account-creating branches sit behind a platform switch that is off by default: while it is off, an open with no account answers with a refusal page linking to the ordinary sign-in, and no partial profiles are left behind.
The "Authorize the application" page is reworked: one button instead of a button plus a quiet link, and once the application is authorized the page forwards to it by itself — no closing the tab and reopening the application from the catalog. The iframe therefore has to allow allow-popups. The e-mail confirmation screen opens no new tab: the code field unfolds behind a button on the same page, and a loader covers the card while the platform checks the code and connects the application. The address can no longer be changed there — only the one from the signed form is confirmed, and the single alternative is signing in on the platform yourself, through a link on that same screen. The full field set, the e-mail confirmation screens and the continuation endpoints are in the integration contract.
FIX-0831-6: Batch create of telephony lines returns the addressable number in results[].id
Before
POST /v1/telephony-lines/batch with action: "create" answered 200, but results[].id carried Bitrix24's internal numeric row id. It could not be used in PATCH or DELETE /v1/telephony-lines/:number — the line is looked up by number, so the request answered 422. The single POST /v1/telephony-lines already returned the correct number, so the two doors into the same create disagreed.
After
results[].id is the same number passed in that item's number field, and the same value the single POST /v1/telephony-lines returns. It comes back verbatim, including numbers with + and other characters. The response is still 200 and no other field changed.
FIX-0831-7: signing back into Cowork on a fee-free seat no longer fails
Before
Cancelling a fee-free Cowork subscription made every later desktop sign-in fail with
403 COWORK_SUB_CANCELLED: the cancelled seat was never revived, and a key is only issued
for an active one. There was no way out from inside the app — this path has no browser
route back to a fee-free seat — so the person stayed locked out for good.
After
A zero-price seat is revived at sign-in and the key is issued. A paid seat still answers
403 COWORK_SUB_CANCELLED / COWORK_SUB_PAUSED: resuming it is a payment, and that stays
a deliberate action in the dashboard.
FIX-0831-8: `TOKEN_MISSING` for a personal key now names the webhook mint failure
Before
When a personal key (vibe_api_*) had no Bitrix24 webhook because Bitrix24 had refused
the key owner the right to create incoming webhooks, or because the last mint attempt had
failed, the 401 TOKEN_MISSING response still reported a generic reason (for example
WEBHOOK_NOT_CONFIGURED) and pointed at GET /v1/me, without explaining that no webhook
was coming or who needed to act.
After
In these two scenarios error.details.reason now returns WEBHOOK_MINT_REFUSED_BY_PORTAL
(a Bitrix24 account administrator must act) or WEBHOOK_MINT_FAILED (the platform retries on its
own), and error.message names the cause and the addressee explicitly. For
WEBHOOK_MINT_REFUSED_BY_PORTAL the reconnect advice (POST /api/keys/:id/reconnect) is no
longer included — the platform mints the webhook automatically once a Bitrix24 account administrator
opens the right to create incoming webhooks, and retrying reconnect will not help. The
response code, HTTP status and error shape are unchanged.
Impact on integrators
Handle WEBHOOK_MINT_REFUSED_BY_PORTAL and WEBHOOK_MINT_FAILED as distinct
details.reason values alongside the already-documented ones — do not recreate the key or
loop on reconnect for these reasons; wait for the Bitrix24 account administrator or the platform's
automatic retry.
A separate note on the message text. error.message now branches on the reason and on
whether reconnect is available for the key — and this affects more than the two new
reasons. A key with no Bitrix24 scopes (VIBE_SCOPES_ONLY) gets its own wording, and keys
the platform would refuse reconnect for (cowork keys, app keys, keys bound to a server or
to a live agent) get advice to create a new key instead of advice to reconnect. The
details.reason values in those scenarios are unchanged. If your code matches on
error.message as a string, switch to details.reason: the message text is not a
contract and does change.
FIX-0831-9: vibe top-up is open to self-hosted accounts on the international installation
Before
A self-hosted account on the international installation always got the
BOX_TOPUP_NOT_AVAILABLE refusal. The subscription preview
GET /v1/cowork/subscription/preview returned topUpAvailable: false for such
an account, and the package catalogue came back empty.
After
A self-hosted account on the international installation tops up just like a
cloud one — it gets the package catalogue, a payment link and
topUpAvailable: true in the subscription preview. The
BOX_TOPUP_NOT_AVAILABLE refusal remains only where top-up is closed to
self-hosted accounts in the account's region. The response format is unchanged
and the successful response remains HTTP 200.