# Notification Tray

{% hint style="info" %}
Notification Tray is currently in Private Beta. Please submit your request to the[**social.plus Help Center**](https://socialplus.atlassian.net/servicedesk/customer/portals) to enable this feature. It will take approximately 5 business days to process your request.
{% endhint %}

The notification tray service is designed to automatically create and group notification records in a notification tray separated by user. The main function of this service is to provide the notification history for each user.

Here's an example of a simple notification tray that we have customized with this service. As shown in the picture, the Notification Tray contains a history of notifications displayed as rows of notification records. Each notification record contains details about a particular notification, including a list of the actors who acted, the action performed (verb), and the target of the action (target).

<figure><img src="/files/Um2jDXhQcl930p2tTeQ6" alt="" width="346"><figcaption></figcaption></figure>

## Concept <a href="#specification" id="specification"></a>

* A notification record consists of actors, a verb, and a target - for example:
  * John Doe and 3 others commented on Sarah Janes's Post
    * **Actors:** John Doe and 3 other users
    * **Verb:** comment
    * **Target:** Sarah Jane's Post
* Notification Tray automatically groups events with the same verb and target together and aggregates a list of actors into the same Notification Record.
* By default, the notification tray displays up to 10 notification records per page, sorted from newest to oldest, using the date of the last update as a reference. All notification records are stored for 90 days from the last update.
* Each notification record displays up to 3 actor names, sorted by the date of record activity, except for mentions. They won't be grouped but shown individually.
* ImageUrl of a notification record is the profile image of the latest actor who acts on the target.
* The notification record expires 90 days after the timestamp of the `lastUpdate` and is then deleted from Notification Tray after expiring.
* When a user leaves a community, the user's notification records are not updated with the target associated with the community. When the user rejoins a community, the notification records are updated again, but events that happened during the time the user left the community are not retroactively reflected in the record.

### Scenarios

The following table shows supported scenarios and Tray Message that is recorded in the Notification Record.

<table><thead><tr><th>Target Type</th><th>Verb</th><th width="121">Scenario</th><th width="247">Tray Message</th><th>Notification Target</th></tr></thead><tbody><tr><td>Post</td><td>post</td><td>A create post on community</td><td><code>{DisplayName A}</code> posted in <code>{CommunityName}</code></td><td>Community's members</td></tr><tr><td></td><td></td><td>A,B create post on community</td><td><code>{DisplayName B}</code> and <code>{DisplayName A}</code> created post in <code>{CommunityName}</code></td><td>Community's members</td></tr><tr><td></td><td></td><td>A,B,C,D create post on community</td><td><code>{DisplayName D}</code>, <code>{DisplayName C}</code> and <code>{2}</code> others posted in {CommunityName}</td><td>Community's members</td></tr><tr><td>Comment</td><td>comment</td><td>B comment on A’s post</td><td>User Feed: <code>{DisplayName B}</code> commented on your post<br>Community Feed:<br><code>{DisplayName B}</code> commented on your post in <code>{CommunityName}</code></td><td>Post owner (User A)</td></tr><tr><td></td><td></td><td>B,C comment on A’s post</td><td><p>User Feed:</p><p><code>{DisplayName C}</code> and <code>{DisplayName B}</code>commented on your post<br>Community Feed:</p><p><code>{DisplayName C}</code> and <code>{DisplayName B}</code> commented on your post in <code>{CommunityName}</code></p></td><td>Post owner (User A)</td></tr><tr><td></td><td></td><td>B,C,D,E comment on A’s post</td><td>User Feed:<br><code>{DisplayName E}</code>, <code>{DisplayName D}</code> and <code>{2}</code>others commented on your post<br>Community Feed:<br><code>{DisplayName E}</code>, <code>{DisplayName D}</code> and <code>{2}</code> others commented on your post in <code>{CommunityName}</code></td><td>Post owner (User A)</td></tr><tr><td>Reply</td><td>mentreply</td><td>B reply on A’s comment</td><td>User Feed: <code>{DisplayName B}</code> has replied to your comment.<br>Community Feed:<br><code>{DisplayName B}</code> has replied to your comment.</td><td>Comment owner (User A)</td></tr><tr><td></td><td></td><td>B, C reply on A’s comment</td><td><p>User Feed:</p><p><code>{DisplayName C}</code> and <code>{DisplayName B}</code> have replied to your comment.<br>Community Feed:</p><p><code>{DisplayName C}</code> and<br><code>{DisplayName B}</code> have replied to your comment.</p></td><td>Comment owner (User A)</td></tr><tr><td></td><td></td><td>B, C, D, E reply on A’s comment</td><td><p>User Feed:</p><p><code>{DisplayName E}</code>, <code>{DisplayName D}</code> and 2 others have replied to your comment.<br>Community Feed:</p><p><code>{DisplayName E}</code>, <code>{DisplayName D}</code> and 2 others have replied to your comment.</p></td><td>Comment owner (User A)</td></tr><tr><td>Reaction</td><td>reaction/mentreact</td><td>B react on A’s post/comment</td><td>User Feed: <code>{DisplayName B}</code> added a reaction to your post/comment<br>Community Feed: <code>{DisplayName B}</code> added a reaction to your post/comment in <code>{CommunityName}</code></td><td>Post/Comment owner (User A)</td></tr><tr><td></td><td></td><td>B,C react on A’s post/comment</td><td>User Feed: <code>{DisplayName C}</code> and <code>{DisplayName B}</code> added reactions to your post/comment<br>Community Feed: <code>{DisplayName C}</code> and <code>{DisplayName B}</code> added reactions to your post/comment in <code>{CommunityName}</code></td><td>Post/Comment owner (User A)</td></tr><tr><td></td><td></td><td>B,C,D,E react on A’s post/comment</td><td>User Feed: <code>{DisplayName E}</code>, <code>{DisplayName D}</code> and <code>{2}</code> others added reactions to your post/comment<br>Community Feed:<code>{DisplayName E}</code>, <code>{DisplayName D}</code> and <code>{2}</code> others added reactions to your post/comment in <code>{CommunityName}</code></td><td>Post/Comment owner (User A)</td></tr><tr><td><a data-footnote-ref href="#user-content-fn-1"><mark style="color:red;">*</mark></a>Mention</td><td>mention</td><td>A mentioned B on A post/comment in a community</td><td><code>{DisplayName A}</code> has mentioned you on a post/comment in <code>{CommunityName}</code></td><td>User B</td></tr><tr><td></td><td></td><td>A mentioned B on A post/comment in a user feed</td><td><code>{DisplayName A}</code> has mentioned you on a post/comment in <code>{DisplayName A}</code> feed</td><td>User B</td></tr></tbody></table>

### Last Read & Has Read

The notification tray supports 2 reading levels as follows:

1. **Last Read**: Update the last read timestamp of the user. This is used to update the total unread count of notification records.
2. **Has Read**: Flag on each notification record that shows whether the user has explicitly read or click the notification record. This is represented as `hasRead` value inside each notification record JSON and can be used to display 'unread dot' on each notification record on Notification Tray.

## GET /notifications/v3

> Get the total unread count of notifications in the user's notification tray.

```json
{"openapi":"3.0.1","info":{"title":"Notification Tray API","version":"1"},"servers":[{"url":"https://beta.amity.services"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"NotificationTotalUnread":{"type":"object","properties":{"data":{"type":"object","properties":{"totalUnreadCount":{"type":"number","description":"Number of total unread notification tray record of the user."}}}}}}},"paths":{"/notifications/v3":{"get":{"summary":"Get the total unread count of notifications in the user's notification tray.","responses":{"200":{"description":"Notification Total Unread Count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationTotalUnread"}}}}}}}}}
```

## GET /notifications/v3/mark-all-as-read

> Mark all the records as read.

```json
{"openapi":"3.0.1","info":{"title":"Notification Tray API","version":"1"},"servers":[{"url":"https://beta.amity.services"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"NotificationMarkAllAsRead":{"type":"object","properties":{"data":{"type":"object","properties":{"message":{"type":"string","description":"Status of process."}}}}}}},"paths":{"/notifications/v3/mark-all-as-read":{"get":{"summary":"Mark all the records as read.","responses":{"200":{"description":"Marked all the records as read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationMarkAllAsRead"}}}}}}}}}
```

## GET /notifications/v3/history

> Retrieve notification records of a user

```json
{"openapi":"3.0.1","info":{"title":"Notification Tray API","version":"1"},"servers":[{"url":"https://beta.amity.services"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"NotificationHistory":{"type":"object","properties":{"totalPages":{"type":"integer","description":"Show how many pages user have."},"nextPage":{"type":"integer","description":"Show the next page timestamp."},"data":{"type":"array","items":{"$ref":"#/components/schemas/NotificationRecord"}}}},"NotificationRecord":{"type":"object","properties":{"v_tarid_uid":{"type":"string","description":"Primarykey of the record."},"description":{"type":"string","description":"Tray Message of the record."},"verb":{"$ref":"#/components/schemas/NotificationVerb"},"imageUrl":{"type":"string","description":"Avatar image of the record"},"avatarCustomUrl":{"type":"string","description":"Avatar image of the record (if last actor use avatarCustomUrl)."},"targetType":{"type":"string","description":"Type of the target","enum":["community","post"]},"targetName":{"type":"string","description":"Name of the target"},"hasRead":{"type":"boolean","description":"Flag indicating whether the user has read the record"},"lastUpdate":{"type":"integer","description":"Timestamp of when the record is last updated"},"actors":{"type":"object","description":"Latest actors (up to 3 actors) who performed the verb on the target.","properties":{"name":{"type":"string","description":"Name of the user"}}},"actorsCount":{"type":"integer","description":"Total count of the actors"},"parentTargetId":{"type":"string","description":"The targetId of Parent incase this record verb = reaction, mentreply, comment."},"targetId":{"type":"string","description":"The targetId of this record."},"lastActionId":{"type":"string","description":"The ID of the last action, which could be postId, commentId, or reactionID, depends on the verb."},"lastActionSegmentNo":{"type":"number","description":"The index of the last action (supported only for comments)."}}},"NotificationVerb":{"type":"string","enum":["post","comment","reaction","mentreply"]}}},"paths":{"/notifications/v3/history":{"get":{"summary":"Retrieve notification records of a user","parameters":[{"name":"startAfter","in":"query","description":"timeStamp of last record of previous page.","required":false,"schema":{"type":"integer","default":1}}],"responses":{"200":{"description":"Notification history JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationHistory"}}}}}}}}}
```

## POST /notifications/v2/last-read

> Update lastRead timestamp of the user

```json
{"openapi":"3.0.1","info":{"title":"Notification Tray API","version":"1"},"servers":[{"url":"https://beta.amity.services"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"NotificationHasRead":{"type":"object","properties":{"data":{"type":"string","description":"Request has succeeded."}}}}},"paths":{"/notifications/v2/last-read":{"post":{"summary":"Update lastRead timestamp of the user","responses":{"200":{"description":"Request has succeeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationHasRead"}}}}}}}}}
```

## POST /notifications/v2/read

> Mark a notification record as read

```json
{"openapi":"3.0.1","info":{"title":"Notification Tray API","version":"1"},"servers":[{"url":"https://beta.amity.services"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"NotificationVerb":{"type":"string","enum":["post","comment","reaction","mentreply"]},"NotificationHasRead":{"type":"object","properties":{"data":{"type":"string","description":"Request has succeeded."}}}}},"paths":{"/notifications/v2/read":{"post":{"summary":"Mark a notification record as read","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"verb":{"$ref":"#/components/schemas/NotificationVerb"},"targetId":{"type":"string"}}}}}},"responses":{"200":{"description":"Request has succeeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationHasRead"}}}}}}}}}
```

## DELETE /notifications/v3/delete-all

> Delete all notification of the user

```json
{"openapi":"3.0.1","info":{"title":"Notification Tray API","version":"1"},"servers":[{"url":"https://beta.amity.services"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"NotificationDeleteAll":{"type":"object","properties":{"data":{"type":"string","description":"Success."}}}}},"paths":{"/notifications/v3/delete-all":{"delete":{"summary":"Delete all notification of the user","responses":{"200":{"description":"Request has succeeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationDeleteAll"}}}}}}}}}
```

## Limitations

* When a user **changes** their display name, the actor's name in Tray Message is not updated.
* **Notification** **Tray** currently **does not support**
  * **Post** on user feed
  * **Grouping** **mention** into one record
* **Customization** of **`description`** is not supported. If customization/localization of notification records is needed we recommend constructing the message at the frontend as notification records already contain all the information needed.

{% hint style="danger" %}

#### Are you still on version 2?

{% endhint %}

Don't worry, Version 2 can still be used, but it won't support the mention feature. So, we highly recommend migrating to v3, and here is the list of changes needed to use Version 3!

<table><thead><tr><th width="185">Breaking Change</th><th width="250.33333333333331">Version 2</th><th>Version 3</th></tr></thead><tbody><tr><td>Pagination</td><td>?page=1</td><td>?startAfter=1692248943383</td></tr><tr><td>Response data</td><td><pre class="language-json"><code class="lang-json">{
    "totalPages": 2,
    "data": [
    .
    .
    .
    ]
}
</code></pre></td><td><pre><code>{
    "totalPages": 2,
    "data": [
    .
    .
    .
    ],
    "nextPage": 1692248943383
}
</code></pre></td></tr></tbody></table>

[^1]: Currently supported on version 3++


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.social.plus/developers/beta-features/notification-tray.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
