How to Call Chatbot 2.0 Methods and Refresh the Authorization Token
If you are developing integrations for Bitrix24 using AI tools (Codex, Claude Code, Cursor), connect to the MCP server so that the assistant can utilize the official REST documentation.
Chatbot imbot.v2 methods are called in the same way as other REST API methods, but the authorization method changes the request parameter composition and determines whether the access token needs to be refreshed. The rules below apply only to imbot.v2: calling deprecated methods imbot.* is described on the How to Call Deprecated Chatbot Methods page.
To call methods on behalf of a bot, register the bot using the imbot.v2.Bot.register method. For an OAuth scenario, the application must be installed in Bitrix24: Bitrix24 issues the first token pair upon installation. How to retrieve and retain this pair is described in Application Installation Scenarios.
Parameters, responses, and error codes for individual methods are described on the method pages in the Chatbots 2.0 section. If messages need to be sent on behalf of a user rather than a bot, use the im.* methods in the Chats section — authorization in them is structured differently, and botToken is not involved.
Scope:
imbotWho can execute the methods: the owner of the registered bot — the application or webhook on behalf of which the bot was registered. Exceptions: imbot.v2.Bot.register — an authorized user, imbot.v2.Revision.get — any user
Which Tokens Are Involved in the Call
Four different tokens are encountered in bot calls. Only access_token must be refreshed.
|
Token |
Where it is passed |
Where it comes from |
Lifespan |
|
Webhook code — denoted as |
In the request path: |
Created in the Bitrix24 interface when setting up an inbound webhook |
Valid until the webhook is deleted |
|
|
As a request parameter along with |
Set by you in |
Valid until you change it using the imbot.v2.Bot.update method |
|
|
As the |
Issued by the OAuth server upon application installation and again with each token pair refresh. An application with a UI receives a ready-to-use token in the |
One hour |
|
|
Not passed in method calls — only in the request to refresh the token pair |
Issued by the OAuth server along with |
180 days |
botToken is not an OAuth token; it does not expire and is not involved in authorization renewal. It identifies the bot during a webhook call: Bitrix24 uses it to determine the bot owner instead of the client_id application.
How to Choose an Authorization Method
|
Criterion |
Inbound webhook |
OAuth |
|
When to use |
Local integration, AI agent, testing within a single Bitrix24 |
Market application or an internal application working across multiple Bitrix24 instances |
|
Request format |
|
|
|
|
Mandatory for all |
Not needed: the bot is linked to the application via |
|
Token refresh |
Not required |
Required when |
Calls via an inbound webhook are performed only via the HTTPS protocol: if accessed via HTTP, an error INVALID_REQUEST with the description Https required will be returned. Such calls are performed with the permissions of the user who created the webhook and within the scope selected for the webhook.
A detailed description of both methods is available in the Authorization section.
Basic Method Call
Below is a call to the imbot.v2.Chat.Message.send method in two cURL tabs, one for each authorization method, and via the ready-to-use PHP CRest wrapper.
How to Use Examples in Documentation
curl -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"botId":456,"botToken":"my_bot_token","dialogId":"chat5","fields":{"message":"Enter search string"}}' \
https://**put_your_bitrix24_address**/rest/**put_your_user_id_here**/**put_your_webhook_here**/imbot.v2.Chat.Message.send
curl -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"botId":456,"dialogId":"chat5","fields":{"message":"Enter search string"},"auth":"**put_access_token_here**"}' \
https://**put_your_bitrix24_address**/rest/imbot.v2.Chat.Message.send
require_once('crest.php');
$result = CRest::call(
'imbot.v2.Chat.Message.send',
[
'botId' => 456,
// 'botToken' => 'my_bot_token', // only during webhook authorization
'dialogId' => 'chat5',
'fields' => [
'message' => 'Enter search string',
],
]
);
if (!empty($result['error'])) {
echo 'Error: ' . $result['error_description'];
} else {
echo 'Message ID: ' . $result['result']['id'];
}
botId is returned by the imbot.v2.Bot.register method upon bot registration. The dialogId format is chat{chatId} for group chats and {userId} for private chats; for more details, see: dialogId Format.
Examples of the same call in JS, PHP, and BX24.js can be found in the "Code Examples" section on the imbot.v2.Chat.Message.send method page.
Ready-to-use wrappers do not automatically insert botToken — when using webhook authorization, add it to the call parameters yourself.
What the Call Returns
The response of any method consists of a result block containing the method data and a time service block containing the request execution time. For imbot.v2.Chat.Message.send, the result block looks like this:
{
"result": {
"id": 789,
"uuidMap": {}
}
}
The composition of result is unique to each method and is described in the "Returned Data" section on its page.
Authorization Errors
|
Code |
Reason |
What to do |
|
|
Webhook call without the |
Pass the |
|
|
A bot with the specified |
Call the bot methods from the same application that registered it, or pass the same |
|
|
|
Update the token pair and retry the request; the procedure is described in the OAuth token update section |
|
|
Invalid |
Check authorization data |
|
|
The token does not have |
Add the |
System errors expired_token and NO_AUTH_FOUND are returned with status 401, while insufficient_scope is returned with status 403. Full list: Error Codes.
OAuth Token Refresh
This section applies only to the OAuth scenario.
When to Refresh the Token
Refresh the token upon an error rather than on a schedule:
- Call the method using the saved
access_token. - If an error
expired_tokenis returned with status401— request a new token pair using the savedrefresh_token. - Retain the new token pair on your side: along with
access_token, the server returns a newrefresh_tokenvalue; use this value moving forward. - Retry the original request with the new
access_token.
If the authorization server does not return a new pair, it means the refresh_token itself has expired or the application has been removed from Bitrix24. Authorization cannot be restored via a request — the application must be reinstalled, and the tokens issued during installation must be retained.
Do not refresh the token preemptively — before every call, once an hour, or on a schedule. This creates unnecessary load on the authorization server, which may cause the application to be blocked by automated systems. For more details, see: OAuth 2.0 Automatic Token Renewal
How to Refresh the Token
Ready-made wrappers handle the refresh process automatically:
- PHP CRest — a set of PHP files for your web server; requires the cURL module. It renews tokens automatically and manages their storage itself.
- b24phpsdk — a Composer package with typed services; requires PHP 8.2 or higher. It updates an expired
access_tokenand notifies you via theAuthTokenRenewedEventevent; the developer is responsible for implementing the storage of the new pair. - b24jssdk — a JavaScript library installed via npm. It updates the pair upon an error
expired_token; the developer is responsible for implementing the storage of the new pair.
The restAuth function below is required when you call the Bitrix24 REST API using your own code without a wrapper.
The restAuth Function
The function exchanges the saved refresh_token for a new token pair. The constants CLIENT_ID and CLIENT_SECRET are the application code and secret key from the partner portal or from the local application card in Bitrix24.
The refresh is performed via a GET request to the authorization server with four parameters in the query string: grant_type=refresh_token, client_id, client_secret, and refresh_token. The server address depends on the license region and is returned in the domain field of the token request response. If the application operates in multiple regions, retrieve the host from the domain field rather than from a constant.
const OAUTH_SERVER = 'https://oauth.bitrix.info/oauth/token/';
const CLIENT_ID = '**put_your_client_id_here**';
const CLIENT_SECRET = '**put_your_client_secret_here**';
/**
* Refresh OAuth token pair.
*
* @param array $auth Saved authorization data with refresh_token
*
* @return array|false New token pair or false if refresh failed
*/
function restAuth(array $auth)
{
if (!CLIENT_ID || !CLIENT_SECRET || empty($auth['refresh_token']))
{
return false;
}
$queryData = http_build_query(
[
'grant_type' => 'refresh_token',
'client_id' => CLIENT_ID,
'client_secret' => CLIENT_SECRET,
'refresh_token' => $auth['refresh_token'],
]
);
$curl = curl_init();
curl_setopt_array(
$curl,
[
CURLOPT_HEADER => 0,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => OAUTH_SERVER . '?' . $queryData,
]
);
$result = curl_exec($curl);
curl_close($curl);
$tokens = json_decode($result, true);
return empty($tokens['access_token']) ? false : $tokens;
}
The server returns JSON, from which you must retain four fields:
access_token— the new access token for theauthparameterrefresh_token— the new value; do not use the old one anymoreexpires_in— the lifetime of theaccess_tokenin secondsdomain— the authorization server domain for the next refresh
The full structure of the authorization server response is described on the OAuth 2.0 Automatic Token Renewal page.
How to Use restAuth
callRest in the example is your method call function, which passes access_token into the auth parameter.
$params = [
'botId' => 456,
'dialogId' => 'chat5',
'fields' => ['message' => 'Enter search string'],
];
$result = callRest('imbot.v2.Chat.Message.send', $params, $auth['access_token']);
if (($result['error'] ?? '') === 'expired_token')
{
$newAuth = restAuth($auth);
if ($newAuth === false)
{
// refresh_token expired or application deleted — reinstallation of the application is required
error_log('Token refresh failed');
}
else
{
$auth = $newAuth;
saveAuth($auth); // save the new token pair in your storage
$result = callRest('imbot.v2.Chat.Message.send', $params, $auth['access_token']);
}
}
Secret Storage
Consider the webhook code along with its URL, CLIENT_SECRET, refresh_token, and botToken as secrets:
- Store them only on your server — the webhook code provides full access to the Bitrix24 REST API within its scope and does not require separate confirmation
- Do not pass them to the browser, links, or application logs
- Do not save them in a repository — move them to environment variables or a secure data store
General integration security rules can be found in Security Recommendations.
Common Sources of Confusion
Two places where similar names mean different things:
- In
fields.*, parameters describing the content — message text, bot properties, command configurations — are nested. Identifiers and service parameters such asbotId,dialogId,botToken, andoffsetare passed at the top level of the request eventModeof a bot is not linked to the authorization method: a bot with webhook authorization can operate infetchmode, and the OAuth application bot is in modewebhook. The event delivery modes themselves are described in the Event Delivery Modes section
Continue Learning
- Chatbots 2.0: Quick Start — the first bot from registration to responding to a message
- Chatbots 2.0: Overview of Methods — all methods in the section, bot types, limits, and the
dialogIdformat - Register a Bot imbot.v2.Bot.register — where
botTokenis defined andeventModeis selected - Send Message imbot.v2.Chat.Message.send — parameters, responses, and method error codes from the examples
- OAuth 2.0 token automatic renewal — the full OAuth token lifecycle
- How to Call Deprecated Chatbot Methods — only for integrations using deprecated
imbot.*methods