Skip to content
AISARAISAR
REST API

Notifications

In-app notifications (the "bell") are a per-user feed of events addressed to a specific cabinet user (for example, being assigned to a deal or to a deal task). This is the REST side of the same stream that arrives in real time as the notification.created event on the user's personal WebSocket channel: use the socket for the live push and badge, and these endpoints to backfill history on app load, read the unread count, and clear the badge.

Feed scope

The feed is scoped to the current user and their active company (current_company_id): the list, the counter, and "mark all" return only notifications for the active company; marking a single notification read resolves it by the owning user regardless of company.

Notification object

A notification object has these fields:

  • id — a UUID string.
  • type — a snake_case string identifying the notification kind; the platform currently emits deal_assigned and deal_task_assigned, and the set will grow.
  • title — a short heading.
  • body — a string or null.
  • data — an object whose fields depend on type (e.g. deal_id/deal_title for deal_assigned).
  • read_at — the ISO timestamp when read, or null while unread.
  • created_at — when it was created.

List response shape and query parameters

Important about the list response shape: GET /v1/notifications returns the standard Laravel paginator envelope — the array under the data key, with the pagination meta fields (current_page, per_page, total, last_page, next_page_url, etc.) sitting flat at the top level. This differs from most REST groups, where a list comes back as data:{ items, pagination }.

Query parameters: filter=unread (return only unread; any other value or omitting it returns all) and per_page (page size, default 20). Note the snake_case per_page (not perPage).

Platform notifications (`GET /platform-notifications`)

GET /platform-notifications (2026-08-24) — not to be confused with the personal "bell" feed above: this is a company-scoped (not per-user) flat log of technical notices from the AISAR platform itself (currently only "channel disconnected", from NotifyChannelDisconnectedJob), replacing the old service-conversation mechanic in chat. It requires the conversation.view permission (the same one the /conversations family uses), the feed window is the last 90 days, newest first, page-based pagination (page/limit, limit 1-50, default 20; a pagination block {page, perPage, total, lastPage}). Rate limit: 120 requests per minute.

A list item: id, kind (the notification type, e.g. channel_disconnected), reason (a human-readable cause, or null), created_at, channel ({id, name, type} or nullnull once the channel has since been deleted; the event itself survives), conversation_id and message_id (kept for backward compatibility with notifications inherited from the old mechanic; null on new rows). The feed has no per-item "read" mark — instead, PATCH /me/ui-preferences with aisar_notifications.seen_until (an ISO datetime or null) advances the unseen-cursor consumed by the counters.aisar_notifications key in the Conversations group (GET /conversations/counters).

Endpoints

MethodPath
GET/v1/notifications

The user's notification feed in the active company (Laravel paginator envelope). Params: `filter=unread`, `per_page` (default 20).

GET/v1/notifications/unread-count

Count of the user's unread notifications in the active company. Response: `{ "count": N }`.

POST/v1/notifications/{notification}/read

Mark a single notification read (by its UUID). Response: `{ "status": "ok" }`; 404 if the notification is missing or owned by another user.

POST/v1/notifications/read-all

Mark all of the user's unread notifications in the active company as read. Response: `{ "status": "ok" }`.

GET/v1/platform-notifications

Company-scoped log of platform notifications (e.g. "channel disconnected") over the last 90 days.

Examples

List unread notifications

Request

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"

Response

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
}

Unread count

Request

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

Response

json
{
  "count": 3
}

Mark one notification read

Request

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"

Response

json
{
  "status": "ok"
}

Mark all read

Request

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

Response

json
{
  "status": "ok"
}

Platform notification log

Request

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

Response

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