Глава 17 GET POST

Webhooks – События в реальном времени

Webhooks BigBlueButton позволяют вашему приложению получать HTTP POST-уведомления в реальном времени при возникновении событий встречи. Вместо постоянного опроса getMeetings или getMeetingInfo вы регистрируете callback URL, и BigBlueButton автоматически отправляет вам события. В этой главе рассматриваются три эндпоинта API webhook, формат callback, типы событий, поведение повторных попыток и конфигурация сервера.

Для webhooks требуется, чтобы пакет bbb-webhooks был установлен на сервере. Некоторые детали, описанные в этой главе, не охвачены официальной документацией BigBlueButton и были определены путём анализа исходного кода. undocumented

Предварительные условия

Пакет bbb-webhooks должен быть установлен на сервере BigBlueButton, прежде чем эндпоинты webhook станут доступны:

sudo apt-get install bbb-webhooks

Если приложение webhook не запущено в момент создания встречи, внутреннее сопоставление встречи не создаётся. В результате для этой встречи callback-запросы не будут вызываться.

hooks/create — зарегистрировать webhook

GET https://api-guide.bbbserver.com/bigbluebutton/api/hooks/create?<parameters>&checksum=replace-with-checksum

Официальная документация не указывает HTTP-метод. Роутер Express регистрирует только маршруты GET — запросы POST не принимаются. undocumented

Параметр Тип Обязательно По умолчанию Описание
callbackURL String Да URL, который будет получать callback POST. Обнаружение дубликатов основано исключительно на этом URL — один и тот же URL нельзя зарегистрировать дважды, даже с другим meetingID или eventID.
meetingID String Нет Ограничивает webhook конкретной встречей (внешний идентификатор встречи). Если параметр опущен, webhook становится глобальным и срабатывает для всех встреч.
eventID String Нет Список типов событий, разделённых запятыми, для отслеживания (например, user-joined,meeting-ended). Если параметр опущен, доставляются все события. Фильтр нечувствителен к регистру. Доступно начиная с BBB 2.5.
getRaw Boolean Нет false Если установлено значение true, callback содержат необработанное сообщение Redis вместо обработанных данных события.

Успешный ответ

<response>
  <returncode>SUCCESS</returncode>
    <hookID>replace-with-hook-id</hookID>
  <permanentHook>false</permanentHook>
  <rawData>false</rawData>
</response>

Дублирующая регистрация

Если тот же callbackURL регистрируется снова, ответ всё равно возвращает SUCCESS, но включает duplicateWarning. Существующий webhook остаётся без изменений — meetingID, eventID и getRaw не обновляются.

<response>
  <returncode>SUCCESS</returncode>
    <hookID>replace-with-hook-id</hookID>
  <messageKey>duplicateWarning</messageKey>
  <message>There is already a hook for this callback URL.</message>
</response>

Ответы с ошибками

messageKey Описание
checksumError Контрольная сумма недействительна или отсутствует.
missingParamCallbackURL Параметр callbackURL не был передан. undocumented
createHookError Произошла внутренняя ошибка (например, Redis недоступен). Проверьте журналы сервера.

hooks/list — список зарегистрированных webhook

GET https://api-guide.bbbserver.com/bigbluebutton/api/hooks/list?<parameters>&checksum=replace-with-checksum
Параметр Тип Обязательно Описание
meetingID String Нет Фильтрует по ID встречи. Результат включает как хуки для указанной встречи, так и все глобальные хуки. Если параметр опущен, возвращаются все зарегистрированные хуки.

Успешный ответ

<response>
  <returncode>SUCCESS</returncode>
  <hooks>
    <hook>
    <hookID>replace-with-hook-id</hookID>
            <callbackURL><![CDATA[https://api-guide.bbbserver.com/callbacks/webhook]]></callbackURL>
    <meetingID><![CDATA[replace-with-meeting-id]]></meetingID>
      <eventID>user-joined,meeting-ended</eventID>
      <permanentHook>false</permanentHook>
      <rawData>false</rawData>
    </hook>
  </hooks>
</response>

Элемент <meetingID> появляется только для хуков, привязанных к встрече. У глобальных хуков элемент <meetingID> отсутствует. Аналогично, <eventID> появляется только тогда, когда при создании был задан фильтр событий.

Ответы с ошибками

messageKey Описание
checksumError Контрольная сумма недействительна или отсутствует.
listHookError При получении списка хуков произошла внутренняя ошибка. Проверьте журналы сервера. undocumented

hooks/destroy — удалить webhook

GET https://api-guide.bbbserver.com/bigbluebutton/api/hooks/destroy?<parameters>&checksum=replace-with-checksum
Параметр Тип Обязательно Описание
hookID String Да ID хука, который нужно удалить (полученный из hooks/create или hooks/list).

Успешный ответ

<response>
  <returncode>SUCCESS</returncode>
  <removed>true</removed>
</response>

Постоянные хуки (настроенные на стороне сервера через permanentURLs) нельзя удалить через API. Попытка сделать это возвращает ошибку destroyMissingHook, как если бы хук не существовал.

Ответы с ошибками

messageKey Описание
checksumError Контрольная сумма недействительна или отсутствует.
missingParamHookID Параметр hookID не был передан.
destroyMissingHook ID хука не существует или принадлежит постоянному хуку.
destroyHookError При удалении хука произошла внутренняя ошибка. Проверьте журналы сервера.

hooks/ping — проверка работоспособности

GET https://api-guide.bbbserver.com/bigbluebutton/api/hooks/ping

Этот диагностический эндпоинт не требует контрольной суммы. Если приложение вебхука доступно, он возвращает строку простого текста bbb-webhooks API up! (не XML, тип содержимого text/plain). undocumented

Формат обратного вызова

Обратные вызовы вебхука отправляются как запросы HTTP POST с типом содержимого application/x-www-form-urlencoded. Тело запроса содержит три поля:

Поле Описание
domain Домен сервера (из конфигурации вебхука). undocumented
event Массив JSON, содержащий данные события. Всегда массив, даже для одного события.
timestamp Метка времени Unix в миллисекундах на момент отправки.

Тело обработанного callback (getRaw=false)

domain=myserver.com&event=[{"data":{"type":"event","id":"user-joined","attributes":{...},"event":{"ts":1532718316938}}}]&timestamp=1532718316953

Тело необработанного callback (getRaw=true)

domain=myserver.com&event=[{"envelope":{"name":"UserJoinedMeetingEvtMsg","routing":{"sender":"bbb-apps-akka"}},"core":{"header":{...},"body":{...}}}]&timestamp=1532718316953

Когда сервер настроен со значением multiEvent больше 1, несколько событий могут быть объединены в массиве event в рамках одного обратного вызова.

Проверка контрольной суммы обратного вызова

В режиме по умолчанию каждый callback URL получает параметр строки запроса checksum, который ваше приложение должно проверить:

https://api-guide.bbbserver.com/callbacks/webhook?checksum=replace-with-checksum

Формула проверки:

sha<algo>(<callback-URL-without-checksum> + <URL-encoded-body> + <shared-secret>)

Возьмите зарегистрированный URL обратного вызова без параметра checksum.

Добавьте полное URL-кодированное тело запроса (domain=...&event=[...]&timestamp=...).

Добавьте общий секрет BBB.

Вычислите хеш получившейся строки с использованием настроенного алгоритма (по умолчанию: sha1, настраивается через hookChecksumAlgorithm).

Режим Auth 2.0 / Bearer

В качестве альтернативы сервер можно настроить с помощью auth2_0: true. В этом режиме параметр checksum не добавляется к callback URL. Вместо этого общий секрет передаётся как токен Bearer в заголовке Authorization: undocumented

Authorization: Bearer <shared-secret>

Поведение обратного вызова

  • Допустимые HTTP-коды статуса: HTTP 2xx и HTTP 401 считаются успешной доставкой. Все остальные коды статуса вызывают повторную попытку. undocumented
  • Перенаправления: Ответы HTTP 3xx обрабатываются с переходом по перенаправлению (до 10 переходов). Только если после 10 перенаправлений не будет достигнут 2xx/401, callback считается неудачным.
  • Тайм-аут: Для каждого запроса обратного вызова установлен тайм-аут 5 секунд (настраивается через requestTimeout).
  • Интервалы повторных попыток: При ошибке повторные попытки используют экспоненциальную задержку: 100ms, 500ms, 1s, 2s, 4s, 8s, 10s, 30s, 60s, 60s, 60s, 60s (12 попыток примерно за 5 минут, настраивается через retryIntervals).
  • После исчерпания всех повторных попыток: Непостоянные хуки удаляются автоматически. Постоянные хуки продолжают повторные попытки бесконечно с интервалом 60 секунд (настраивается через permanentIntervalReset).

Типы событий

События встречи

ID события Описание
meeting-created Встреча была создана.
meeting-ended Встреча завершилась. Это также вызывает синтетические события user-left для всех подключённых пользователей.
meeting-recording-started Запись началась.
meeting-recording-stopped Запись остановлена.
meeting-recording-unhandled Необработанное событие записи (резервный вариант, когда статус записи не равен ни true, ни false).
meeting-screenshare-started Начат показ экрана (включает данные пользователя-презентатора).
meeting-screenshare-stopped Показ экрана остановлен (включает данные пользователя-владельца).
meeting-presentation-changed Активная презентация изменилась (включает presentation-id).

События пользователя

ID события Описание
user-joined Пользователь присоединился к встрече (включает флаг гостя, пользовательские данные, IP-адрес, User-Agent).
user-left Пользователь покинул встречу (включает флаг гостя). Также синтетически генерируется при meeting-ended.
user-audio-voice-enabled Аудио включено (включает флаги listening-only, sharing-mic, muted).
user-audio-voice-disabled Аудио отключено.
user-audio-muted Пользователь был заглушён.
user-audio-unmuted Пользователь был разглушён.
user-audio-unhandled Необработанное аудиособытие (резервный вариант).
user-cam-broadcast-start Веб-камера запущена (включает stream-id).
user-cam-broadcast-end Веб-камера выключена.
user-presenter-assigned Пользователю была назначена роль ведущего.
user-presenter-unassigned Пользователь был лишён роли ведущего.
user-emoji-changed Эмодзи или реакция пользователя изменены (включает значение эмодзи).
user-raise-hand-changed Пользователь поднял или опустил руку (включает логическое значение raise-hand). В версиях BBB до 2.7 это генерируется синтетически из user-emoji-changed.

События чата и заметок

ID события Описание
chat-group-message-sent Сообщение было отправлено в публичный чат. Сообщения в приватном чате не создают событий webhook.
transcript-updated Транскрипция обновлена (включает transcript, locale, флаг final).
pad-content Содержимое общих заметок изменилось (включает pad-id, rev, text).

События опросов

ID события Описание
poll-started Опрос был запущен (включает вопрос и варианты ответов).
poll-responded Участник ответил на опрос (включает ID ответов).

События записи и воспроизведения (RAP)

ID события Описание
rap-archive-started Архивирование началось.
rap-archive-ended Архивирование завершено (включает флаг recorded и длительность).
rap-sanity-started Проверка целостности началась.
rap-sanity-ended Проверка целостности завершена.
rap-post-archive-started Пост-архивирование началось.
rap-post-archive-ended Пост-архивирование завершено.
rap-process-started Обработка началась.
rap-process-ended Обработка завершена.
rap-post-process-started Пост-обработка началась.
rap-post-process-ended Пост-обработка завершена.
rap-publish-started Публикация началась.
rap-publish-ended Публикация завершена (включает полный объект записи с метаданными, информацией о воспроизведении и скачивании).
rap-post-publish-started Пост-публикация началась.
rap-post-publish-ended Пост-публикация завершена.
rap-published Запись опубликована.
rap-unpublished Публикация записи отменена.
rap-deleted Запись удалена.

Большинство событий RAP включают record-id, success (булево значение) и step-time. События с полем workflow дополнительно содержат имя рабочего процесса обработки.

Конфигурация сервера

Следующие параметры можно настроить в /etc/bigbluebutton/bbb-webhooks.yml или config/default.yml. Большинство из этих параметров не описано в официальной документации. undocumented

Вариант По умолчанию Описание
hookChecksumAlgorithm sha1 Алгоритм хеширования для checksum callback (sha1, sha256, sha384, sha512).
api.supportedChecksumAlgorithms [sha1, sha256, sha384, sha512] Допустимые алгоритмы для контрольных сумм входящих API-запросов.
api.port 3005 Порт сервера webhook API.
api.bind 127.0.0.1 Адрес привязки сервера API.
includeEvents [] Глобальный фильтр событий сервера: только эти события доставляются всем хукам. Пустое значение означает все события.
excludeEvents [] Глобальный фильтр событий сервера: эти события подавляются для всех хуков. Пустое значение означает отсутствие исключений.
permanentURLs [] Список постоянных URL-хуков, которые регистрируются при запуске и не могут быть удалены через API.
retryIntervals [100,500,1000,...,60000] Интервалы повторных попыток в миллисекундах для неудачных callback-запросов.
permanentIntervalReset 60000 Интервал повторной попытки в миллисекундах для постоянных хуков после исчерпания всех обычных повторных попыток.
requestTimeout 5000 HTTP-таймаут в миллисекундах для callback-запросов.
multiEvent 1 Если установлено значение больше 1, несколько событий объединяются в массив событий в рамках одного callback-запроса.
queueSize 10000 Максимальный размер внутренней очереди событий.
bbb.auth2_0 false Включает аутентификацию по токену Bearer вместо checksum в URL для callback.

includeEvents и excludeEvents — это фильтры на уровне всего сервера, которые применяются дополнительно к фильтру eventID для каждого хука. Событие должно пройти оба фильтра, чтобы быть доставленным.

Примечания по эксплуатации

  • Постоянство: Хуки хранятся в Redis и сохраняются после перезапуска сервера (повторно синхронизируются при запуске).
  • Порядок: Обратные вызовы отправляются последовательно для каждого хука, по одному за раз, с сохранением порядка событий.
  • Уникальность URL: Обнаружение дубликатов основано исключительно на callback URL. Один и тот же URL нельзя зарегистрировать с разными фильтрами meetingID или eventID — побеждает первая регистрация.
  • Очистка данных: Внутренние сопоставления встреч удаляются после одной недели неактивности (настраивается через mappings.timeout, по умолчанию: 604800000 мс).
  • Синтетические события: Когда встреча заканчивается, события user-left автоматически генерируются для всех ещё подключённых пользователей, потому что сам BigBlueButton не генерирует UserLeftMeetingEvtMsg при завершении встречи.
  • Приватные чаты: Только сообщения публичного чата создают события chat-group-message-sent. Личные сообщения молча игнорируются.
На bbbserver.de webhooks доступны с двумя ограничениями: (1) для каждого хука требуется meetingID — глобальные хуки без meetingID не поддерживаются; (2) персональные данные в событиях автоматически обфусцируются в целях конфиденциальности (например, IP-адреса участников не видны).

Часто задаваемые вопросы

Да. Пакет bbb-webhooks должен быть установлен через apt-get install bbb-webhooks. Без него эндпоинты hooks/create, hooks/list и hooks/destroy недоступны.

Система вебхуков повторяет доставку с экспоненциальной задержкой в течение примерно 5 минут (12 попыток). Если все повторные попытки не удаются, непостоянные хуки автоматически удаляются. Постоянные хуки продолжают повторные попытки бесконечно с интервалом в 60 секунд.

Нет. Обнаружение дубликатов основано исключительно на callback URL. Если вы снова зарегистрируете тот же URL, вы получите duplicateWarning, а существующий хук останется без изменений. Чтобы отдельно отслеживать конкретные встречи, используйте разные callback URL.

Нет. Только сообщения, отправленные в публичный чат (MAIN-PUBLIC-GROUP-CHAT), вызывают событие chat-group-message-sent. Личные сообщения между участниками не генерируют никаких событий webhook.

С getRaw=false (по умолчанию) вы получаете обработанные данные события со стандартизированной структурой, содержащей поля type, id и attributes. С getRaw=true вы получаете необработанное сообщение Redis, опубликованное внутренне BigBlueButton, которое включает поля envelope и core. Необработанный формат полезен для отладки или когда вам нужны данные, не включённые в обработанный формат.

Нет. Постоянные хуки настраиваются на стороне сервера через параметр permanentURLs и не могут быть удалены через API. Вызов hooks/destroy для постоянного хука возвращает ошибку destroyMissingHook, как будто хук не существует.

HTTP 2xx и HTTP 401 оба считаются успешной доставкой. Все остальные коды статуса, включая 3xx (после перехода максимум по 10 перенаправлениям), 4xx (кроме 401) и 5xx, вызывают повторную попытку. Такое поведение не задокументировано в официальной документации BigBlueButton.
Руководство по API BigBlueButton