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

Уведомления

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

Скоуп ленты

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

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

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

  • id — строка UUID.
  • type — строковый идентификатор вида уведомления в snake_case. Текущий каталог: conversation_assigned, call_missed, channel_disconnected, channel_banned, export_completed, export_failed, template_approved, template_rejected, broadcast_finished, broadcast_failed, history_sync_completed, ai_action_pending, deal_assigned, recording_retention_changed, recording_switched_off, recording_switched_on, task_assigned, task_reminder, task_reminder_unassigned (с 2026-09-26 три task_* заменили прежний deal_task_assigned, который больше не отправляется), lead_unsorted и lead_cap_reached (с 2026-09-29: новые авто-лиды в «Неразобранном» воронки — одна строка на воронку с текущим числом лидов, получают держатели deal.update, строка помечается прочитанной, когда колонку разобрали; достигнут часовой лимит авто-лидов компании — администраторам, раз в час) и три типа ИИ-сотрудников (с 2026-10-10): ai_agent_budget_warning (агент израсходовал budget_warning_pct месячного лимита, раз в месяц на агента, администраторам), ai_handoff_waiting (ИИ передал диалог людям, и никто не ответил за handoff.notify_after_minutes, участникам диалога), ai_model_retired (провайдер перестал отдавать модель агента; при ключе компании администратор должен выбрать новую, администраторам); с 2026-10-15 ещё два типа ночной проверки ИИ-сотрудников: ai_review_enabled (платформа включила проверку для занятых агентов компании, администраторам, до первого прогона; data: instance_ids и disable = {method, path, body} для кнопки «Выключить» — PUT /v1/ai-agents/review-settings с {enabled: false}) и ai_review_proposed (менеджер предложил решение по вопросу проверки, администраторам; data: issue_id, instance_id, без заголовка и фрагментов диалога). Утренний дайджест проверки (ai_review_digest, счётчики и ссылка, без текстов вопросов) уходит не в ленту, а по e-mail и WhatsApp администраторам, если это не выключено в review-settings; набор будет расширяться, поэтому неизвестный type показывайте по title/body, а не отбрасывайте.
  • category — раздел, к которому относится уведомление: inbox, calls, deals, tasks, channels, broadcasts, automations, data, team, billing, system. Поле есть всегда — удобно для группировки и фильтров в своём UI.
  • severity — важность: info, success, warning, critical. Тоже всегда присутствует.
  • title — короткий заголовок.
  • body — строка или null.
  • action_url — путь внутри кабинета, куда ведёт уведомление, либо null (уведомление чисто информационное, открывать нечего). Путь относительный, без домена, и может отличаться у разных получателей одного и того же события: например, у пропущенного звонка (call_missed) со связанным диалогом это всегда сам диалог (/chat?conversation_id=...), а без диалога — очередь перезвона на пульте (/telephony?tab=console&callback=...) для тех, кто может управлять телефонией (право company_telephony.manage), и журнал звонков (/chat?filter=calls&call_id=...) для остальных.
  • group_key — ключ схлопывания однотипных уведомлений (например, несколько пропущенных звонков одного контакта обновляют одну строку вместо того, чтобы плодить новые), либо null.
  • data — объект с полями, зависящими от type (например, deal_id/deal_title для deal_assigned, call_id/contact_id/conversation_id/missed_last_hour для call_missed; у task_* — deal_task_id, deal_id, company_id, assigned_user_id, unassigned, плюс task_title/assigned_by у task_assigned и count/last_deal_task_id у task_reminder_unassigned; у lead_unsorted — count, funnel_id, last_deal_id, у lead_cap_reached — limit).
  • read_at — ISO-время прочтения или null, если не прочитано.
  • expires_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|all (по умолчанию — все; иное значение отклоняется с 422), category (одно из значений category, см. выше; неизвестное — 422), categories[] (несколько значений category сразу, например categories[]=deals&categories[]=tasks; сочетается с category по И), q (поиск без учёта регистра по title и body, 2–100 символов; % и _ ищутся буквально) и per_page (размер страницы, 1–100, по умолчанию 20). Обратите внимание на snake_case per_page (не perPage). Уведомления с истёкшим expires_at не попадают ни в список, ни в счётчик.

Платформенные уведомления (`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} либо null — null, если канал с тех пор удалён; событие само по себе не исчезает вместе с каналом), 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|all`, `category`, `categories[]`, `q` (2–100 символов), `per_page` (1–100, по умолчанию 20).

GET/v1/notifications/unread-count

Число непрочитанных уведомлений пользователя в активной компании. Ответ: `{ "count": N, "critical": M, "by_category": { "<category>": n } }` — `critical` считает только непрочитанные с `severity: "critical"`; `by_category` — непрочитанные по разделам, только с n>0 (`{}`, если непрочитанных нет).

POST/v1/notifications/{notification}/read

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

POST/v1/notifications/{notification}/unread

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

POST/v1/notifications/bulk

Массово отметить уведомления: тело `{ "ids": [uuid, ...] (1–100), "action": "read"|"unread" }`. Ответ: `{ "updated": n }`; id других пользователей и компаний молча игнорируются.

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",
      "type": "deal_assigned",
      "category": "deals",
      "severity": "info",
      "title": "You were assigned to deal \"Website redesign\"",
      "body": "Assigned by Aigerim",
      "action_url": "/deals/42",
      "group_key": null,
      "data": {
        "deal_id": 42,
        "deal_title": "Website redesign",
        "assigned_by": 3
      },
      "read_at": null,
      "expires_at": null,
      "created_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,
  "critical": 1,
  "by_category": { "deals": 2, "tasks": 1 }
}

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

Запрос

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/3f1e6a20-0c7b-4a9e-b2d1-8a5c1e000001/unread" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Ответ

json
{
  "status": "ok"
}

Массовая отметка уведомлений

Запрос

bash
curl -X POST "https://api.aisar.app/v1/notifications/bulk" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ids": ["3f1e6a20-0c7b-4a9e-b2d1-8a5c1e000001", "3f1e6a20-0c7b-4a9e-b2d1-8a5c1e000002"], "action": "read"}'

Ответ

json
{
  "updated": 2
}

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

Запрос

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 }
  }
}