Skip to content

Notifications overview ​

A notification is an entry in your Plane inbox, such as a mention, an assignment, or a change on something you're subscribed to. The notifications API returns your own inbox for one workspace, so a bot or agent can poll for the events addressed to it.

The API is read-only, and POST, PATCH, and DELETE return 405. To mark a notification read, archive it, or snooze it, use Plane. Each request returns only the caller's notifications. A notification addressed to someone else returns 404, as if it didn't exist.

The inbox covers every kind of record that sends notifications, not only work items. Filter with ?entity_name=issue for work item notifications only. Archived notifications stay out of results unless you pass ?archived=.

Learn more about notifications

The notification object ​

Attributes ​

  • id string (uuid)

    Unique identifier for the notification.

  • entity_id string (uuid) or null

    The id of the record the notification is about, such as a work item.

  • entity_name string

    The kind of record, for example issue for a work item, intake for an intake work item, page, initiative, or teamspace.

  • project_id string (uuid) or null

    The project the record belongs to, or null for a record outside a project.

  • title string

    The notification's text, for example Priya Shah has mentioned you in a comment in issue Fix login redirect loop.

  • message string or null

    A plain-text body. Many notifications carry their text in title only and return null here.

  • message_html string

    An HTML body. <p></p> when the notification has none.

  • sender string

    The event that produced the notification, as a colon-separated string such as in_app:issue_activities:mentioned or in_app:issue_activities:assigned.

  • is_mention boolean

    Whether the notification is an @-mention of you.

  • read_at string (date-time) or null

    When you read it. null while unread.

  • archived_at string (date-time) or null

    When you archived it. null for an active notification.

  • snoozed_till string (date-time) or null

    The time the notification is snoozed until, or null.

  • data object or null

    Context written when the notification was created, so you can act on it without another request. Its shape depends on the record and isn't fixed by the schema. For a work item, issue holds the work item's id, name, project identifier, sequence_id, state_name, state_group, and type_id. issue_activity holds the change that triggered the notification. For a comment, issue_activity.issue_comment holds the comment's plain text.

  • triggered_by_id string (uuid) or null

    The user whose action produced the notification.

  • created_at string (date-time)

    When the notification was created.

  • updated_at string (date-time)

    When the notification was last updated.

Response200
json
{
  "id": "71f4c2a9-8e3b-4d56-a017-5c9e2b8d4f63",
  "entity_id": "8c3d1f72-4a9e-4b65-9d20-6e1f3b7a5c48",
  "entity_name": "issue",
  "project_id": "4af68566-94a4-4eb3-94aa-50dc9427067b",
  "title": "Priya Shah has mentioned you in a comment in issue Fix login redirect loop",
  "message": null,
  "message_html": "<p></p>",
  "sender": "in_app:issue_activities:mentioned",
  "is_mention": true,
  "read_at": null,
  "archived_at": null,
  "snoozed_till": null,
  "data": {
    "issue": {
      "id": "8c3d1f72-4a9e-4b65-9d20-6e1f3b7a5c48",
      "name": "Fix login redirect loop",
      "identifier": "ENG",
      "sequence_id": 142,
      "state_name": "In Progress",
      "state_group": "started",
      "type_id": "5b7e2d94-1a6c-4f38-9e02-8d4c3b6a1f57"
    },
    "issue_activity": {
      "id": "3f8b6d21-9c4e-4a73-b1d5-7e2a0c9f6b48",
      "verb": "created",
      "field": "comment",
      "actor": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
      "new_value": "@Ravi can you check the redirect on Safari?",
      "old_value": "None",
      "old_identifier": null,
      "new_identifier": null,
      "issue_comment": "@Ravi can you check the redirect on Safari?"
    }
  },
  "triggered_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
  "created_at": "2026-01-14T09:22:41.478363Z",
  "updated_at": "2026-01-14T09:22:41.478363Z"
}

Endpoints ​

MethodPathDescription
GET/api/v2/workspaces/{slug}/notifications/List notifications
GET/api/v2/workspaces/{slug}/notifications/{pk}/Get a notification

Both endpoints need the notifications:read scope.

Polling the inbox ​

Notifications are newest first by default. A simple poll asks for unread, active notifications created since the last run, for example ?read=false&created_at__gte=2026-01-14T09:00:00Z. Because the API can't mark a notification read, store the ids you've processed so a second poll doesn't act on them twice.

Response shaping ​

Every notification read accepts ?fields= for sparse responses and ?expand=triggered_by to embed the user who triggered it. See Sparse fields and Expanding relations. Errors follow the shared problem+json contract.

Changed from v1 ​

  • v2 returns every entity type. v1 returned work item notifications only. Pass ?entity_name=issue for v1's set.
  • entity_identifier is now entity_id. The inline triggered_by object is now triggered_by_id, with ?expand=triggered_by for the user object.
  • Reads add archived_at, snoozed_till, and updated_at.
  • Four filters are renamed. mentioned is now is_mention, type is trigger_type, triggered_by is triggered_by_id, and project_slug is project_identifier. An unknown trigger_type returns 400, where v1 ignored an unknown type.
  • ?archived= keeps v1's default of active notifications only. A get by id now applies the same default, so an archived notification returns 404 unless you pass ?archived=true.
  • Lists use the standard v2 offset envelope, with cursor pagination as an opt-in.

See Migrating from v1 for the full list.