# API changes: October 3, 2026

[← Changelog](/docs/changelog) · [October 2026](/docs/changelog/2026-10)

### BC-1003-1: addresses and bookings no longer lose a filter condition in silence

> Old format supported until: not provided

**Before**

`GET /v1/addresses` and `GET /v1/bookings` accepted a filter that could not be applied and answered `200`. On addresses, a request like `?filter[city]=Berlin&filter=` returned **the entire address book of the Bitrix24 account**: during query-string parsing one spelling destroys the other, the condition disappeared, and the answer looked filtered. The spelling `?filter={"city":"Berlin"}&filter=` lost the condition the same way without a single bracket. On bookings, any envelope key other than `dateFrom` and `dateTo` never reached Bitrix24 and the answer covered the whole interval, while a destroyed envelope answered `MISSING_REQUIRED_PARAMS` — "pass `dateFrom` and `dateTo`" to a caller who had passed exactly those. `POST /v1/bookings/search` lost a condition the same way: a body of `{"filter":{"status":"CONFIRMED"}}` went to Bitrix24 without that key and the answer covered the whole interval.

**After**

Both routes inspect the `filter` envelope before calling Bitrix24. If at least one spelled condition did not arrive — both forms mixed, one name spelled at two different nesting levels (`?filter[a]=1&filter[a][b]=2`), nesting deeper than two levels — the answer is `400 INVALID_FILTER`, and the message names which case it is. On bookings, a key other than `dateFrom` and `dateTo`, as well as a `filter` that arrived as a string, a JSON object or an array, answers `400 UNSUPPORTED_FILTER` listing the accepted keys. `POST /v1/bookings/search` refuses the same way: the body is read only through `filter.within` with the keys `dateFrom` and `dateTo`, and any other key is `400 UNSUPPORTED_FILTER` before Bitrix24 is called.

**What integrators should do**

Pass the whole filter in **one form** — either bracket notation `?filter[field]=value` throughout, or a single JSON object `?filter={…}` carrying every condition. On `GET /v1/bookings`, narrow only by `dateFrom` and `dateTo` (flat parameters or the `filter[dateFrom]` / `filter[dateTo]` keys); on `POST /v1/bookings/search`, use the top-level pair or `filter.within`. Select the rest on your side. An empty `?filter=` still means "no filter" and such requests need no change. A request that used to get `200` with extra records now gets `400`, and that is the fix: the old answer carried data you had not asked for.

### FIX-1003-2: CRM forms no longer hide ordinary form text

**Before**

[GET /v1/crm-forms](/docs/entities/crm-forms/list) and [GET /v1/crm-forms/:id](/docs/entities/crm-forms/get) sometimes replaced ordinary form text with `[redacted]`. A word ending in "key" was treated as a credential name: the label `Monkey: Banana` came back as `[redacted]`. An encoded address such as `%2Frest%2F1%2Fhelp` was treated as an inbound webhook address and was hidden as well.

**After**

Ordinary form text is returned as is. Credentials in the text are still hidden: pairs such as `apiKey: …`, `api_key=…`, `x-api-key: …`, `token=…` and inbound webhook addresses, including encoded ones. The response remains HTTP 200, and the response fields are unchanged.

**Impact on integrators**

No action is required. Form names, field labels and result texts contain fewer false `[redacted]` values.

### FIX-1003-3: deleting a blocked key confirms revocation of its tokens

**Before**

[DELETE /v1/keys/:id](/docs/management-keys) could confirm deletion of a blocked key before access tokens issued by that key stopped being accepted.

**After**

Successful deletion of a blocked key confirms that all related live access tokens have already been revoked. If revocation cannot be completed temporarily, the key remains available for another deletion attempt.

**Impact on integrators**

The request does not need to change. Retry deletion after a transient failure.

### FIX-1003-4: a deleted authorization app no longer describes the application card

**Before**

When an application's authorization key was deleted before fix FIX-0922-6, the link to the
deleted authorization app stayed in place until a new key was issued, and the card kept
describing the deleted app:

- `GET /v1/applications` and `GET /v1/applications/{id}` returned `isEmbedded: true` when the
  deleted app had placements, and the `key` block showed the mask of its key when that key was
  blocked (`status: BLOCKED`);
- `POST /v1/cowork/applications/{id}/key` returned `APPLICATION_HAS_AUTH_KEY` in `warningCodes`,
  and the `key` block of the returned card showed the same mask.

**After**

A link to a deleted authorization app reads as "no authorization key" on all of these
endpoints: `isEmbedded` is `false`, the `key` block shows the personal key (`slot: "api"`) or an
empty slot, and `APPLICATION_HAS_AUTH_KEY` no longer appears in `warningCodes`. Successful
responses are preserved: the HTTP 200 response of both `GET` endpoints and the HTTP 201 response
of key issuance are unchanged. A live authorization app is described as before, including its
blocked key.

### BC-1003-5: static deploy uses the platform web server

> Old format supported until: not provided

**Before**

For `runtime: "static"`, the `start` field was required and the supplied command
controlled the application process.

**After**

For `runtime: "static"`, the `start` field is optional and ignored. The platform
serves the ready static build from `extractTo` on the selected `port` and supports
SPA routes through `index.html`.

**What integrators should do**

Remove `start` from static deploys and make sure the archive contains the ready
build directly in `extractTo`. If the application needs a custom start command,
select a suitable non-static runtime; for a manually managed existing unit on a
dedicated virtual machine, use `systemd: false`.
