Перейти к содержимому

Делегирование каналов (Sharing)

Делегирование (sharing) — это способ дать другому человеку доступ к одному вашему каналу, не пуская его в остальной аккаунт. Коллега получит право либо только читать сообщения этого канала, либо читать и отправлять в него новые — но не сможет ни видеть другие ваши каналы, ни менять настройки, ни управлять клиентами и токенами.

Удобно, когда:

  • нужно показать команде только канал Prod-алёрты, не открывая весь проект;
  • CI-боту нужно лишь слать в один канал (право send) и больше ничего;
  • дежурный должен видеть входящие уведомления конкретного сервиса (view);
  • хочется передать доступ временно — делегацию легко отозвать, не трогая токены самого канала.

Технически каждая делегация — это отдельный Share-токен с префиксом S, привязанный к каналу. Владелец канала выпускает токен, опционально указывает email получателя и уровень доступа. Получатель пользуется токеном как обычным notifly-токеном (см. ниже Как получателю пользоваться доступом).

permissionЧто разрешено
viewВидеть сам канал в списке и читать его сообщения (GET /message).
sendТо же, что view, плюс отправлять сообщения (POST /message).

send включает в себя view. Любые мутации самого канала, клиентов, токенов, а также удаление сообщений по Share-токену запрещены (ответ 403).

Делегация на конкретный email сначала создаётся в статусе приглашения, которое получатель может принять или отклонить:

statusЧто значит
pendingПриглашение выдано, получатель ещё не отреагировал.
acceptedПолучатель принял — канал появился у него в списке.
declinedПолучатель отклонил приглашение.

Принять можно только pending-приглашение (POST /share/:id/accept); попытка принять/отклонить уже обработанное вернёт 400 share is not pending.

Запрос делает владелец канала (или делегированный пользователь — см. Ре-шеринг) клиент-токеном или MCP-кодом с правом записи.

Окно терминала
curl -X POST "$NOTIFLY_URL/application/42/share" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <client-token>" \
-d '{
"recipientEmail": "colleague@example.com",
"permission": "view",
"note": "Дежурному на эту неделю"
}'

Поля тела (ChannelShareParams):

ПолеТипОбязательноОписание
permissionstringдаview или send. Другое значение → 400.
recipientEmailstringнетEmail получателя. Если пусто — получается «open share» (см. ниже).
notestringнетПроизвольный комментарий для себя («для CI», «коллеге Х»).

Ответ — созданный объект ChannelShare:

{
"id": 1007,
"token": "S9f3k...",
"appid": 42,
"recipientEmail": "colleague@example.com",
"permission": "view",
"status": "pending",
"note": "Дежурному на эту неделю",
"created": "2026-06-23T10:00:00Z",
"lastUsed": null,
"appName": "Prod-алёрты"
}

Поле token (префикс S) — это и есть Share-токен. Передайте его получателю любым каналом, либо рассчитывайте на то, что он сам найдёт приглашение через входящие.

Если оставить recipientEmail пустым, делегация становится open share — ссылкой/токеном, которым может воспользоваться кто угодно, у кого он есть. В этом случае получатель присоединяется через POST /share/join, и для него создаётся персональная копия делегации (со своим Share-токеном), не затрагивая оригинал. Это удобно для приглашений вида «перешлите ссылку команде».

После того как делегация принята (accepted), канал появляется в обычном списке получателя (GET /application). Дальше Share-токен используется как любой notifly-токен:

Окно терминала
# Чтение сообщений канала (view и send)
curl "$NOTIFLY_URL/message" -H "X-Notifly-Key: S9f3k..."
# Отправка в канал (только send)
curl -X POST "$NOTIFLY_URL/message" \
-H "X-Notifly-Key: S9f3k..." \
-d 'title=Деплой&message=Готово'

Share-токен даёт доступ строго к одному каналу. Попытка вызвать мутирующие эндпоинты (создать/изменить канал, удалить сообщение, управлять токенами) вернёт 403 share tokens cannot perform this action.

Получатель видит выданные на его email делегации через GET /share/incoming. Возвращаются как ещё не принятые (pending), так и принятые (accepted) — кроме приглашений на каналы, которыми получатель уже владеет, и pending-дубликатов с теми же правами, что у уже принятой делегации.

Окно терминала
curl "$NOTIFLY_URL/share/incoming" -H "X-Notifly-Key: <client-token>"
Окно терминала
# Принять — канал появится в списке получателя
curl -X POST "$NOTIFLY_URL/share/1007/accept" -H "X-Notifly-Key: <client-token>"
# Отклонить
curl -X POST "$NOTIFLY_URL/share/1007/decline" -H "X-Notifly-Key: <client-token>"

Принять/отклонить может только пользователь, чей email совпадает с recipientEmail делегации; иначе — 404. Обработать можно только pending-приглашение.

Если получателю передали Share-токен напрямую (например, open share или просто строку S...), он присоединяется одним вызовом:

Окно терминала
curl -X POST "$NOTIFLY_URL/share/join" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <client-token>" \
-d '{"token": "S9f3k..."}'

Поведение зависит от типа делегации:

  • ИменнаяrecipientEmail): токен присоединяет, только если email пользователя совпадает с адресом делегации (иначе 403 this share is not for your email). Статус автоматически переводится в accepted.
  • Open share (без email): создаётся персональная копия делегации для присоединившегося со статусом accepted. Если у него уже есть делегация на этот канал, она при необходимости повышается до send и переводится в accepted.

Неверный токен → 404 invalid share token.

Управление выданными делегациями (владельцу)

Заголовок раздела «Управление выданными делегациями (владельцу)»

Список делегаций конкретного канала (показываются только созданные вами; владельцу канала также видны legacy-делегации без автора):

Окно терминала
curl "$NOTIFLY_URL/application/42/share" -H "X-Notifly-Key: <client-token>"

Изменить уровень доступа, email или комментарий — PUT /share/:id (только владелец канала):

Окно терминала
curl -X PUT "$NOTIFLY_URL/share/1007" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <client-token>" \
-d '{"permission": "send", "recipientEmail": "colleague@example.com"}'

Отозвать делегацию — DELETE /share/:id. Удалить может тот, кто её создал, либо владелец канала (для legacy-делегаций без автора). После удаления токен немедленно перестаёт работать, и канал исчезает из списка получателя.

Окно терминала
curl -X DELETE "$NOTIFLY_URL/share/1007" -H "X-Notifly-Key: <client-token>"

Чтобы не вводить email вручную, форма шеринга может подсказать адреса, с кем вы уже делились, — GET /share/recipients возвращает список distinct-email от самых свежих к старым:

Окно терминала
curl "$NOTIFLY_URL/share/recipients" -H "X-Notifly-Key: <client-token>"

Отказ от доступа и ротация своего токена (получателю)

Заголовок раздела «Отказ от доступа и ротация своего токена (получателю)»

Получатель управляет только своей стороной доступа — двумя вызовами. Оба принимают канал в теле запроса (appid), а не в пути:

Окно терминала
# Отказаться от доступа к каналу (канал исчезает из списка, токен умирает)
curl -X POST "$NOTIFLY_URL/share/leave" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <client-token>" \
-d '{"appid": 42}'
# Сменить значение своего Share-токена (например, при компрометации)
curl -X POST "$NOTIFLY_URL/share/rotate" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <client-token>" \
-d '{"appid": 42}'
  • share/leave удаляет все ваши доступы к этому каналу (их может быть несколько, если делились разные люди). Сама делегация владельцем при этом не «возвращается»: чтобы вернуться, нужно новое приглашение или токен.
  • share/rotate меняет значение токена на месте, сохраняя права и привязку; старое значение перестаёт работать сразу. Ротировать можно только принятую (accepted) и действующую делегацию.

Если доступа к каналу нет, оба вызова отвечают 404.

Делегации по email — про людей. Для скриптов, CI и интеграций у канала есть машинные ключи: несколько ключей на канал, у каждого свои права, метка, срок действия и собственный lastUsed.

Окно терминала
# Выдать ключ только на отправку
curl -X POST "$NOTIFLY_URL/application/42/token" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <client-token>" \
-d '{"name": "CI deploy key", "canRead": false, "canWrite": true,
"note": "gitlab runner", "expiresAt": 0}'
ПолеЗначение
nameчеловекочитаемая метка ключа
canReadчтение истории канала и подписка по WebSocket
canWriteотправка в канал (POST /message, /ask)
noteпроизвольный комментарий
expiresAtсрок действия, unix-миллисекунды; 0 — бессрочно

Ключ обязан разрешать хотя бы одно из canRead/canWrite, иначе — 400. Управление ключами доступно только владельцу канала: получателю делегации оно не положено даже с правом записи.

Отзыв двухступенчатый. Первый DELETE /token/:id — мягкий: ключ перестаёт аутентифицировать, но строка остаётся, и видно, когда он использовался в последний раз и когда отозван. Повторный DELETE удаляет запись навсегда.

Ротация (POST /token/:id/rotate) меняет только значение: id, права и привязка к каналу сохраняются, поэтому ничего, что ссылается на ключ, не рвётся.

Отзыв действует со следующего запроса. Исключение — уже открытое WebSocket-соединение: оно авторизовано до апгрейда и живёт со старым ключом до переподключения.

Делегированный пользователь может, в свою очередь, поделиться каналом дальше — но не выше собственного уровня доступа. Если у вас есть только view, попытка выдать send вернёт:

403 cannot grant 'send' permission — you only have 'view' access

Владелец канала всегда считается имеющим максимальный доступ (send). Каждый пользователь в списке GET /application/:id/share видит только свои делегации (поле created_by), поэтому ре-шеринг не раскрывает чужие делегации того же канала.

Метод и путьАвторизацияНазначение
GET /application/:id/shareclient-tokenсписок делегаций канала (только свои)
POST /application/:id/shareclient-token (write)создать делегацию (выдать Share-токен)
PUT /share/:idclient-token (write)изменить permission / email / note (владелец канала)
DELETE /share/:idclient-token (write)отозвать делегацию
GET /share/incomingclient-tokenвходящие приглашения на email пользователя
GET /share/recipientsclient-tokenemail-адреса, с кем вы уже делились (для подсказок)
POST /share/:id/acceptclient-tokenпринять pending-приглашение
POST /share/:id/declineclient-tokenотклонить pending-приглашение
POST /share/joinclient-tokenприсоединиться к каналу по Share-токену
POST /share/leaveclient-token (write)отказаться от доступа к каналу, тело {"appid": N}
POST /share/rotateclient-token (write)сменить значение своего Share-токена, тело {"appid": N}
GET /application/:id/tokenclient-tokenмашинные ключи канала (только владелец)
POST /application/:id/tokenclient-token (write)выдать машинный ключ
PUT /token/:idclient-token (write)изменить права, метку и срок ключа
DELETE /token/:idclient-token (write)отозвать ключ (повторно — удалить навсегда)
POST /token/:id/rotateclient-token (write)сменить значение ключа, сохранив права