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

Уведомления

In-app уведомления («колокольчик») — персональная лента событий, адресованных конкретному пользователю кабинета (например, назначение на сделку или на задачу по сделке). Это REST-сторона того же потока, что в реальном времени приходит событием notification.created по персональному WebSocket-каналу пользователя: сокет нужен для живого пуша и бейджа, а эти эндпоинты — чтобы подгрузить историю при загрузке приложения, узнать число непрочитанных и сбросить бейдж.

Скоуп ленты

Лента скоупится по текущему пользователю и его активной компании (current_company_id): список, счётчик и «отметить всё» возвращают только уведомления активной компании; пометка одного уведомления прочитанным находит его по владельцу-пользователю независимо от компании.

Объект уведомления

Объект уведомления содержит поля:

  • id — строка UUID.
  • type — строковый идентификатор вида уведомления в snake_case; сейчас платформа эмитит deal_assigned и deal_task_assigned, набор будет расширяться.
  • title — короткий заголовок.
  • body — строка или null.
  • data — объект с полями, зависящими от type (например, deal_id/deal_title для deal_assigned).
  • read_at — ISO-время прочтения или null, если не прочитано.
  • created_at — время создания.

Форма ответа списка и параметры

Важно про форму ответа списка: GET /v1/notifications отдаёт стандартный конверт пагинатора Laravel — массив под ключом data, а мета-поля пагинации (current_page, per_page, total, last_page, next_page_url и т.д.) лежат плоско на верхнем уровне. Это отличается от большинства REST-групп, где список приходит как data:{ items, pagination }.

Параметры запроса: filter=unread (вернуть только непрочитанные; любое другое значение или отсутствие параметра — все), per_page (размер страницы, по умолчанию 20). Обратите внимание на snake_case per_page (не perPage).

Платформенные уведомления (`GET /platform-notifications`)

GET /platform-notifications (2026-08-24) — не путать с персональной лентой «колокольчика» выше: это company-scoped (не per-user) плоский журнал технических уведомлений от самой платформы AISAR (пока единственный вид — «канал отключился», из NotifyChannelDisconnectedJob), заменивший собой прежнюю механику служебных диалогов в чате. Право доступа — conversation.view (то же, что у семейства /conversations), окно выдачи — последние 90 дней, сортировка — новые сверху, пагинация постраничная (page/limit, limit 1–50, по умолчанию 20; блок pagination {page, perPage, total, lastPage}). Лимитер — 120 запросов в минуту.

Элемент списка: id, kind (тип уведомления, например channel_disconnected), reason (человекочитаемая причина или null), created_at, channel ({id, name, type} либо nullnull, если канал с тех пор удалён; событие само по себе не исчезает вместе с каналом), conversation_id и message_id (для обратной совместимости с уведомлениями, унаследованными от прежней механики; null для новых записей). «Прочтение» ленты — не по элементам, а курсором: PATCH /me/ui-preferences с aisar_notifications.seen_until (ISO-datetime либо null) продвигает границу непросмотренного, которую использует счётчик counters.aisar_notifications в группе «Диалоги» (GET /conversations/counters).

Эндпоинты

МетодПуть
GET/v1/notifications

Лента уведомлений пользователя в активной компании (конверт пагинатора Laravel). Параметры: `filter=unread`, `per_page` (по умолчанию 20).

GET/v1/notifications/unread-count

Число непрочитанных уведомлений пользователя в активной компании. Ответ: `{ "count": N }`.

POST/v1/notifications/{notification}/read

Отметить одно уведомление прочитанным (по его UUID). Ответ: `{ "status": "ok" }`; 404, если уведомление не найдено или принадлежит другому пользователю.

POST/v1/notifications/read-all

Отметить прочитанными все непрочитанные уведомления пользователя в активной компании. Ответ: `{ "status": "ok" }`.

GET/v1/platform-notifications

Company-scoped журнал платформенных уведомлений (например «канал отключился») за последние 90 дней.

Примеры

Список непрочитанных уведомлений

Запрос

bash
curl -X GET "https://api.aisar.app/v1/notifications?filter=unread&per_page=20" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Ответ

json
{
  "current_page": 1,
  "data": [
    {
      "id": "3f1e6a20-0c7b-4a9e-b2d1-8a5c1e000001",
      "company_id": 1,
      "user_id": 7,
      "type": "deal_assigned",
      "title": "You were assigned to deal \"Website redesign\"",
      "body": "Assigned by Aigerim",
      "data": {
        "deal_id": 42,
        "deal_title": "Website redesign",
        "assigned_by": 3
      },
      "read_at": null,
      "created_at": "2026-02-10T09:15:00.000000Z",
      "updated_at": "2026-02-10T09:15:00.000000Z"
    }
  ],
  "first_page_url": "https://api.aisar.app/v1/notifications?page=1",
  "from": 1,
  "last_page": 1,
  "last_page_url": "https://api.aisar.app/v1/notifications?page=1",
  "next_page_url": null,
  "path": "https://api.aisar.app/v1/notifications",
  "per_page": 20,
  "prev_page_url": null,
  "to": 1,
  "total": 1
}

Счётчик непрочитанных

Запрос

bash
curl -X GET "https://api.aisar.app/v1/notifications/unread-count" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Ответ

json
{
  "count": 3
}

Отметить одно уведомление прочитанным

Запрос

bash
curl -X POST "https://api.aisar.app/v1/notifications/3f1e6a20-0c7b-4a9e-b2d1-8a5c1e000001/read" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Ответ

json
{
  "status": "ok"
}

Отметить все прочитанными

Запрос

bash
curl -X POST "https://api.aisar.app/v1/notifications/read-all" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Ответ

json
{
  "status": "ok"
}

Журнал платформенных уведомлений

Запрос

bash
curl -X GET "https://api.aisar.app/v1/platform-notifications?limit=20" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Ответ

json
{
  "data": {
    "items": [
      {
        "id": 340,
        "kind": "channel_disconnected",
        "reason": "logged_out",
        "created_at": "2026-08-24T09:12:00.000000Z",
        "channel": { "id": 3, "name": "Основной WhatsApp", "type": "whatsapp" },
        "conversation_id": null,
        "message_id": null
      }
    ],
    "pagination": { "page": 1, "perPage": 20, "total": 1, "lastPage": 1 }
  }
}