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

GET /api/public/notifications/inbox — Мои in-app уведомления

Назначение

Авторизованный пользователь читает свои in-app уведомления (NotificationEntity, Channel = InApp) — страницу ленты-колокольчика с пагинацией и число непрочитанных для бейджа. Owning-контекст — notifications, feature group inbox.

Metadata

ПолеЗначение
Сервис/контекстnotifications
API areapublic (JWT пользователя)
Feature groupinbox
Статусdraft
Документdocs/06-services/notifications/api/public/list-my-notifications.md

Актор и доступ

ПроверкаЗначение
Actor typeUser
Auth policy / Permissionsnotifications.inbox.read (own)
Record-levelвладелец = RecipientUserId (актор)
Tenant isolationдоступ по RecipientUserId; TenantId не фильтрует (уведомления получателя)
Auditread (тело — PII, наружу только владельцу)

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/public/notifications/inbox
Success status200
Idempotency headerне применяется
Correlationсквозной trace через заголовок traceparent

Входные данные / параметры запроса

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
RecipientUserIdidentity claims (JWT sub)GuidДане Guid.Emptyвладелец
PagingqueryPagingQueryДаPageSize 1..100 (default 20), keyset по CreatedAt desc
UnreadOnlyqueryboolНетdefault false
KindqueryNotificationKind?Нетзначение enum (фильтр)

Модель ответа InboxPageModel

ПолеТипОбязательностьИсточникMaskingОписание
Itemsстраница NotificationItemModelДалента уведомленийСтраница уведомлений получателя.
UnreadCountintДачисло Status != Read при Channel = InAppЧисло непрочитанных (бейдж).

NotificationItemModel — проекция NotificationEntity: NotificationId (Guid), Kind (NotificationKind), Title (string?), Body (string), DeepLink (string?), IsRead (bool, = Status == Read), CreatedAt (DateTimeOffset).

Алгоритм

Операцию выполняет авторизованный пользователь (RecipientUserId из JWT; нет валидного JWT → UNAUTHENTICATED); доступ — только к собственным уведомлениям. Проверяется корректность параметров: Paging в границах, Kind — допустимое значение (нарушение → VALIDATION_FAILED). Возвращается страница in-app уведомлений получателя (Channel = InApp, не удалённые, при UnreadOnly — только Status != Read, опционально фильтр по Kind), отсортированных по CreatedAt убыв., плюс отдельно счётчик непрочитанных для бейджа. Каждый элемент маппится в NotificationItemModel (IsRead = Status == Read).

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
UNAUTHENTICATED401нет/невалидный JWT«Требуется авторизация»no retry
VALIDATION_FAILED400Paging/Kind вне границ«Проверьте параметры»no retry

Полнота выборки и границы

  • В ленту входят только уведомления получателя с Channel = InApp и DeletedAt = null; внешние каналы (email/sms/push/…) в inbox не показываются. Доступ строго по RecipientUserId = actor — чужие записи недоступны (INV-NTF-6), кросс-tenant фильтра нет.
  • UnreadCount — число in-app уведомлений в статусе != Read (то есть Pending/Sent; терминальный для in-app — Read); считается по всему инбоксу получателя независимо от UnreadOnly/Kind-фильтра страницы.
  • Фильтры комбинируются по «И»: UnreadOnly = true оставляет Status != Read; Kind сужает по виду.
  • Пустой инбокс или страница за пределами набора — не ошибка: 200, пустой Items, UnreadCount = 0.
  • Keyset-пагинация по CreatedAt desc устойчива к вставке новых уведомлений между запросами страниц (курсор по CreatedAt, не смещается при дозаписи).

Соотношение с realtime

Новые in-app уведомления и изменения бейджа приходят push-ом через SignalR (../../providers/in-app.md) сразу после persist. Этот endpoint — догоняющее чтение: первичная загрузка ленты, восстановление после reconnect/пропуска push. Промежуточное состояние: до получения push клиент может недосчитаться самого свежего уведомления — повторный list/reconnect его подтянет (eventual, окно — секунды).

Совместимость и наблюдаемость

  • Новые фильтры/поля — additive. Realtime-доставка новых уведомлений — через SignalR (../../providers/in-app.md); этот endpoint — догоняющее чтение/reconnect.
  • Logs: inbox-read (RecipientUserId, page size); metrics: notifications_inbox_read_total, notifications_inbox_unread_gauge.

Acceptance criteria

  • Given пользователь с несколькими in-app уведомлениями, when запрашивает inbox, then 200, страница по CreatedAt desc, UnreadCount = число непрочитанных.
  • Given UnreadOnly = true, when запрос, then только Status != Read; UnreadCount совпадает с полным числом непрочитанных инбокса.
  • Given пустой инбокс, when запрос, then 200, Items пуст, UnreadCount = 0 (не 404).
  • Given PageSize вне 1..100 или неизвестный Kind, when запрос, then 400 VALIDATION_FAILED.
  • Given отсутствует/просрочен JWT, when запрос, then 401 UNAUTHENTICATED.

Обратные ссылки

Автоссылки: где используется этот документ.

Связанные документы