# API changes: August 2, 2026

[← Changelog](/docs/changelog) · [August 2026](/docs/changelog/2026-08)

### FIX-0802-1: a batch sub-call with its own start=-1 no longer returns a fabricated total

A `POST /v1/batch` sub-call that carries its own `params.start: -1` no longer receives a fabricated record count. `-1` is Bitrix24's own instruction to skip counting the collection, so the Bitrix24 answer holds no count; the envelope used to take whatever was at hand as the size — the `result_total` echo from methods that answer `0` next to a full page in this mode, or simply the length of the first page. Both branches are affected: a sub-call with `limit` up to 50, and a sub-call with `limit` above 50, which is read by its own auto-pagination.

**Before**

`{"entity":"activities","action":"list","params":{"start":-1}}` → `meta.<id>.total: 0` and `data.totals.<id>: 0` next to 50 records, `meta.<id>.hasMore: false`.
`{"entity":"deals","action":"list","params":{"limit":5000,"start":-1}}` → 50 records, `meta.<id>.total: 50`, `meta.<id>.hasMore: false` — a request for 5000 records answered with a confident "there are only 50".

**After**

Such a sub-call carries no `total` key in `meta.<id>` and none in `data.totals` — no count was ordered, and there is nothing to build one from. `hasMore` is decided by page fullness: a page filled up to the requested limit → `true`, a short page → `false`. Fullness is measured against the ceiling that actually went to Bitrix24, so `{"limit":10,"start":-1}` answered with 10 records is a full page and now reports `hasMore: true` instead of `false`. The walk builds no continuation plan out of an invented size and returns a contiguous prefix.

The "no count ordered" signal is read off a normalised value: `start` is coerced to an integer the way Bitrix24 does it (truncation toward zero, a string read by its numeric prefix), so `-1`, `"-1"`, `-1.5`, `"-1abc"` and `"-1 x"` are one and the same. A positive offset (`start: 100`) is an ordinary counted cursor and still returns its `total`.

A value that is not a number at all (`"abc"`, an empty string, `null`, an object, an array, `true`) is no longer sent to Bitrix24 — it reads as if it had not been supplied. The page does not change ("start from zero" and "no `start`" are the same page), but such a sub-call falls under the platform's ordinary choice and may come back without a `total`.

Separately: a sub-call that failed no longer publishes `data.totals.<id>` next to its error.

**Impact on integrators**

A client that sent `start: -1` and read `total` was given a knowingly wrong number: zero for the methods that echo `result_total: 0`, the page length for the rest. A read loop driven by `meta.hasMore` stopped on the first page. Check for the presence of the key (`meta.<id>.total !== undefined`) and drive continuation from `meta.<id>.hasMore`. If you need an exact count, do not send `start: -1`: that value is the client's own instruction to skip counting, so there is nothing to return for such a sub-call and `withTotal: true` will not bring it back.

### BC-0802-2: self-hosted account access is no longer granted unconditionally

> Old format supported until: 30.01.2027

**Before**

A self-hosted account was always treated as commercial: the flag was set when the account was connected, not by anything the platform had checked. Nothing about the account's own state could change its access.

**After**

A self-hosted account is now evaluated against the same access rules as any other account, instead of being granted access unconditionally. Where those rules are not met, [POST /v1/infra/servers](/docs/infra) answers `402` with a denial code in the body instead of creating a server, and `capabilities.servers.create` in [GET /v1/me](/docs/quickstart) comes back unavailable with the reason. The same applies when creating agents and bots that provision a server.

A paid self-hosted licence does not by itself grant access: the licence covers the installation, access is decided separately. An installation that is paid for but does not meet the access rules is denied.

While the account's state cannot be read, access is **not** restricted: a missing signal is not treated as a failed check.

The denial is switched on by a separate decision, not by the release: until then the responses are unchanged. Two fields change earlier — on the release itself:

- `wasEverCommercial` in [GET /v1/me](/docs/quickstart) stops being one-way for self-hosted accounts: where no qualifying history and no payments were found, the value changes once from `true` to `false` — the previous value was set at connection time, not by observation.
- `placements.bindPrerequisite` in the same response starts describing the model that actually applies to the account (a different `errorCodes` set and a different `note`) — an account with no resolved region used to be described as international.

**What integrators should do**

Check `capabilities.servers.create` in [GET /v1/me](/docs/quickstart) before creating infrastructure, and handle `402` on creation — the denial code and message come in the response body. If the account's state has changed and the denial persists, force a refresh: `GET /v1/me?refresh=tariff`. Do not rely on `wasEverCommercial` being monotonic for self-hosted accounts.
