room:read
Description: Mark a room as read up to a specific timestamp.
This endpoint marks comments in a room as read for the authenticated person. Comments created after the provided timestamp remain unread, enabling precise control over read state without losing track of genuinely new messages.
If no timestamp is provided, all comments up to the current time are marked as read.
Request Schema
{
"payload": {
"type": "room:read",
"room_id": 9415,
"read_at": "2026-04-15T15:38:28Z"
},
"signature": "payload_ed25519_hex_signature",
"source_public_key": "your_client_public_key"
}
Request Attributes
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
room_id | Integer | Yes | - | The unique identifier of the room to mark as read |
read_at | String | No | Current time | ISO 8601 timestamp up to which comments are marked as read. Comments after this time remain unread. |
Authentication Behavior
This endpoint follows Pattern A: Full Account Access.
All authentication methods can mark rooms as read, but only rooms where the authenticated person is a participant or creator can be accessed.
Error Handling
The read operation is processed asynchronously. Check the message status for errors:
- Record not found: Room does not exist or is not accessible to the authenticated person
-
Validation failed: Invalid
room_idorread_atformat - Authorization failed: Person is not a participant in the room
- General error: Unexpected processing error
Message status will be set to failed with error details in these cases.
Response Schema
{
"source_public_key": "community_public_key",
"source_site": {
"protocol": "https",
"fqdn": "arkipel.localhost:3000"
},
"created_at": "2025-04-15T15:38:30Z",
"signature": "8b6392d5550605bd6ccddf9c21ebec470de4b44e4b4deb746076e37ab61c5346e07e7c7c7cebb5bbee41cdd92a476bcd3f02373d146ec165b31c31fc31c9ce0d",
"payload": {
"message_id": "6916452112f746b2b4cf48c1",
"type": "room:read",
"room_id": 9415,
"read_at": "2026-04-15T15:38:28Z",
"unread_count_before": 3,
"unread_count_after": 0,
"comments_marked_as_read": 3
}
}
Response Attributes
-
payload.message_id- String - The unique identifier for the async processing message. Use this to check the processing status. -
payload.type- String - Always “room:read” -
payload.room_id- Integer - The ID of the room that was marked as read -
payload.read_at- String - The timestamp up to which comments were marked as read -
payload.unread_count_before- Integer - The number of unread comments before this operation -
payload.unread_count_after- Integer - The number of unread comments remaining after this operation -
payload.comments_marked_as_read- Integer - The number of comments actually marked as read
Processing Status
After receiving the response, poll the message status using the message_id to determine if the read operation succeeded:
-
queued- Message is waiting to be processed -
processing- Message is currently being processed -
persisted- Room was successfully marked as read -
failed- An error occurred (check error details)
Real Life Examples
Mark all comments as read (up to current time)
{
"type": "room:read",
"room_id": 9415
}
Mark comments as read up to specific timestamp
{
"type": "room:read",
"room_id": 9415,
"read_at": "2026-04-15T15:38:28Z"
}
This marks all comments posted at or before 2026-04-15T15:38:28Z as read. Any comments posted after that timestamp remain unread.
Error Responses
Room Not Found
{
"source_public_key": "community_public_key",
"source_site": {
"protocol": "https",
"fqdn": "arkipel.localhost:3000"
},
"created_at": "2025-04-15T15:38:30Z",
"signature": "...",
"payload": {
"type": "room:read",
"room_id": 99999
},
"error": "Room not found with id: 99999",
"status": "not_found"
}
Not a Participant (Forbidden)
{
"source_public_key": "community_public_key",
"source_site": {
"protocol": "https",
"fqdn": "arkipel.localhost:3000"
},
"created_at": "2025-04-15T15:38:30Z",
"signature": "...",
"payload": {
"type": "room:read",
"room_id": 123
},
"error": "Forbidden: You are not a participant in this room",
"status": "forbidden"
}
Missing Room ID
{
"source_public_key": "community_public_key",
"source_site": {
"protocol": "https",
"fqdn": "arkipel.localhost:3000"
},
"created_at": "2025-04-15T15:38:30Z",
"signature": "...",
"payload": {
"type": "room:read"
},
"error": "Missing required field: room_id",
"status": "bad_request"
}
Invalid Timestamp Format
{
"source_public_key": "community_public_key",
"source_site": {
"protocol": "https",
"fqdn": "arkipel.localhost:3000"
},
"created_at": "2025-04-15T15:38:30Z",
"signature": "...",
"payload": {
"type": "room:read",
"room_id": 123,
"read_at": "invalid-timestamp"
},
"error": "Invalid timestamp format for 'read_at'. Use ISO 8601 format (e.g., 2026-04-15T15:38:28Z)",
"status": "bad_request"
}
Usage Notes
- This is a persistent mutation - a message is created and processed asynchronously
- The
read_attimestamp enables partial read scenarios (e.g., “I read up to this point, but anything after is new”) - If
read_atis not provided, all existing comments in the room are marked as read - You must be a participant in the room to mark it as read
- Marking a room as read also marks all notifications for that room as read
- The
comments_marked_as_readcount in the response reflects how many comments were actually affected - Use this endpoint in combination with
inbox:queryto build a complete inbox workflow:- Query inbox to get unread rooms and comments
- Display comments to the user
- Call
room:readwhen user has “read” the comments - Re-query inbox to refresh the view