
## Update a bot

New OAuth bots support `fetch` and `webhook`. The platform verifies bot ownership using the same OAuth application and the bot's exact ID and code, without sending `botToken` to the OAuth API. Delivery to `/api/bot/webhook` requires a recent, verified INSTALL/placement of the bound application; otherwise registration returns `409 BOT_APP_EVENT_ENROLLMENT_REQUIRED`. A previously issued application token does not replace this verification. Events received before initial registration completes are retained in a bounded encrypted inbox. Bot-token changes for new application-owned bots are refused (`409 BOT_OAUTH_POLICY_INVALID`); unmarked legacy bots are not automatically converted. A standalone OAuth key without a bound application can use `fetch` or its own receiver, but is not trusted by the platform's receiver.

The platform receiver is available to Agent and ManagedBot bots with a verified owner. An application bot without a verified owner receives `409 BOT_APP_EVENT_CONSUMER_REQUIRED` before any data is written to Bitrix24. It can use `fetch` or its own callback. Events for an already published bot after a Bitrix24 account address change may remain in encrypted quarantine until the recovered identity is verified and published. Delivery requires an unchanged callback binding, continued eligibility of the application, author and owner membership, and verified authority to deliver the recovered events. If that basis changes or cannot be verified, held events are permanently discarded while bot identity recovery continues. Bounded retention does not guarantee delivery. Each recovery can retain at most 256 events and 4 MiB of ciphertext for 72 hours. A duplicate event does not extend retention. On overflow, the receiver returns `503` without acknowledging receipt.

`PATCH /v1/bots/:botId`

Updates a bot's properties. Pass only the fields you want to change.

> **Two body forms — both valid.** The platform accepts both a **flat** body (the same as for `POST /v1/bots`) and the Bitrix24 format with a `fields` wrapper. If the body contains a **non-empty** `fields` wrapper, the request is forwarded to Bitrix24 unchanged. The values `[]`, `null`, `false`, `0` and `""` do not count as a wrapper — the body is read as flat. An empty object `{}` does count as a wrapper: it disables the expansion, and top-level fields are not applied. Without a wrapper, the known top-level fields are automatically expanded into `fields.properties.*` / `fields.*`, and an unrecognized key is dropped by that expansion — Bitrix24 would ignore it anyway. For every field that Bitrix24 applies, the behavior of both forms is identical.
>
> **The one exception is `disabled`.** That field is handled by the platform itself and never travels to Bitrix24, so it is read **only** from the top level of the body. Inside the `fields` wrapper it is not a platform field at all: `{"fields": {"disabled": false}}` goes down the ordinary update path, and on a disabled bot that path returns `410 BOT_DISABLED`. The re-enable call is the flat body `{"disabled": false}` and nothing else.

## Request fields (body)

| Parameter (flat) | Parameter (Bitrix24 format) | Type | Description |
|---|---|-----|---------|
| `name` | `fields.properties.name` | string | New bot name, at most 50 Unicode code points. Longer names are refused before the update, without truncation. The limit applies to the effective name, including the `PROPERTIES` and `NAME` aliases; an ignored flat name is not validated when a wrapper is present |
| `lastName` | `fields.properties.lastName` | string | New last name |
| `workPosition` | `fields.properties.workPosition` | string | New job title |
| `color` | `fields.properties.color` | string | New avatar color |
| `gender` | `fields.properties.gender` | string | Gender: `M` or `F` |
| `avatar` | `fields.properties.avatar` | string | Bot avatar: PNG or JPEG as a base64 string without the `data:image/...;base64,` prefix, up to ~50 KB. See "Known specifics" |
| `eventMode` | `fields.eventMode` | string | Event mode: `fetch` or `webhook` |
| `webhookUrl` | `fields.webhookUrl` | string | URL for push notifications |
| `isHidden` | `fields.isHidden` | boolean | Hide from the contact list |
| `isReactionsEnabled` | `fields.isReactionsEnabled` | boolean | Allow reactions |
| `backgroundId` | `fields.backgroundId` | string | Chat background: `azure`, `mint`, `steel`, `slate`, `teal`, `cornflower`, `sky`, `peach`, `frost` |
| `isSupportOpenline` | `fields.isSupportOpenline` | boolean | Open Channels support (only for `type: "openline"`) |
| — | `fields.botToken` | string | For personal-key bots and OAuth bots registered under the previous contract. New application-owned OAuth bots reject this field with `409 BOT_OAUTH_POLICY_INVALID`. Your own bot token instead of the platform-issued one; events use `custom` followed by this value (see [Webhook authenticity](/docs/bots/events/webhook)). Use 32 to 40 characters from the `[A-Za-z0-9_-]` alphabet. A value outside those bounds is rejected with `400 BOT_TOKEN_INVALID` before Bitrix24 is called, and the bot token is left unchanged. Accepted only in the `fields` form — the field has no top-level equivalent. See "Known specifics" |
| `disabled` | — | boolean | Re-enables a bot that the platform disabled. Accepted only in the flat form and only as `false` — the field has no equivalent inside `fields`, because it is applied by the platform and is never sent to Bitrix24. This is the only field that works on a disabled bot: the platform returns `200` before the `BOT_DISABLED` check, with the body `{"success": true, "data": {"id": "<string bot record id>", "disabled": false}}` (no `bot` and no `users`). `disabled: true` is rejected with `400 DISABLE_NOT_ALLOWED`. See "Known specifics" |

## Examples

### curl — personal key

```bash
curl -X PATCH https://vibecode.bitrix24.com/v1/bots/42 \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "properties": { "name": "New name", "color": "MINT" },
      "eventMode": "fetch"
    }
  }'
```

### curl — OAuth application

```bash
curl -X PATCH https://vibecode.bitrix24.com/v1/bots/42 \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "properties": { "name": "New name", "color": "MINT" },
      "eventMode": "fetch"
    }
  }'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/bots/42', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    fields: {
      properties: { name: 'New name', color: 'MINT' },
      eventMode: 'fetch',
    },
  }),
})
const { data } = await res.json()
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/bots/42', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    fields: {
      properties: { name: 'New name', color: 'MINT' },
      eventMode: 'fetch',
    },
  }),
})
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `data.bot` | object | The updated bot. The field set matches the [registration](/docs/bots/management/create) response |
| `data.bot.id` | number | Bot ID in the Bitrix24 account |
| `data.bot.code` | string | The bot's system code |
| `data.bot.type` | string | Bot type: `bot`, `personal`, or `supervisor` |
| `data.bot.eventMode` | string | Event delivery mode: `fetch` or `webhook` |
| `data.users` | array | The bot's user profile in the Bitrix24 account |

## Response example

The main fields are shown. The full set of bot fields is in the [registration](/docs/bots/management/create) response.

```json
{
  "success": true,
  "data": {
    "bot": {
      "id": 42,
      "code": "my_helper_bot",
      "type": "bot",
      "eventMode": "fetch",
      "isHidden": false,
      "isReactionsEnabled": true,
      "language": "en"
    },
    "users": []
  }
}
```

## Error response example

403 — the bot belongs to a different key:

```json
{
  "success": false,
  "error": {
    "code": "BOT_ACCESS_DENIED",
    "message": "This bot belongs to a different API key"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `INVALID_BOT_ID` | `botId` is not a number |
| 400 | `BOT_NAME_TOO_LONG` | The effective name exceeds 50 Unicode code points. No update is attempted, and the name and other properties stay unchanged; supply a shorter name |
| 400 | `BOT_TOKEN_INVALID` | `fields.botToken` is shorter than 32 or longer than 40 characters, contains characters outside `[A-Za-z0-9_-]`, or was not passed as a string. Bitrix24 is not called and the bot token stays as it was |
| 400 | `DISABLE_NOT_ALLOWED` | The body carries `disabled: true`. Only the system can disable a bot; to remove the bot, use `DELETE /v1/bots/:botId` instead |
| 404 | `BOT_NOT_FOUND` | Bot not found |
| 403 | `BOT_ACCESS_DENIED` | The bot belongs to a different API key |
| 403 | `SCOPE_DENIED` | The API key does not have the `imbot` scope |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is read-only — see [access rights](/docs/access-rights) |
| 409 | `BOT_RECOVERY_IN_PROGRESS` | Automatic recovery after an account address change. Wait for `Retry-After: 5`. |
| 409 | `BOT_EFFECT_IN_PROGRESS` | Another bot change is being reconciled. Wait for `Retry-After`: 30 seconds, or 1–300 until its scheduled check. |
| 409 | `BOT_UNAVAILABLE` | The bot state requires repair by support. No `Retry-After`; stop automatic retries and contact support. |
| 409 | `BOT_ID_REPLACED` | The old bot ID was replaced. Use `error.details.botId` as the current ID. No `Retry-After`. |
| 409 | `BOT_REGISTRATION_CONTEXT_CHANGED` | Only on the flat `disabled: false` re-enable path: lifecycle or ownership changed concurrently. No `Retry-After`; re-read the bot before retrying. |
| 409 | `BOT_OAUTH_POLICY_INVALID` | The change conflicts with OAuth application ownership, including attempts to change `botToken` for a new OAuth bot |
| 409 | `BOT_APP_EVENT_ENROLLMENT_REQUIRED` | The platform receiver requires a fresh verified INSTALL/placement of the bound application |
| 409 | `BOT_APP_EVENT_CONSUMER_REQUIRED` | The platform receiver requires verified Agent or ManagedBot ownership. Use that owner's key, or choose `fetch` or your own receiver |
| 410 | `BOT_DISABLED` | The bot is disabled and does not process API calls. **Exception:** the flat body `{"disabled": false}` is the re-enable path — it is handled before this check and returns `200`. Any other request body for a disabled bot results in this error, including `disabled` inside `fields`. How to restore the bot — [Bot disabled](/docs/bots/troubleshooting#bot-disabled-bot_disabled) |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |
| 422 | `APP_HOST_NOT_ALLOWED_HERE` | `webhookUrl` points to a named host in the platform's app domain (`<name>.<domain>`, not `app-…`), and that name is not assigned to a server in your Bitrix24 account. Nothing is stored and Bitrix24 is not called. Your server's name is accepted and stored as that server's `app-…` address |

Full list of common API errors — [Errors](/docs/errors).

## Known specifics

**Request body format.** Like `POST /v1/bots`, PATCH accepts a flat body (`{ name, eventMode, ... }`). It also accepts the Bitrix24 format with a `fields` wrapper. See the top of the page for how the platform detects a wrapper and when it expands a flat body.

**`type` cannot be changed:** the `type` field is not accepted on update.

**Re-enabling a disabled bot.** `{"disabled": false}` in the flat body is the only API call that clears the disabled state without `/reauth` — and the only call this endpoint handles for a disabled bot. The platform processes it before the `BOT_DISABLED` check without calling Bitrix24:

```bash
curl -X PATCH https://vibecode.bitrix24.com/v1/bots/42 \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"disabled": false}'
```

```json
{ "success": true, "data": { "id": "cm3k9x2a10001qz7f8h2b4d6e", "disabled": false } }
```

In this response, `id` is the string identifier of the bot record on the platform, not the `botId` from the path. The response carries no `bot` and no `users` — nothing was read from Bitrix24. On an already enabled bot the call is a no-op and returns the same body. The `fields` form does not work here: `{"fields": {"disabled": false}}` is forwarded to Bitrix24 as an ordinary update, so on a disabled bot it returns `410 BOT_DISABLED` and the bot stays disabled. `disabled: true` is never accepted (`400 DISABLE_NOT_ALLOWED`) — to retire a bot, use `DELETE /v1/bots/:botId`. See [Bot disabled](/docs/bots/troubleshooting#bot-disabled-bot_disabled) for guidance on choosing a recovery path. This call only clears the state and the authorization-error counter, while `/reauth` additionally verifies access.

The following token guidance applies to personal-key bots and OAuth bots registered under the previous contract.

**Set your own bot token when your receiver needs a known verification value.** The platform generates a token at registration and does not return it in API responses. For personal-key bots and OAuth bots registered under the previous contract, Bitrix24 sends `custom` followed by the bot token in `auth.application_token`; see [Webhook authenticity](/docs/bots/events/webhook). Use a random value of 32 to 40 characters — for example 32 hexadecimal characters. Descriptive strings such as `support-bot-2026` do not meet these requirements. New application-owned OAuth bots use the application token instead and reject `fields.botToken` with `409 BOT_OAUTH_POLICY_INVALID`.

**Avatar format.** The `avatar` field accepts a PNG or JPEG image as a base64 string **without** the `data:image/...;base64,` prefix — pass only the base64 data itself. A string with the `data:` prefix results in a 422 response. The maximum size is ~50 KB: if the limit is exceeded, the request completes successfully (`success: true`), but the avatar is not saved and the bot's avatar remains empty. The endpoint accepts JSON only — file upload via `multipart/form-data` is not supported (415 response). Pass the value as `avatar` (flat form) or as `fields.properties.avatar` (the `fields` form) — the result is the same.

## See also

- [Get a bot](/docs/bots/management/get)
- [Register a bot](/docs/bots/management/create)
- [Bot platform](/docs/bots)
- [Limits and optimization](/docs/optimization)
