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
idstring (uuid)Unique identifier for the notification.
entity_idstring (uuid) or nullThe id of the record the notification is about, such as a work item.
entity_namestringThe kind of record, for example
issuefor a work item,intakefor an intake work item,page,initiative, orteamspace.project_idstring (uuid) or nullThe project the record belongs to, or
nullfor a record outside a project.titlestringThe notification's text, for example
Priya Shah has mentioned you in a comment in issue Fix login redirect loop.messagestring or nullA plain-text body. Many notifications carry their text in
titleonly and returnnullhere.message_htmlstringAn HTML body.
<p></p>when the notification has none.senderstringThe event that produced the notification, as a colon-separated string such as
in_app:issue_activities:mentionedorin_app:issue_activities:assigned.is_mentionbooleanWhether the notification is an @-mention of you.
read_atstring (date-time) or nullWhen you read it.
nullwhile unread.archived_atstring (date-time) or nullWhen you archived it.
nullfor an active notification.snoozed_tillstring (date-time) or nullThe time the notification is snoozed until, or
null.dataobject or nullContext 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,
issueholds the work item'sid,name, projectidentifier,sequence_id,state_name,state_group, andtype_id.issue_activityholds the change that triggered the notification. For a comment,issue_activity.issue_commentholds the comment's plain text.triggered_by_idstring (uuid) or nullThe user whose action produced the notification.
created_atstring (date-time)When the notification was created.
updated_atstring (date-time)When the notification was last updated.
{
"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
| Method | Path | Description |
|---|---|---|
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=issuefor v1's set. entity_identifieris nowentity_id. The inlinetriggered_byobject is nowtriggered_by_id, with?expand=triggered_byfor the user object.- Reads add
archived_at,snoozed_till, andupdated_at. - Four filters are renamed.
mentionedis nowis_mention,typeistrigger_type,triggered_byistriggered_by_id, andproject_slugisproject_identifier. An unknowntrigger_typereturns400, where v1 ignored an unknowntype. ?archived=keeps v1's default of active notifications only. A get by id now applies the same default, so an archived notification returns404unless 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.

