For AI agents: markdown of this page — /docs-content-en/bots/management/transfer.md documentation index — /llms.txt

Transfer bot ownership

POST /v1/bots/:botId/transfer

Moves a bot's ownership to another API key of the same Bitrix24 account and the same user (or an account admin). Resolves the case where a bot is orphaned after the app is recreated: the owning key is revoked and the bot's runtime stops working. The transfer changes only the key binding — the botId, chat history, and subscriptions are preserved. No B24 call is made; after the transfer, verify the new key's B24 binding via POST /v1/bots/:botId/reauth.

Parameters

Parameter Type Required Description
botId number yes Bot ID (path parameter)
targetApiKeyId string yes ID of the target API key (request body)

The target key must be active (ACTIVE), in the same account as the bot, belong to the same user (or the caller is an account admin), carry the imbot scope, and not be a platform-managed service key (cowork, agent-seat, agent-maintenance) — those have a platform-driven lifecycle, so the bot would be orphaned again when they rotate.

Examples

curl

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/bots/42/transfer \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "targetApiKeyId": "ck_target_key_id" }'

JavaScript

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/bots/42/transfer', {
  method: 'POST',
  headers: { 'X-Api-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({ targetApiKeyId: 'ck_target_key_id' }),
})
const { data } = await res.json()
console.log(data) // { transferred: true, botId: 42, fromApiKeyId: '...', toApiKeyId: '...' }

Response fields

Field Type Description
data.transferred boolean true if the binding changed; false if the key already owned the bot (idempotent no-op)
data.botId number Bot ID
data.fromApiKeyId string ID of the previous owner key (only when transferred: true)
data.toApiKeyId string ID of the new owner key

Response example

JSON
{
  "success": true,
  "data": {
    "transferred": true,
    "botId": 42,
    "fromApiKeyId": "ck_old_owner",
    "toApiKeyId": "ck_target_key_id"
  }
}

If the target key already owns the bot, no transfer happens and transferred: false is returned (with fromApiKeyId equal to toApiKeyId — the current owner).

Error response example

400 — the target key is not eligible (with a reason field):

JSON
{
  "success": false,
  "error": {
    "code": "TARGET_KEY_INVALID",
    "message": "Target API key is not eligible to own this bot.",
    "reason": "wrong_user"
  }
}

Errors

HTTP Code Description
400 INVALID_BOT_ID botId is not a number
400 INVALID_PARAMS targetApiKeyId is missing or not a string
400 TARGET_KEY_INVALID The target key is not eligible. reason: not_active · wrong_portal · wrong_user · missing_scope · expired · system_key (platform-managed service key)
403 NOT_BOT_OWNER The caller does not own the bot (must be the same user as the owner key, or an account admin)
403 SCOPE_DENIED The API key does not have the imbot scope
403 WRITE_BLOCKED_READONLY_KEY The key is in read-only mode
404 BOT_NOT_FOUND The bot was not found in the account
404 TARGET_KEY_NOT_FOUND The target key was not found
409 BOT_TRANSFER_NOT_ALLOWED The bot is managed by an agent or a managed bot — transfer it via that resource, not directly
409 BOT_TRANSFER_CONFLICT Ownership changed concurrently — re-read the current owner and retry if still needed

Full list of common API errors — Errors.

Known specifics

When to use. The bot stopped working after the OAuth app was recreated: the owning key is revoked and the bot's runtime no longer starts. Transferring to an active personal key (vibe_api_*) of the same account restores the bot — the runtime does not depend on which app registered the bot.

Authorization is by user, not by key. The transfer is allowed for the bot owner (the same Vibe user as the current owner key — even if that key is already revoked) or an account admin. Holding the current owner key is not required — that is exactly why the transfer works when the original key is revoked.

Idempotency. Transferring to the current owner key (including a revoked one) is a safe no-op: transferred: false is returned, the binding is unchanged, and no audit entry is written.

Verify after the transfer. No B24 call is made during the transfer. To confirm the new key can drive the bot, call POST /v1/bots/:botId/reauth — it validates the new key's B24 binding.

See also