Journey Docs
Members APINotifications

Mark as Read

Mark a specific notification as read

PATCH/members/me/notifications/{id}/read

Overview

Marks a specific notification as read for the authenticated member. This updates the notification's read status and timestamp, affecting the unread count and filtering.

Authentication

Requires a valid Clerk JWT token in the Authorization header.

Path Parameters

idpathnumberrequired

Notification ID to mark as read

Request

curl -X PATCH "http://localhost:3000/v1/members/me/notifications/1234/read" \
  -H "Authorization: Bearer YOUR_CLERK_JWT"

Response

Returns the updated notification object with the same structure as individual notification items from Get Notifications.

idnumberrequired

Notification ID

typestringrequired

Notification type

titlestring

Notification title

messagestring

Notification message

messagePartsobject

Structured message parts

isReadbooleanrequired

Read status (will be true after marking as read)

isWalletbooleanrequired

Whether this is a wallet-related notification

metadataobject

Additional notification metadata

createdAtstringrequired

ISO 8601 timestamp when notification was created

updatedAtstringrequired

ISO 8601 timestamp when notification was last updated (updated when marked as read)

readAtstring

ISO 8601 timestamp when notification was marked as read (set to current time)

Response

{
  "id": 1234,
  "type": "wallet",
  "title": "Points Earned",
  "message": "You earned 2,500 points from your recent stay at Luxury Resort Bali",
  "messageParts": {
    "action": "points_earned",
    "amount": 2500,
    "source": "reservation",
    "propertyName": "Luxury Resort Bali"
  },
  "isRead": true,
  "isWallet": true,
  "metadata": {
    "reservationId": "550e8400-e29b-41d4-a716-446655440000",
    "propertyId": "prop_luxury_resort_bali",
    "pointsType": "VALID"
  },
  "createdAt": "2024-04-20T10:30:00Z",
  "updatedAt": "2024-04-20T16:45:00Z",
  "readAt": "2024-04-20T16:45:00Z"
}

Behavior

Read Status Update

  • isRead: Changes from false to true
  • readAt: Set to current timestamp
  • updatedAt: Updated to current timestamp

Already Read

  • No Error: Returns 200 even if notification was already read
  • Idempotent: Safe to call multiple times
  • Timestamp: readAt timestamp is updated to the most recent call

Ownership Validation

  • Member Check: Only the notification owner can mark it as read
  • Security: Returns 404 if notification doesn't belong to authenticated member

Use Cases

Individual Notification Read

// Mark notification as read when user clicks/views it
const markNotificationRead = async (notificationId: number) => {
  try {
    const response = await fetch(`/api/members/me/notifications/${notificationId}/read`, {
      method: 'PATCH'
    });
    
    if (response.ok) {
      // Update local state
      updateNotificationInList(notificationId, { isRead: true });
      // Update unread count
      decrementUnreadCount();
    }
  } catch (error) {
    console.error('Failed to mark notification as read:', error);
  }
};

Bulk Read Operations

// Mark multiple notifications as read
const markMultipleAsRead = async (notificationIds: number[]) => {
  const promises = notificationIds.map(id => 
    fetch(`/api/members/me/notifications/${id}/read`, { method: 'PATCH' })
  );
  
  await Promise.allSettled(promises);
  // Refresh notification list and unread count
  refreshNotifications();
};

Auto-Read on View

// Auto-mark as read when notification comes into viewport
const useAutoMarkAsRead = () => {
  const observerRef = useRef();
  
  useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const notificationId = entry.target.getAttribute('data-notification-id');
          const isRead = entry.target.getAttribute('data-is-read') === 'true';
          
          if (!isRead && notificationId) {
            markNotificationRead(parseInt(notificationId));
          }
        }
      });
    });
    
    return () => observer.disconnect();
  }, []);
};

Impact on Other Endpoints

Unread Count

  • Decreased: Marking as read decreases the unread count by 1
  • Immediate: Count is updated immediately
  • Filtered: Affects both general and filtered counts (wallet=true)

Notification List

  • Filtering: Notification will no longer appear in read=false filter
  • Will Appear: Notification will appear in read=true filter
  • Timestamps: Updated readAt and updatedAt reflect the change

On this page