Добавить виджет на Вайб landing.repowidget.register

Выберите инструмент для разработки с AI-агентом:

  • используйте Битрикс24 Вайбкод, чтобы создать приложение для Битрикс24 по описанию задачи без знания языков программирования. Агент напишет код и разместит приложение на сервере без ручной настройки хостинга
  • используйте MCP-сервер, чтобы разрабатывать интеграцию через REST API в своем проекте. Агент будет обращаться к официальной REST-документации

Scope: landing

Кто может выполнять метод: любой пользователь

Метод landing.repowidget.register добавляет виджет для Вайба. Возвращает ошибку или идентификатор ID добавленного виджета.

При добавлении выполняется проверка. Если виджет с кодом code уже зарегистрирован ранее, то происходит обновление его контента. Виджеты, уже размещенные на Вайбах, в случае обновления контента обновляются автоматически.

Параметры метода

Обязательные параметры отмечены *

Название
тип

Описание

code*
string

Уникальный код виджета. Настоятельно рекомендуется использовать какой-либо уникальный префикс для своих виджетов, чтобы избежать риск совпадения кодов с виджетами других разработчиков

fields*
object

Значения полей для создания виджета

Параметр fields

Обязательные параметры отмечены *

Название
тип

Описание

NAME*
string

Название виджета

PREVIEW*
string

URL картинки-обложки виджета для слайдера выбора виджетов

DESCRIPTION
string

Описание виджета

CONTENT*
string

Верстка виджета с использованием конструкций Vue

SECTIONS*
string

Код раздела, в который будет добавлен виджет. Список доступных разделов:

  • widgets_company_life — Жизнь компании
  • widgets_new_employees — Новым сотрудникам
  • widgets_team — Команда
  • widgets_automation — Автоматизация
  • widgets_events — Встречи и события
  • widgets_profile — Профиль сотрудника
  • widgets_tasks — Задачи и проекты
  • widgets_sales — Продажи и клиенты
  • widgets_hr — HR
  • widgets_other — Другое
  • widgets_separators — Переходы и разделители
  • widgets_text — Текст
  • widgets_image — Картинки
  • widgets_video — Видео

WIDGET_PARAMS*
object

Параметры для vue-шаблонизатора. Без них метод вернет ошибку REQUIRED_FIELD_NO_EXISTS

ACTIVE
char

Активность виджета. Принимает значения:

  • Y - виджет активен и доступен
  • N - виджет неактивен и недоступен

SITE_TEMPLATE_ID
string

Привязка виджета к определенному шаблону сайта. Только для коробочного Битрикс24!

Параметр WIDGET_PARAMS

Обязательные параметры отмечены *

Название
тип

Описание

rootNode*
string

Селектор корневого элемента в верстке, который будет превращен во vue-component. Корневой элемент должен быть единственным элементом в передаваемом шаблоне, вся остальная разметка будет очищена

lang
string

Массив языковых фраз, использующихся в конструкциях {{$Bitrix.Loc.getMessage('W_EMPTY')}}

handler*
string

Адрес внешнего обработчика, к которому будут выполняться запросы.

Важно: Обработчик должен быть доступен из внешней сети! Проверяйте доступность обработчика специальными сервисами

style
string

Адрес стилей для виджета. Стили также могут быть заданы инлайново в разметке через привязку :style="{borderBottom: '1px solid red'}"

demoData*
object

Демо-данные для виджета, которые будут использованы для демонстрации виджета в шаблонах Вайба в Битрикс24 Маркетплейс.

Если вы разрабатываете виджет для конкретного Битрикс24 и не планируете публиковать его в Маркет, то можете указать в качестве значения параметра произвольный массив, он все равно не будет использован.

Однако, если вы готовите тиражное решение с виджетом, уделите демонстрационным данным максимальное внимание — именно они будут отображаться в слайдере предварительного просмотра шаблона Вайба! Очевидно, что структура демо-данных должна соответствовать той, которую вернул бы ваш обработчик handler в обычном режиме использования виджета

Примеры кода

Как использовать примеры в документации

// This snippet is an ES module: top-level await requires type="module" or a bundler.
// $b24 is an already-initialized SDK instance (see the SDK "Get started" guide).
import { Text } from '@bitrix24/b24jssdk'
import type { B24Frame } from '@bitrix24/b24jssdk'

declare const $b24: B24Frame

const content = '<div class="my-app-w-container"><!-- Vue template --></div>'

try {
  const response = await $b24.actions.v2.call.make<number>({
    method: 'landing.repowidget.register',
    params: {
      code: 'my_widget',
      fields: {
        NAME: 'My widget',
        PREVIEW: 'https://my-app.com/vibe_preview.jpg',
        CONTENT: content,
        SECTIONS: 'widgets_company_life',
        WIDGET_PARAMS: {
          rootNode: '.my-app-w-container',
          lang: {
            ru: {
              W_TITLE: 'People and their ages',
              W_EMPTY: 'No data',
            },
            en: {
              W_TITLE: 'People and their ages',
              W_EMPTY: 'Empty',
            },
          },
          handler: 'https://my-app.com/vibe.php',
          style: 'https://my-app.com/vibe.css',
          demoData: {
            desc: 'Just a test widget',
            count: 420,
            persons: [
              { name: 'Person 1', age: 21 },
              { name: 'Person 2', age: 42 },
              { name: 'Person 3', age: 123 },
            ],
          },
        },
      },
    },
    requestId: Text.getUuidRfc4122()
  })

  // The payload is available only on a successful response
  if (!response.isSuccess) {
    console.error(response.getErrorMessages().join('; '))
  } else {
    const result = response.getData()!.result
    console.info('Registered widget ID:', result)
  }
} catch (error) {
  // Thrown on transport or SDK failures (AjaxError, SdkError, etc.)
  console.error(error)
}
<!-- Load the SDK (UMD build); it is exposed as the global B24Js -->
<script src="https://unpkg.com/@bitrix24/b24jssdk@1/dist/umd/index.min.js"></script>
<script>
  async function registerVibeWidget() {
    try {
      // Initialize the SDK inside a Bitrix24 frame
      const $b24 = await B24Js.initializeB24Frame()

      const content = '<div class="my-app-w-container"><!-- Vue template --></div>'

      const response = await $b24.actions.v2.call.make({
        method: 'landing.repowidget.register',
        params: {
          code: 'my_widget',
          fields: {
            NAME: 'My widget',
            PREVIEW: 'https://my-app.com/vibe_preview.jpg',
            CONTENT: content,
            SECTIONS: 'widgets_company_life',
            WIDGET_PARAMS: {
              rootNode: '.my-app-w-container',
              lang: {
                ru: {
                  W_TITLE: 'People and their ages',
                  W_EMPTY: 'No data',
                },
                en: {
                  W_TITLE: 'People and their ages',
                  W_EMPTY: 'Empty',
                },
              },
              handler: 'https://my-app.com/vibe.php',
              style: 'https://my-app.com/vibe.css',
              demoData: {
                desc: 'Just a test widget',
                count: 420,
                persons: [
                  { name: 'Person 1', age: 21 },
                  { name: 'Person 2', age: 42 },
                  { name: 'Person 3', age: 123 },
                ],
              },
            },
          },
        },
        requestId: B24Js.Text.getUuidRfc4122()
      })

      // The payload is available only on a successful response
      if (!response.isSuccess) {
        console.error(response.getErrorMessages().join('; '))
        return
      }

      const result = response.getData().result
      console.info('Registered widget ID:', result)
    } catch (error) {
      // Thrown on transport or SDK failures (AjaxError, SdkError, etc.)
      console.error(error)
    }
  }

  document.addEventListener('DOMContentLoaded', registerVibeWidget)
</script>
from b24pysdk.errors import BitrixAPIError, BitrixSDKException

content = '<div class="my-app-w-container"><!-- Vue template --></div>'

try:
    bitrix_response = client.landing.repowidget.register(
        code="my_widget",
        fields={
            "NAME": "My widget",
            "PREVIEW": "https://my-app.com/vibe_preview.jpg",
            "CONTENT": content,
            "SECTIONS": "widgets_company_life",
            "WIDGET_PARAMS": {
                "rootNode": ".my-app-w-container",
                "lang": {
                    "ru": {
                        "W_TITLE": "People and their ages",
                        "W_EMPTY": "No data",
                    },
                    "en": {
                        "W_TITLE": "People and their ages",
                        "W_EMPTY": "Empty",
                    },
                },
                "handler": "https://my-app.com/vibe.php",
                "style": "https://my-app.com/vibe.css",
                "demoData": {
                    "desc": "Some people...",
                    "persons": [
                        {
                            "name": "Person 1",
                            "age": 21,
                        },
                        {
                            "name": "Person 2",
                            "age": 42,
                        },
                        {
                            "name": "Person 3",
                            "age": 123,
                        },
                    ],
                },
            },
        },
    ).response
    result = bitrix_response.result
    print(result)
except BitrixAPIError as error:
    print(
        "Ошибка Bitrix API",
        f"error: {error.error}",
        f"error_description: {error.error_description}",
        sep="\n",
    )
except BitrixSDKException as error:
    print(f"Ошибка Bitrix SDK: {error.message}")
except Exception as error:
    print(f"Непредвиденная ошибка: {error}")
try {
    $response = $b24Service
        ->core
        ->call(
            'landing.repowidget.register',
            [
                'code'    => 'my_widget',
                'fields'  => [
                    'NAME'         => 'My widget',
                    'PREVIEW'      => 'https://my-app.com/vibe_preview.jpg',
                    'CONTENT'      => $content,
                    'SECTIONS'     => 'widgets_company_life',
                    'WIDGET_PARAMS' => [
                        'rootNode' => '.my-app-w-container',
                        'lang'     => [
                            'ru' => [
                                'W_TITLE' => 'Люди и их возраст',
                                'W_EMPTY' => 'Нет людей',
                            ],
                            'en' => [
                                'W_TITLE' => 'People and their ages',
                                'W_EMPTY' => 'Empty',
                            ],
                        ],
                        'handler'   => 'https://my-app.com/vibe.php',
                        'style'     => 'https://my-app.com/vibe.css',
                        'demoData'  => [
                            'desc'    => 'Just a test widget',
                            'count'   => 420,
                            'persons' => [
                                ['name' => 'Person 1', 'age' => 21],
                                ['name' => 'Person 2', 'age' => 42],
                                ['name' => 'Person 3', 'age' => 123],
                            ],
                        ],
                    ],
                ],
            ]
        );

    $result = $response
        ->getResponseData()
        ->getResult();

    echo 'Success: ' . print_r($result, true);
    // Нужная вам логика обработки данных
    processData($result);

} catch (Throwable $e) {
    error_log($e->getMessage());
    echo 'Error registering repowidget: ' . $e->getMessage();
}
const content = `
    <div class="my-app-w-container">
        <h2 class="w-title" :style="{borderBottom: '1px solid red'}">
            {{$Bitrix.Loc.getMessage('W_TITLE')}}
        </h2>
        
        <h3>Description: {{desc}}</h3>
        
        <div v-for="(value) in persons">
            <p>
                <span class="w-name">{{value.name}}</span>:
                <span class="w-age">{{value.age}}</span>
            </p>
        </div>
        
        <div v-if="persons == null">
            {{$Bitrix.Loc.getMessage('W_EMPTY')}}
        </div>
        
        <h4>Just a number {{count}}</h4>
        
        <div class="w-buttons">
            <button @click="fetch">Получить данные (без параметров)</button>
            <button @click="fetch({param: 'a'})">Данные для параметра 'a'</button>
            <button @click="fetch({param: 'b'})">Данные для параметра 'b'</button>
            <button @click="openApplication({param1: '1', param2: 'false'})">Открыть приложение</button>
            <button @click="openPath('/crm')">Открыть локальный адрес в слайдере</button>
        </div>
    </div>
`;

const data = {
    code: 'my_widget',
    fields: {
        NAME: 'My widget',
        PREVIEW: 'https://my-app.com/vibe_preview.jpg',
        CONTENT: content,
        SECTIONS: 'widgets_company_life',
        WIDGET_PARAMS: {
            rootNode: '.my-app-w-container',
            lang: {
                ru: {
                    W_TITLE: 'Люди и их возраст',
                    W_EMPTY: 'Нет людей',
                },
                en: {
                    W_TITLE: 'People and their ages',
                    W_EMPTY: 'Empty',
                },
            },
            handler: 'https://my-app.com/vibe.php',
            style: 'https://my-app.com/vibe.css',
            demoData: {
                desc: 'Just a test widget',
                count: 420,
                persons: [
                    {'name': 'Person 1', 'age': 21},
                    {'name': 'Person 2', 'age': 42},
                    {'name': 'Person 3', 'age': 123},
                ],
            },
        },
    },
};

BX24.callMethod(
    'landing.repowidget.register',
    data,
    (result) =>
    {
        if (result.error())
        {
            console.error(result.error());

            return;
        }

        console.info(result.data());
    },
);
require_once('crest.php');

$content = <<<'HTML'
    <div class="my-app-w-container">
        <h2 class="w-title" :style="{borderBottom: '1px solid red'}">
            {{$Bitrix.Loc.getMessage('W_TITLE')}}
        </h2>
        
        <h3>Description: {{desc}}</h3>
        
        <div v-for="(value) in persons">
            <p>
                <span class="w-name">{{value.name}}</span>: 
                <span class="w-age">{{value.age}}</span>
            </p>
        </div>
        
        <div v-if="persons == null">
            {{$Bitrix.Loc.getMessage('W_EMPTY')}}
        </div>
        
        <h4>Just a number {{count}}</h4>
        
        <div class="w-buttons">
            <button @click="fetch">Получить данные (без параметров)</button>
            <button @click="fetch({param: 'a'})">Данные для параметра 'a'</button>
            <button @click="fetch({param: 'b'})">Данные для параметра 'b'</button>
            <button @click="openApplication({param1: '1', param2: 'false'})">Открыть приложение</button>
            <button @click="openPath('/crm')">Открыть локальный адрес в слайдере</button>
        </div>
    </div>
HTML;

$data = [
    'code' => 'my_widget',
    'fields' => [
        'NAME' => 'My widget', 
        'PREVIEW' => 'https://my-app.com/vibe_preview.jpg', 
        'CONTENT' => $content,  // Vue-разметка вынесена в отдельную переменную для удобства
        'SECTIONS' => 'widgets_company_life', 
        'WIDGET_PARAMS' => [
            'rootNode' => '.my-app-w-container',
            'lang' => [
                'ru' => [
                    'W_TITLE' => 'Люди и их возраст',
                    'W_EMPTY' => 'Нет людей',
                ],
                'en' => [
                    'W_TITLE' => 'People and their ages',
                    'W_EMPTY' => 'Empty!',
                ],
            ],
            'handler' => 'https://my-app.com/vibe.php',
            'style' => 'https://my-app.com/vibe.css',
            'demoData' => [
                'desc' => 'Just a test widget',
                'count' => 420,
                'persons' => [
                    [
                        'name' => 'Person 1',
                        'age' => 21,
                    ],
                    [
                        'name' => 'Person 2',
                        'age' => 42,
                    ],
                    [
                        'name' => 'Person 3',
                        'age' => 123,
                    ],
                ],
            ],
        ],
    ],
];

$result = CRest::call(
    'landing.repowidget.register',
    $data
);

echo '<PRE>';
print_r($result);
echo '</PRE>';

Обработка ответа

HTTP-статус: 200

{
    "result": 10,
    "time": {
        "start": 1713949410.036288,
        "finish": 1713949411.632775,
        "duration": 1.596487045288086,
        "processing": 0.6458539962768555,
        "date_start": "2024-04-24T11:03:30+02:00",
        "date_finish": "2024-04-24T11:03:31+02:00",
        "operating": 0
    }
}

Возвращаемые данные

Название
тип

Описание

result
integer

Идентификатор добавленного виджета

time
time

Информация о времени выполнения запроса

Обработка ошибок

HTTP-статус: 400

{
    "error":"REQUIRED_FIELD_NO_EXISTS",
    "error_description":"Отсутствует обязательное поле CONTENT"
}

Название
тип

Описание

error
string

Строковый код ошибки. Состоит из цифр, латинских букв и знака подчеркивания. Может прийти пустым — тогда причину показывает только error_description

error_description
string

Текст ошибки для разработчика. Не показывайте его конечному пользователю без обработки

Возможные коды ошибок

Код

Описание

REQUIRED_FIELD_NO_EXISTS

В параметре fields не передано обязательное поле: NAME, PREVIEW, CONTENT, SECTIONS или WIDGET_PARAMS. Имя поля подставляется в текст ошибки

REQUIRED_PARAM_NO_EXISTS

В параметре WIDGET_PARAMS не передан обязательный параметр: rootNode, handler или demoData. Имя параметра подставляется в текст ошибки

Статусы и коды системных ошибок

HTTP-статус: 4xx, 5xx

Описанные ниже ошибки возвращает сам REST API, а не логика конкретного метода. Они могут прийти в ответ на любой метод.

Статус

Код
Текст ошибки

Описание

500

INTERNAL_SERVER_ERROR
Internal server error

Возникла внутренняя ошибка сервера. Повторите вызов, а если ошибка сохраняется, обратитесь к администратору сервера или в техническую поддержку Битрикс24

500

ERROR_UNEXPECTED_ANSWER
Server returned an unexpected response

Сервер вернул неожиданный ответ. Повторите вызов, а если ошибка сохраняется, обратитесь к администратору сервера или в техническую поддержку Битрикс24

503

QUERY_LIMIT_EXCEEDED
Too many requests

Превышен лимит на интенсивность запросов

429

OPERATION_TIME_LIMIT
Method is blocked due to operation time limit

Метод заблокирован из-за превышения лимита на ресурсоемкость запросов. Блокировка снимается автоматически, когда накопленное время выполнения метода перестает превышать лимит

401

NO_AUTH_FOUND
Wrong authorization data

В запросе нет авторизационных данных: не передан ни access-токен, ни код вебхука

401

INVALID_REQUEST
Https required

Методы вызываются только по протоколу HTTPS

401

OVERLOAD_LIMIT
REST API is blocked due to overload

REST API заблокирован из-за перегрузки. Это ручная индивидуальная блокировка. Чтобы ее снять, обратитесь в техническую поддержку Битрикс24

401

ACCESS_DENIED
REST is available only on commercial plans

REST API доступен только на коммерческих тарифах. У вебхука текст ошибки другой — REST is available only by subscription

401

INVALID_CREDENTIALS
Invalid request credentials

Не найден активный вебхук с указанным идентификатором пользователя и секретным кодом

404

ERROR_METHOD_NOT_FOUND
Method not found!

Метод с таким именем не найден. Имя написано с ошибкой, метода нет в REST API или он недоступен без нужного скоупа

401

insufficient_scope
The request requires higher privileges than provided by the webhook token

Запрос требует более широких прав, чем есть у токена: у вебхука это выданные ему права, у приложения — скоуп. У приложения текст ошибки заканчивается на provided by the access token

401

expired_token
The access token provided has expired

Срок действия access-токена истек

401

user_access_error
The user does not have access to the application

Приложение установлено, но администратор Битрикс24 открыл доступ к нему только конкретным пользователям

403

PORTAL_DELETED
Portal was deleted

Публичная часть сайта закрыта. Чтобы открыть ее на коробочной установке, отключите опцию «Временное закрытие публичной части сайта». Путь к настройке: Рабочий стол > Настройки > Настройки продукта > Настройки модулей > Главный модуль > Временное закрытие публичной части сайта

Продолжите изучение

Предыдущая
Следующая