@ihazz/bitrix24 0.2.5 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,18 +1,17 @@
1
1
  # @ihazz/bitrix24
2
2
 
3
- OpenClaw channel plugin for Bitrix24 Messenger. Allows using a Bitrix24 chatbot as a communication interface for OpenClaw AI agents.
3
+ OpenClaw channel plugin for Bitrix24 Messenger based on Bot Platform 2.0 (`imbot.v2.*` / `im.v2.*`).
4
4
 
5
- ## Features
5
+ ## Current Status
6
6
 
7
- - Receive messages from Bitrix24 users via webhook
8
- - Send responses through the Bitrix24 REST API (`imbot.message.add`)
9
- - Typing indicator (`imbot.chat.sendTyping`)
10
- - Markdown to BB-code conversion
11
- - Interactive keyboard buttons
12
- - Rate limiting (2 req/sec token-bucket)
13
- - Webhook deduplication (MESSAGE_ID, 5 min TTL)
14
- - Access control: open, allowlist, pairing modes
15
- - Multi-account support (multiple portals)
7
+ - Works with Bitrix24 Bot Platform 2.0
8
+ - Supports direct messages only
9
+ - Supports inbound and outbound media
10
+ - Uses secure default access policy: `webhookUser`
11
+ - Supports optional pairing flow for controlled approval
12
+ - Production recommendation today: one portal per plugin instance
13
+
14
+ Group chats are intentionally not supported. If the bot is added to a group chat, it sends a short notice and leaves the chat.
16
15
 
17
16
  ## Installation
18
17
 
@@ -20,230 +19,213 @@ OpenClaw channel plugin for Bitrix24 Messenger. Allows using a Bitrix24 chatbot
20
19
  openclaw plugins install @ihazz/bitrix24
21
20
  ```
22
21
 
22
+ Allow the plugin in `openclaw.json`:
23
+
24
+ ```json
25
+ {
26
+ "plugins": {
27
+ "allow": ["bitrix24"]
28
+ }
29
+ }
30
+ ```
31
+
23
32
  ## Bitrix24 Setup
24
33
 
25
- 1. Go to your Bitrix24 portal: **Apps** > **Developer resources** > **Other** > **Inbound webhook**
26
- 2. Name it, e.g. "OpenClaw Bot"
27
- 3. Under **Access permissions**, select scopes:
28
- - **`imbot`** chatbot management (register, send/update messages)
29
- - **`im`** — messenger (chats, typing indicator)
30
- - **`disk`**file operations (optional, for future support)
31
- 4. Click **Save**
32
- 5. Copy the **Webhook URL** it will look like:
33
- ```
34
- https://your-portal.bitrix24.com/rest/1/abc123xyz456/
35
- ```
34
+ Create an inbound webhook in Bitrix24:
35
+
36
+ 1. Open **Apps** > **Developer resources** > **Other** > **Inbound webhook**
37
+ 2. Create a webhook for your OpenClaw bot
38
+ 3. Grant scopes:
39
+ - `imbot`the minimum scope required for full bot operation
40
+ - `im` — reserved for future `agentMode` support; `agentMode` is not production-ready yet and will be available in future versions
41
+ - you may also grant any extra scopes beyond this set if they are needed for your Bitrix24 scenarios
42
+ 4. Save the webhook and copy the URL
36
43
 
37
- > The webhook URL contains authentication (user_id + token) — do not publish or commit it to a repository.
44
+ Example webhook URL:
45
+
46
+ ```text
47
+ https://your-portal.bitrix24.com/rest/1/abc123xyz456/
48
+ ```
49
+
50
+ The webhook URL contains credentials. Do not publish it or commit it to a repository.
38
51
 
39
52
  ## Configuration
40
53
 
41
- Add to your `openclaw.json`:
54
+ Minimal configuration:
42
55
 
43
56
  ```json
44
57
  {
45
58
  "channels": {
46
59
  "bitrix24": {
47
60
  "webhookUrl": "https://your-portal.bitrix24.com/rest/1/abc123xyz456/",
48
- "callbackUrl": "https://your-server.com/hooks/bitrix24",
49
61
  "botName": "OpenClaw",
50
- "botCode": "openclaw",
51
- "dmPolicy": "open",
52
- "allowFrom": ["*"],
53
- "showTyping": true,
54
- "capabilities": ["inlineButtons"]
62
+ "dmPolicy": "webhookUser",
63
+ "showTyping": true
55
64
  }
56
65
  }
57
66
  }
58
67
  ```
59
68
 
60
- Set allow in plugin section:
69
+ Webhook delivery mode:
70
+
61
71
  ```json
62
72
  {
63
- "plugins": {
64
- "allow": [
65
- "bitrix24"
66
- ],
73
+ "channels": {
74
+ "bitrix24": {
75
+ "webhookUrl": "https://your-portal.bitrix24.com/rest/1/abc123xyz456/",
76
+ "callbackUrl": "https://your-server.com/hooks/bitrix24",
77
+ "eventMode": "webhook"
78
+ }
67
79
  }
68
80
  }
69
81
  ```
70
- Only `webhookUrl` is required. The gateway will not start without it.
71
82
 
72
- ### Configuration Options
83
+ If `eventMode` is omitted, the plugin uses:
84
+
85
+ - `webhook` when `callbackUrl` is set
86
+ - `fetch` when `callbackUrl` is not set
87
+
88
+ ## Configuration Options
73
89
 
74
90
  | Parameter | Default | Description |
75
91
  |---|---|---|
76
- | `webhookUrl` | — | Bitrix24 REST webhook URL (**required**) |
77
- | `callbackUrl` | — | Full public URL for bot EVENT_HANDLER (e.g. `https://your-server.com/hooks/bitrix24`). Path is auto-extracted for route registration. (**required**) |
78
- | `botName` | `"OpenClaw"` | Bot display name (shown in welcome message) |
79
- | `botCode` | `"openclaw"` | Unique bot code for `imbot.register` |
80
- | `dmPolicy` | `"open"` | Access policy: `"open"` / `"allowlist"` / `"pairing"` |
81
- | `allowFrom` | | Allowed B24 user IDs (when `dmPolicy: "allowlist"`) |
82
- | `showTyping` | `true` | Send typing indicator before responding |
83
- | `streamUpdates` | `false` | Stream response via message updates |
84
- | `updateIntervalMs` | `10000` | Throttle interval for streaming updates (ms, min 500) |
85
- | `enabled` | `true` | Whether this account is enabled |
86
- | `capabilities` | `[]` | Runtime capabilities to enable (see below) |
87
-
88
- ### Capabilities
89
-
90
- The `capabilities` array activates additional runtime features for the AI agent. Add them to the channel config in `openclaw.json`:
92
+ | `webhookUrl` | — | Bitrix24 REST webhook URL. Required. |
93
+ | `callbackUrl` | — | Public HTTPS URL for webhook delivery mode. Required only for `eventMode: "webhook"`. |
94
+ | `eventMode` | auto | `fetch` or `webhook`. Auto-selects from `callbackUrl` when omitted. |
95
+ | `botName` | `"OpenClaw"` | Bot display name. |
96
+ | `botCode` | auto | Optional explicit bot code. If omitted, the plugin registers the bot as `openclaw_<webhookUserId>`, and if that code is occupied it tries `openclaw_<webhookUserId>_2`, `_3`, and so on. |
97
+ | `botToken` | `md5(webhookUrl)` | Bot token for `imbot.v2` authentication (32-char hex string). If omitted, derived as `md5(webhookUrl)`. **Strongly recommended to set explicitly** if your `webhookUrl` may change (e.g. ngrok, dynamic DNS) — otherwise the plugin loses control of the previously registered bot. You can find the token in the Bitrix24 admin panel or compute it as `md5` of the original webhook URL. |
98
+ | `botAvatar` | | Optional base64 avatar override. |
99
+ | `dmPolicy` | `"webhookUser"` | Access policy: `webhookUser` or `pairing`. |
100
+ | `showTyping` | `true` | Sends typing indicator before response. |
101
+ | `enabled` | `true` | Enables or disables the account. |
102
+ | `agentMode` | `false` | Reserved for future user-event integration. Not working yet; planned for future versions. |
103
+ | `pollingIntervalMs` | `3000` | Base poll interval for `fetch` mode. |
104
+ | `pollingFastIntervalMs` | `100` | Fast follow-up poll interval when more events are pending. |
105
+
106
+ ### Agent-Driven Reactions
107
+
108
+ To enable agent-driven reactions, add `reactions` to the channel capabilities in your OpenClaw config:
91
109
 
92
110
  ```json
93
111
  {
94
112
  "channels": {
95
113
  "bitrix24": {
96
- ...
97
- "capabilities": ["inlineButtons"]
114
+ "webhookUrl": "...",
115
+ "capabilities": ["reactions"]
98
116
  }
99
117
  }
100
118
  }
101
119
  ```
102
120
 
103
- | Capability | Description |
104
- |---|---|
105
- | `inlineButtons` | Enables inline keyboard buttons in bot messages. The AI agent will be able to send interactive buttons using `action=send` with `buttons=[[{text, callback_data, style?}]]`. Without this capability the agent will not attempt to generate buttons. |
121
+ The plugin maps standard Unicode emoji (👍, 🔥, 👀, etc.) to Bitrix24 reaction codes automatically. B24 reaction codes (like `like`, `fire`, `eyes`) can also be used directly.
106
122
 
107
- ### Access Policies
123
+ ### Inline Buttons
108
124
 
109
- - **`"open"`** any Bitrix24 portal user can message the bot
110
- - **`"allowlist"`** — only users listed in `allowFrom`:
111
- ```json
112
- {
113
- "dmPolicy": "allowlist",
114
- "allowFrom": ["42", "b24:108", "bitrix24:256"]
115
- }
116
- ```
117
- Prefixes `b24:`, `bx24:`, `bitrix24:` are stripped automatically.
118
- - **`"pairing"`** — pairing mode (work in progress)
119
-
120
- ### Multi-Account (Multiple Portals)
121
-
122
- Connect multiple Bitrix24 portals to a single OpenClaw server:
125
+ To enable agent-driven inline buttons, add `inlineButtons` to the channel capabilities in your OpenClaw config:
123
126
 
124
127
  ```json
125
128
  {
126
129
  "channels": {
127
130
  "bitrix24": {
128
- "webhookUrl": "https://main-portal.bitrix24.com/rest/1/token1/",
129
- "botName": "Main Bot",
130
- "accounts": {
131
- "sales": {
132
- "webhookUrl": "https://sales.bitrix24.com/rest/1/token2/",
133
- "botName": "Sales Bot",
134
- "dmPolicy": "allowlist",
135
- "allowFrom": ["10", "20", "30"]
136
- },
137
- "support": {
138
- "webhookUrl": "https://support.bitrix24.com/rest/1/token3/",
139
- "botName": "Support Bot"
140
- }
141
- }
131
+ "webhookUrl": "...",
132
+ "capabilities": ["inlineButtons"]
142
133
  }
143
134
  }
144
135
  }
145
136
  ```
146
137
 
147
- The root config acts as the `"default"` account. Each entry in `accounts` inherits all root settings and can override any of them.
138
+ The plugin supports two button input forms:
148
139
 
149
- ## Network Access
140
+ - native Bitrix24 keyboard payload via `channelData.bitrix24.keyboard`
141
+ - generic OpenClaw button rows via `channelData.telegram.buttons`, which the plugin converts to Bitrix24 `KEYBOARD`
150
142
 
151
- The OpenClaw gateway must be reachable over HTTPS for POST requests from Bitrix24 servers.
143
+ For converted generic buttons:
152
144
 
153
- Default callback URL: `https://your-server.com/hooks/bitrix24`
145
+ - `callback_data` starting with `/` becomes a native Bitrix24 slash command button
146
+ - any other `callback_data` becomes `ACTION=PUT`
147
+ - `primary`, `attention`, and `danger` button styles are mapped to Bitrix24 color tokens
154
148
 
155
- For local development, use ngrok or a similar tool:
149
+ ## Access Policies
156
150
 
157
- ```bash
158
- ngrok http 3000
159
- ```
151
+ ### `webhookUser`
160
152
 
161
- Use the HTTPS URL from ngrok as the event handler URL in Bitrix24 bot settings.
153
+ Default and recommended mode for production.
162
154
 
163
- ## Running (restarting)
155
+ Only the Bitrix24 user whose ID is embedded in the webhook URL may talk to the bot. For a URL like:
164
156
 
165
- ```bash
166
- systemctl restart openclaw
157
+ ```text
158
+ https://your-portal.bitrix24.com/rest/42/secret/
167
159
  ```
168
160
 
169
- On successful start, logs will show: `Bitrix24 gateway started, webhook at /hooks/bitrix24`
161
+ only user `42` is allowed to use the bot in direct messages.
170
162
 
171
- ### Verification
163
+ ### `pairing`
172
164
 
173
- 1. Open a chat with the bot on your Bitrix24 portal
174
- 2. Send any message
175
- 3. The bot should show a typing indicator and respond
165
+ Pairing mode allows a user to request access and wait for approval through the OpenClaw pairing flow.
176
166
 
177
- ### Troubleshooting
167
+ Approval hint:
178
168
 
179
- - Webhook URL is correct and accessible (`webhookUrl`)
180
- - OpenClaw server is reachable from the internet over HTTPS
181
- - Scopes `imbot`, `im`, `disk` are enabled in the B24 webhook settings
182
- - No `QUERY_LIMIT_EXCEEDED` errors in logs (rate limit)
169
+ ```bash
170
+ openclaw pairing approve bitrix24 <CODE>
171
+ ```
183
172
 
184
- ## How It Works
173
+ ## Delivery Modes
185
174
 
186
- ```
187
- B24 user sends a message to the bot
188
- |
189
- B24 POSTs to /hooks/bitrix24 (application/x-www-form-urlencoded)
190
- |
191
- InboundHandler parses the request body
192
- |
193
- Event routing:
194
- ONIMBOTMESSAGEADD -> message processing
195
- ONIMBOTJOINCHAT -> welcome message
196
- ONIMCOMMANDADD -> slash command (WIP)
197
- ONIMBOTDELETE -> cleanup
198
- |
199
- Deduplication (MESSAGE_ID, 5 min TTL)
200
- |
201
- Access control (senderId vs. dmPolicy + allowFrom)
202
- |
203
- Normalize to MsgContext -> pass to OpenClaw AI agent
204
- |
205
- OpenClaw processes -> calls outbound.sendText()
206
- |
207
- SendService:
208
- imbot.chat.sendTyping -> typing indicator
209
- imbot.message.add -> response (Markdown -> BB-code)
210
- ```
175
+ ### `fetch`
176
+
177
+ - No public callback endpoint required
178
+ - Events are polled with `imbot.v2.Event.get`
179
+ - Best default for private or internal deployments
180
+
181
+ ### `webhook`
182
+
183
+ - Requires public HTTPS `callbackUrl`
184
+ - Bitrix24 sends events directly to OpenClaw
185
+ - The plugin accepts both JSON and form-encoded webhook bodies
211
186
 
212
- ### Handled Events
187
+ ## Supported Behavior
213
188
 
214
- | Event | Plugin Action |
215
- |---|---|
216
- | `ONIMBOTMESSAGEADD` | Incoming message -> normalize -> AI agent |
217
- | `ONIMBOTJOINCHAT` | Bot added to chat -> welcome message |
218
- | `ONIMCOMMANDADD` | Slash command (stub) |
219
- | `ONAPPINSTALL` | App installed (stub) |
220
- | `ONIMBOTDELETE` | Bot removed -> cleanup |
189
+ - Direct messages
190
+ - Typing indicators
191
+ - Text replies with BBCode conversion
192
+ - Inline keyboard buttons (`channelData.bitrix24.keyboard` and converted generic button rows)
193
+ - Reactions (agent can add/remove reactions on messages via `imbot.v2.Chat.Message.Reaction.*`)
194
+ - File upload to chat via `imbot.v2.File.upload`
195
+ - File download via `imbot.v2.File.download`
196
+ - Slash command registration via `imbot.v2.Command.*`
197
+ - Deduplication for repeated deliveries
198
+ - Rate limiting for Bitrix24 API calls
221
199
 
222
- ### Built-in Safeguards
200
+ ## Not Supported
223
201
 
224
- - **Rate limiter**: token-bucket, 2 requests/sec (B24 webhook limit)
225
- - **Deduplication**: B24 retries webhooks if it doesn't get a 200 in time — the plugin stores MESSAGE_IDs for 5 minutes
226
- - **Text conversion**: B24 uses BB-code, not Markdown — automatic conversion (`**bold**` -> `[B]bold[/B]`, etc.)
202
+ - Group chat conversations
203
+ - Production-ready multi-account operation in one process
227
204
 
228
- ## Customization
205
+ There is already account-config scaffolding in the plugin, but the current production recommendation is still one active Bitrix24 portal per instance.
229
206
 
230
- ### Bot Avatar
207
+ ## Verification
231
208
 
232
- The default bot avatar is stored in `src/bot-avatar.ts` as a base64-encoded JPEG string. To change the avatar:
209
+ 1. Start OpenClaw with the plugin enabled.
210
+ 2. Open a direct chat with the bot in Bitrix24.
211
+ 3. Send a message.
212
+ 4. Verify that the bot shows typing and returns a response.
213
+ 5. If `dmPolicy` is `webhookUser`, verify that only the webhook owner can talk to the bot.
233
214
 
234
- 1. Prepare a JPEG or PNG image (recommended: 200×200 px, ≤ 50 KB)
235
- 2. Convert it to base64
236
- 3. Replace the `DEFAULT_AVATAR_BASE64` value in `src/bot-avatar.ts`
237
- 4. Rebuild and redeploy
215
+ ## Troubleshooting
238
216
 
239
- The avatar can also be overridden per-account via the `botAvatar` config option (base64 string).
217
+ - Verify `webhookUrl` is valid and active.
218
+ - If you use `eventMode: "webhook"`, verify `callbackUrl` is reachable from the internet over HTTPS.
219
+ - Do not rely on `agentMode` yet. It is not working in the current release and is planned for future versions.
220
+ - Do not expect the bot to work in group chats.
221
+ - If file transfer fails, verify the file size and Bitrix24-side availability of the attachment.
240
222
 
241
223
  ## Development
242
224
 
243
225
  ```bash
244
226
  npm install
245
- npm test # run tests
246
- npm run build # compile TypeScript
227
+ npm test
228
+ npm run build
247
229
  ```
248
230
 
249
231
  ## License
package/index.ts CHANGED
@@ -8,10 +8,47 @@ interface OpenClawPluginApi {
8
8
  registerChannel: (opts: { plugin: typeof bitrix24Plugin }) => void;
9
9
  registerHttpRoute: (params: {
10
10
  path: string;
11
+ auth?: 'plugin';
11
12
  handler: (req: IncomingMessage, res: ServerResponse) => Promise<void>;
12
13
  }) => void;
13
14
  }
14
15
 
16
+ export function collectBitrix24CallbackPaths(config: Record<string, unknown>): string[] {
17
+ const channels = config?.channels as Record<string, Record<string, unknown>> | undefined;
18
+ const bitrix24 = channels?.bitrix24 as {
19
+ callbackUrl?: string;
20
+ accounts?: Record<string, { callbackUrl?: string }>;
21
+ } | undefined;
22
+
23
+ const callbackUrls: string[] = [];
24
+ if (typeof bitrix24?.callbackUrl === 'string') {
25
+ callbackUrls.push(bitrix24.callbackUrl);
26
+ }
27
+
28
+ for (const account of Object.values(bitrix24?.accounts ?? {})) {
29
+ if (typeof account?.callbackUrl === 'string') {
30
+ callbackUrls.push(account.callbackUrl);
31
+ }
32
+ }
33
+
34
+ const paths: string[] = [];
35
+ const seenPaths = new Set<string>();
36
+
37
+ for (const callbackUrl of callbackUrls) {
38
+ try {
39
+ const path = new URL(callbackUrl).pathname;
40
+ if (!seenPaths.has(path)) {
41
+ seenPaths.add(path);
42
+ paths.push(path);
43
+ }
44
+ } catch {
45
+ console.warn(`[bitrix24] Invalid callbackUrl "${callbackUrl}", skipping HTTP route`);
46
+ }
47
+ }
48
+
49
+ return paths;
50
+ }
51
+
15
52
  /**
16
53
  * OpenClaw Bitrix24 Channel Plugin
17
54
  *
@@ -28,16 +65,14 @@ export default {
28
65
 
29
66
  api.registerChannel({ plugin: bitrix24Plugin });
30
67
 
31
- // Register HTTP webhook route — derive path from callbackUrl
32
- const channels = api.config?.channels as Record<string, Record<string, unknown>> | undefined;
33
- const callbackUrl = channels?.bitrix24?.callbackUrl as string | undefined;
34
- const callbackPath = callbackUrl ? new URL(callbackUrl).pathname : '/hooks/bitrix24';
35
-
36
- api.registerHttpRoute({
37
- path: callbackPath,
38
- handler: async (req: IncomingMessage, res: ServerResponse) => {
39
- await handleWebhookRequest(req, res);
40
- },
41
- });
68
+ for (const callbackPath of collectBitrix24CallbackPaths(api.config)) {
69
+ api.registerHttpRoute({
70
+ path: callbackPath,
71
+ auth: 'plugin',
72
+ handler: async (req: IncomingMessage, res: ServerResponse) => {
73
+ await handleWebhookRequest(req, res);
74
+ },
75
+ });
76
+ }
42
77
  },
43
78
  };
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "id": "bitrix24",
3
3
  "channels": ["bitrix24"],
4
+ "skills": ["skills/bitrix24"],
4
5
  "configSchema": {
5
6
  "type": "object",
6
7
  "additionalProperties": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ihazz/bitrix24",
3
- "version": "0.2.5",
3
+ "version": "1.0.1",
4
4
  "description": "Bitrix24 Messenger channel for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: bitrix24
3
+ description: "Bitrix24 Messenger ops via the message tool (channel=bitrix24)."
4
+ metadata: { "openclaw": { "emoji": "💬", "requires": { "config": ["channels.bitrix24.webhookUrl"] } } }
5
+ allowed-tools: ["message"]
6
+ ---
7
+
8
+ # Bitrix24 (Via `message`)
9
+
10
+ Use the `message` tool. No provider-specific `bitrix24` tool exposed to the agent.
11
+
12
+ ## Musts
13
+
14
+ - Always: `channel: "bitrix24"`.
15
+ - The bot works in direct messages only (no group chats).
16
+
17
+ ## Common Actions (Examples)
18
+
19
+ Send message:
20
+
21
+ ```json
22
+ {
23
+ "action": "send",
24
+ "channel": "bitrix24",
25
+ "message": "Hello!"
26
+ }
27
+ ```
28
+
29
+ React to the current (last received) message:
30
+
31
+ ```json
32
+ {
33
+ "action": "react",
34
+ "channel": "bitrix24",
35
+ "emoji": "👍"
36
+ }
37
+ ```
38
+
39
+ - When `messageId` is **omitted**, the reaction is applied to the current inbound message automatically.
40
+ - `emoji` can be a standard Unicode emoji (👍, 🔥, ❤️, 😂, 😢, 😮, 👀, 🎉, 🤔, 👎, etc.) or a Bitrix24 reaction code (`like`, `fire`, `heart`, `laugh`, `cry`, `wonder`, `eyes`, `hooray`, `think`, `dislike`).
41
+ - To react to a **specific** message, pass `"messageId": "<numeric id>"`.
42
+ - To remove a reaction, add `"remove": true`.
43
+
44
+ Remove a reaction:
45
+
46
+ ```json
47
+ {
48
+ "action": "react",
49
+ "channel": "bitrix24",
50
+ "emoji": "👍",
51
+ "remove": true
52
+ }
53
+ ```
54
+
55
+ ## Reactions Guidance
56
+
57
+ When you see a message from a Bitrix24 user, you can react to acknowledge it before (or instead of) sending a text reply. Common patterns:
58
+
59
+ - React with 👍 to acknowledge a request.
60
+ - React with 👀 to indicate you're looking into something.
61
+ - React with ✅ or 🎉 when a task is completed.
62
+ - React with 🤔 if you need to think about the request.
63
+
64
+ **Important:** Do NOT invent or guess messageId values. Either omit `messageId` to react to the current message, or use a messageId that was explicitly provided to you.
65
+
66
+ ## Inline Keyboard Buttons
67
+
68
+ You can attach inline buttons to a message. The `callback_data` value is sent back when the user taps the button.
69
+
70
+ ```json
71
+ {
72
+ "action": "send",
73
+ "channel": "bitrix24",
74
+ "message": "Выберите вариант:",
75
+ "buttons": [
76
+ [
77
+ { "text": "Да", "callback_data": "Да" },
78
+ { "text": "Нет", "callback_data": "Нет" }
79
+ ]
80
+ ]
81
+ }
82
+ ```
83
+
84
+ **Important rules for buttons:**
85
+
86
+ - `callback_data` **must match** the button `text` exactly — when the user taps a button, `callback_data` is sent as a message in the chat. If they differ, the user sees confusing text.
87
+ - Write button labels in the **same language as the conversation** (e.g. Russian if the user writes in Russian).
88
+ - Use `"style": "primary"` for the recommended option, `"style": "danger"` for destructive actions.
89
+ - Each inner array is one row of buttons.
90
+
91
+ ## Writing Style (Bitrix24)
92
+
93
+ - Direct, professional, moderate length.
94
+ - **Always reply in the same language the user writes in.** If the user writes in Russian, reply in Russian. If in English, reply in English.
95
+ - Bitrix24 uses BBCode for formatting (conversion is automatic).
96
+ - Inline keyboard buttons are supported for interactive responses.