# Mark as Read
> Source: /api-reference/members/notifications/mark-read
> Mark a specific notification as read
> Endpoint: PATCH /members/me/notifications/{id}/read

## Overview [#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 [#authentication]

Requires a valid Clerk JWT token in the Authorization header.

## Path Parameters [#path-parameters]

<ParamField path="id" type="number" required>
  Notification ID to mark as read
</ParamField>

<RequestExample>

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

```typescript TypeScript
const notificationId = 1234;
const response = await fetch(`http://localhost:3000/v1/members/me/notifications/${notificationId}/read`, {
  method: 'PATCH',
  headers: {
    'Authorization': 'Bearer YOUR_CLERK_JWT'
  }
});

const notification = await response.json();
```

</RequestExample>

## Response [#response]

Returns the updated notification object with the same structure as individual notification items from [Get Notifications](/api-reference/members/notifications/get-notifications).

<ResponseField name="id" type="number" required>
  Notification ID
</ResponseField>

<ResponseField name="type" type="string" required>
  Notification type
</ResponseField>

<ResponseField name="title" type="string">
  Notification title
</ResponseField>

<ResponseField name="message" type="string">
  Notification message
</ResponseField>

<ResponseField name="messageParts" type="object">
  Structured message parts
</ResponseField>

<ResponseField name="isRead" type="boolean" required>
  Read status (will be true after marking as read)
</ResponseField>

<ResponseField name="isWallet" type="boolean" required>
  Whether this is a wallet-related notification
</ResponseField>

<ResponseField name="metadata" type="object">
  Additional notification metadata
</ResponseField>

<ResponseField name="createdAt" type="string" required>
  ISO 8601 timestamp when notification was created
</ResponseField>

<ResponseField name="updatedAt" type="string" required>
  ISO 8601 timestamp when notification was last updated (updated when marked as read)
</ResponseField>

<ResponseField name="readAt" type="string">
  ISO 8601 timestamp when notification was marked as read (set to current time)
</ResponseField>

<ResponseExample>

```json 200 Response - Successfully Marked as Read
{
  "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"
}
```

```json 404 Response - Not Found
{
  "statusCode": 404,
  "message": "Notification not found"
}
```

</ResponseExample>

## Behavior [#behavior]

### Read Status Update [#read-status-update]
- **isRead**: Changes from false to true
- **readAt**: Set to current timestamp
- **updatedAt**: Updated to current timestamp

### Already Read [#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 [#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 [#use-cases]

### Individual Notification Read [#individual-notification-read]
```typescript
// 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 [#bulk-read-operations]
```typescript
// 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-read-on-view]
```typescript
// 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 [#impact-on-other-endpoints]

### Unread Count [#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 [#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

## Related Endpoints [#related-endpoints]

- [Mark as Unread](/api-reference/members/notifications/mark-unread) - Mark notification as unread
- [Get Unread Count](/api-reference/members/notifications/get-unread-count) - Check updated count
- [Get Notifications](/api-reference/members/notifications/get-notifications) - View updated notification list
