Вебхуки
Входящий вебхук позволяет другой системе отправлять сообщения в канал, передавая JSON на секретный URL. Исходящий вебхук работает наоборот: он отправляет сообщения на ваш URL — те, что начинаются со слова триггера, или те, для которых человек выбирает его в меню сообщения, — и публикует ваш ответ.
Где управлять вебхуками
Откройте свой аватар в правом верхнем углу, затем выберите Интеграции. На страницах интеграций текущего сообщества перечислены Входящие вебхуки и Исходящие вебхуки. Каждый вебхук принадлежит одному сообществу.
По умолчанию вебхуки могут создавать администраторы сообщества и системные администраторы. Системный администратор может предоставить это право другим ролям в настройках разрешений Системной консоли. Системный администратор также может отключить каждый тип вебхука в Системная консоль › Интеграции › Управление интеграцией: Разрешить входящие вебхуки и Разрешить исходящие вебхуки включены по умолчанию.

Создание входящего вебхука
- В разделе Интеграции выберите Входящие вебхуки, затем Добавить входящий Webhook.
- Заполните Заголовок и Описание: они отображаются только на страницах интеграций.
- Выберите Канал, в который сообщения отправляются по умолчанию. Для закрытого канала вы должны быть его участником.
- Отметьте Прикрепить к этому каналу, если отправители не должны иметь возможность публиковать сообщения в других каналах.
- При необходимости задайте Имя пользователя и URL Изображения профиля для его сообщений (см. Имя и значок).
- Выберите Сохранить. Скопируйте отображаемый URL:
https://chat.example.com/hooks/<key>.
Через API: POST /api/v4/hooks/incoming с {"channel_id", "display_name", "description", "username", "icon_url", "channel_locked"}; id в ответе является ключом. Из командной строки: amctl webhook create-incoming --channel <channel id> --user <user> --display-name "CI".
Отправка сообщения во входящий вебхук
curl -X POST https://chat.example.com/hooks/xgh5ycrx1jf7mbs9w8z4c8e7ho \
-H 'Content-Type: application/json' \
-d '{"text": "Deploy of **api 2.4.0** finished :white_check_mark:"}'
Сервер отвечает 200 с телом ok. Он также принимает application/x-www-form-urlencoded с JSON в поле payload, как вебхуки Slack, поэтому инструменты, созданные для Slack, обычно работают без изменений.
| Поле | Значение |
|---|---|
text | Сообщение в формате Markdown. Обязательное поле, если нет attachments. Текст, превышающий лимит длины сообщения сервера, разбивается на несколько сообщений. |
channel | Другой канал сообщества вебхука, по имени (ops-alerts или #ops-alerts), или @username для личного сообщения от владельца вебхука. Отказывается, если вебхук привязан к своему каналу. Старое имя town-square по-прежнему ведёт в канал по умолчанию сообщества, который теперь называется general. |
username, icon_url, icon_emoji | Имя и изображение для отображения, если сервер разрешает переопределения. |
attachments | Вложения к сообщению, отображаемые в виде карточек (см. ниже). |
props | Дополнительные свойства, сохраняемые в сообщении для приложений, которые их читают. |
type | Пользовательский тип сообщения, например custom_poll, для приложения, которое его отображает. Типы, начинающиеся с system_, отклоняются. |
root_id | ID первого сообщения Обсуждения, чтобы ответить в этом Обсуждении. |
priority | Приоритет сообщения, например {"priority": "urgent"}. |
silent | true отправляет сообщение без push-уведомлений. |
Каждое сообщение, отправленное вебхуком, имеет метку БОТ рядом с именем, даже если оно отображается от имени создателя, чтобы его можно было отличить от сообщения реального человека. Сообщения вебхуков никогда не активируют исходящие вебхуки.
Имя и значок
Вебхук публикует сообщения от имени человека, который его создал, если сервер не разрешает переопределение. Два параметра в Системная консоль › Интеграции › Управление интеграцией, оба отключены по умолчанию, изменяют это поведение:
- Разрешить интеграциям переопределять имена пользователей (
ServiceSettings.EnablePostUsernameOverride): отображается Имя пользователя вебхука илиusernameиз запроса; если ни одно из них не задано, имя будетwebhook. - Разрешить интеграциям переопеределять иконки изображений профилей (
ServiceSettings.EnablePostIconOverride): отображается Изображение профиля вебхука илиicon_urlилиicon_emojiиз запроса.
Значение из запроса имеет приоритет над сохранённым в вебхуке.
Вложения
Вложения добавляют структурированный контент под текстом. Они следуют формату вложений сообщений Slack:
{
"text": "Build failed on `main`",
"attachments": [{
"fallback": "main #1902 failed",
"color": "#d24b4e",
"author_name": "GitHub Actions",
"author_icon": "https://chat.example.com/static/ci.png",
"title": "main #1902 failed",
"title_link": "https://ci.example.com/runs/1902",
"text": "Commit `0f4d8e2` by Jonas Weber",
"fields": [
{"title": "Branch", "value": "zephyr-3.7", "short": true},
{"title": "Duration", "value": "3m 40s", "short": true}
],
"footer": "Lumen CI",
"ts": 1760000000
}]
}
| Поле | Значение |
|---|---|
fallback | Обычный текст для мест, где карточка не может быть отображена, например в уведомлениях. |
color | Цветная полоса: шестнадцатеричный цвет, либо good, warning, danger. |
pretext | Текст над карточкой. |
author_name, author_link, author_icon | Небольшая строка заголовка. |
title, title_link | Заголовок карточки, опционально со ссылкой. |
text | Тело карточки, в формате Markdown. |
fields | Список {"title", "value", "short"}; поля short располагаются рядом. |
image_url, thumb_url | Большое изображение внизу или маленькое сбоку. |
footer, footer_icon, ts | Строка подвала и время (в секундах Unix). |
actions | Кнопки и меню: см. Интерактивные сообщения. |
Карточки: этапы и графики
Antimatter добавляет к вложениям два поля, отображаемые стандартным интерфейсом:
stages: шаги конвейера в виде «пилюль», до 20. Каждый элемент имеет вид{"name", "status"}, где status принимает значениеpassed,failed,running,pending,skippedилиcanceled.chart: небольшой линейный график последних значений,{"values": [2 to 200 numbers], "threshold": number, "label": "…"}. Порог отображается пунктирной линией, например, для ограничения тревоги.
{
"attachments": [{
"color": "danger",
"title": "main #1902 failed",
"stages": [
{"name": "build", "status": "failed"},
{"name": "unit", "status": "skipped"},
{"name": "publish", "status": "skipped"}
]
}, {
"color": "warning",
"title": "API latency above 400 ms",
"chart": {"values": [210, 230, 260, 390, 450, 470], "threshold": 400, "label": "p95 latency, ms"}
}]
}
Классический интерфейс и другие клиенты игнорируют эти два поля, поэтому дублируйте основную информацию в полях text или fields.
Создание исходящего вебхука
Исходящий вебхук отслеживает общие каналы сообщества. Он отправляет сообщение на ваш URL, когда первое слово сообщения совпадает с одним из его триггерных слов, либо когда кто-то выбирает его в меню сообщения (действие с сообщением).
- В разделе Интеграции выберите Исходящие вебхуки, затем Добавить исходящий Webhook.
- Заполните Заголовок и Описание.
- Выберите Тип содержимого запроса:
application/x-www-form-urlencodedилиapplication/json. - Выберите Канал, введите Ключевые слова (по одному на строку) или и то, и другое. Если указан канал, но нет ключевых слов, отправляются все сообщения этого канала. Если указаны оба условия, сообщение должно соответствовать обоим.
- В разделе Условие срабатывания выберите Первое слово соответствует слову события полностью, Первое слово начинается со слова триггера или Из меню сообщения. При выборе Из меню сообщения слова триггера исчезают, Канал становится необязательным (без него действие предлагается во всех публичных каналах сообщества), а Заголовок становится обязательным: это имя действия в меню.
- Введите URL обратного вызова (по одному на строку). Каждому URL отправляется каждое подходящее сообщение.
- При необходимости задайте Имя пользователя и Изображение профиля, используемые для ответов. Для действия из меню сообщения поле Значок заменяет Изображение профиля: это URL изображения в формате .png или .jpg или загруженное изображение в интерфейсе Antimatter по умолчанию. В меню оно отображается серым цветом; без него действие получает нейтральный значок.
- Нажмите Сохранить и скопируйте отображаемый токен. Ваша служба использует его для проверки того, что запросы исходят от вашего сервера.
Через API: POST /api/v4/hooks/outgoing с {"team_id", "channel_id", "trigger_words", "trigger_when", "callback_urls", "content_type", "display_name"} (trigger_when: 0 для точного совпадения, 1 для «начинается с», 2 для «из меню сообщения»). Вебхук с trigger_when 2 не принимает триггерные слова и требует display_name. Загрузите его иконку с помощью POST /api/v4/hooks/outgoing/{hook_id}/icon (multipart, поле image: PNG, JPEG или GIF, хранится как PNG 128 px); его icon_url затем указывает на GET /api/v4/hooks/outgoing/{hook_id}/icon.
ServiceSettings.AllowedUntrustedInternalConnections). В противном случае сервер не обращается к частным адресам.Исходящий запрос
Antimatter отправляет POST-запрос с этими полями в формате JSON или form-encoded в зависимости от типа содержимого:
{
"token": "6kd1ofo5ojr5zgu5ipfipybgnc",
"team_id": "…",
"team_domain": "lumen-labs",
"channel_id": "…",
"channel_name": "ops-alerts",
"timestamp": 1760010000000,
"user_id": "…",
"user_name": "priya",
"post_id": "…",
"text": "deploy api 2.4.0",
"trigger_word": "deploy",
"file_ids": ""
}
Сначала сравните token с токеном вебхука. В версии с кодировкой формы timestamp указывается в секундах, а не в миллисекундах. Сервер ожидает ваш ответ в течение времени, разрешённого параметром Таймаут запроса на интеграцию (по умолчанию 30 секунд, ServiceSettings.OutgoingIntegrationRequestsTimeout).
Ответ на исходящий вебхук
Чтобы отправить ответ, верните JSON. Чтобы ничего не отправлять, верните пустое тело ответа.
{
"text": "Deploying **api 2.4.0** to staging…",
"response_type": "comment",
"username": "deploy-bot",
"icon_url": "https://chat.example.com/static/deploy.png"
}
textиattachments: содержимое ответа. Если ни одно из полей не указано, ничего не будет отправлено.response_type: значениеcommentотправляет ответ в обсуждение сообщения, вызвавшего вебхук; в противном случае ответ публикуется в канале.username,icon_url: отображаются, если сервер разрешает переопределение; в противном случае используются собственные значения вебхука.props,type,priority: как для входящих вебхуков.
Ответ публикуется от имени создателя вебхука, с переопределённым именем, если оно указано. Для ответов длиннее короткого ответа отправьте ответ сразу, а затем опубликуйте его позже с помощью входящего вебхука или API.
Действия с сообщением
Действие с сообщением — это исходящий вебхук с параметром Условие срабатывания, установленным в значение Из меню сообщения. Он никогда не срабатывает на отправленных сообщениях. Вместо этого пользователи видят его в меню сообщения: Действия с сообщением (⋯) › Другие действия, в разделе Интеграции, с его иконкой. В классическом интерфейсе действия с сообщением не отображаются. При выборе действия одно это сообщение отправляется на URL обратного вызова, а короткое уведомление показывает Отправлено в с именем действия или отображает ваш ephemeral_text.
- Где отображается: в канале вебхука или, если канал не указан, во всех публичных каналах сообщества. Действия с сообщением доступны только в публичных каналах.
- Гости получают только действия, привязанные к каналу, в котором они находятся, а не общесообщественные.
- Архивированные и каналы только для чтения: сообщение всё равно может быть отправлено. Архивирование канала удаляет вебхуки, привязанные к нему, поэтому в архивированном канале остаются только общесообщественные действия. Ответ, который пользователь не мог отправить в этот канал, показывается только ему.
- Ограничение частоты: каждый пользователь может выполнить 10 действий с сообщением в минуту после серии из 5. При превышении сервер отвечает
429. - Частные сети: как и для других исходящих вебхуков, внутренние адреса должны быть разрешены в параметре Разрешить недоверенные внутренние соединения для.
Запрос
Данные отправляются в формате JSON или form-encoded, в соответствии с типом содержимого вебхука:
{
"token": "6kd1ofo5ojr5zgu5ipfipybgnc",
"trigger": "message_action",
"team_id": "…",
"team_domain": "lumen-labs",
"channel_id": "…",
"channel_name": "ops-alerts",
"timestamp": 1760010000000,
"user_id": "…",
"user_name": "priya",
"post_id": "…",
"post_root_id": "",
"post_create_at": 1760009000000,
"post_user_id": "…",
"post_user_name": "jonas",
"permalink": "https://chat.example.com/lumen-labs/pl/…",
"text": "The staging database is full again",
"files": [{"id": "…", "name": "df.txt", "link": "https://chat.example.com/api/v4/files/…"}],
"priority": "",
"requested_ack": false,
"burn_on_read": false
}
user_idиuser_name— это пользователь, выбравший действие;post_user_idиpost_user_name— автор сообщения.- Отправляется только это сообщение, никогда — остальная часть обсуждения.
filesсодержит файлы сообщения только в том случае, если пользователь, выбравший действие, имеет право их скачать. Скачиваниеlinkтребует сессии или токена, как и любой файл API.- Сообщение, сгорающее после прочтения, отправляется без текста и файлов, с параметром
burn_on_read, установленным вtrue. - При кодировании формы файлы передаются как повторяющиеся поля
file_id,file_nameиfile_linkв том же порядке.
Ответ
Ответ формируется так же, как для любого исходящего вебхука (см. Ответ на исходящий вебхук): text или attachments публикует ответ в канале, а "response_type": "comment" — в обсуждении сообщения. Также можно ответить с помощью ephemeral_text (не более 300 символов): он отображается только тому, кто выбрал действие, в уведомлении. Пустое тело ответа ничего не публикует.
{"ephemeral_text": "Ticket OPS-412 created"}
С помощью API
GET /api/v4/channels/{channel_id}/message_actions: действия, доступные в канале, с полямиid,display_name,descriptionиicon_url. Токены и URL обратного вызова не возвращаются.POST /api/v4/posts/{post_id}/message_actions/{hook_id}: выполняет действие над сообщением, которое вы можете прочитать. Возвращает{"ephemeral_text"}.
Если вебхук не работает
- 501 от URL вебхука: входящие вебхуки отключены на сервере.
- 400 "Failed to decode the payload…": JSON недействителен, или поле формы не называется
payload. Сообщение "No text specified." означает, что в запросе нет ниtext, ниattachments. - 403: вебхук привязан к другому каналу, или его владелец больше не может читать канал.
- Исходящий вебхук никогда не срабатывает: канал закрытый, триггер не является первым словом, сообщение отправлено вебхуком или вебхук настроен на срабатывание Из меню сообщения.
- Действие не отображается в меню: канал закрытый, действие привязано к другому каналу, пользователь является гостем, а действие не привязано к каналу, или исходящие вебхуки отключены.
- 404 при выполнении действия: действие не существует или не распространяется на канал данного сообщения для этого пользователя. 429: пользователь выполнил более 10 действий за минуту. 502: ни один URL обратного вызова недоступен (причина указана в журнале).
- Журналы: при включённом параметре Включить отладку Webhook-ов (
LogSettings.EnableWebhookDebugging) и уровне журналаDEBUGсервер записывает в журнал данные (payloads) неудачных входящих запросов. Неудачные исходящие вызовы записываются какOutgoing Webhook POST failed.