> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/No-Country-simulation/S02-26-Equipo-33-Web-App/llms.txt
> Use this file to discover all available pages before exploring further.

# Unread Count

> Get the total number of unread messages for the authenticated user

## Overview

The unread count endpoint returns the total number of unread messages across all conversations for the authenticated user. This is useful for displaying notification badges in your application's UI.

## Authentication

This endpoint requires authentication via JWT token in the `Authorization` header.

```
Authorization: Bearer <your_jwt_token>
```

***

## Get Unread Count

<RequestExample>
  ```bash cURL theme={null}
  curl https://api.horsetrust.com/api/chat/unread-count \
    -H "Authorization: Bearer <token>"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.horsetrust.com/api/chat/unread-count', {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });

  const data = await response.json();
  console.log(`You have ${data.unread_count} unread messages`);
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      'https://api.horsetrust.com/api/chat/unread-count',
      headers={'Authorization': f'Bearer {token}'}
  )

  data = response.json()
  print(f"You have {data['unread_count']} unread messages")
  ```

  ```swift Swift theme={null}
  let url = URL(string: "https://api.horsetrust.com/api/chat/unread-count")!
  var request = URLRequest(url: url)
  request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")

  let (data, _) = try await URLSession.shared.data(for: request)
  let response = try JSONDecoder().decode(UnreadCountResponse.self, from: data)
  print("You have \(response.unread_count) unread messages")
  ```
</RequestExample>

<ResponseExample>
  ```json Success Response theme={null}
  {
    "success": true,
    "unread_count": 5
  }
  ```

  ```json No Unread Messages theme={null}
  {
    "success": true,
    "unread_count": 0
  }
  ```

  ```json Error Response theme={null}
  {
    "success": false,
    "message": "Server error"
  }
  ```
</ResponseExample>

### GET `/api/chat/unread-count`

Returns the total number of unread messages for the authenticated user across all their conversations.

### Response Fields

<ResponseField name="success" type="boolean" required>
  Indicates if the request was successful
</ResponseField>

<ResponseField name="unread_count" type="number" required>
  Total number of unread messages across all conversations. Returns `0` if there are no unread messages.
</ResponseField>

<ResponseField name="message" type="string">
  Error message (only present when success is false)
</ResponseField>

### How It Works

The endpoint:

1. Finds all conversations where the authenticated user is a participant
2. Counts all messages in those conversations where:
   * The sender is NOT the authenticated user
   * The `is_read` field is `false`
3. Returns the total count

### Error Responses

* **401 Unauthorized**: Missing or invalid authentication token
* **500 Internal Server Error**: Server error occurred

***

## Usage Examples

### Display Notification Badge

```javascript React theme={null}
import { useEffect, useState } from 'react';

function NotificationBadge() {
  const [unreadCount, setUnreadCount] = useState(0);
  
  useEffect(() => {
    async function fetchUnreadCount() {
      const response = await fetch('https://api.horsetrust.com/api/chat/unread-count', {
        headers: {
          'Authorization': `Bearer ${localStorage.getItem('jwt_token')}`
        }
      });
      
      const data = await response.json();
      if (data.success) {
        setUnreadCount(data.unread_count);
      }
    }
    
    // Fetch on mount
    fetchUnreadCount();
    
    // Poll every 30 seconds
    const interval = setInterval(fetchUnreadCount, 30000);
    
    return () => clearInterval(interval);
  }, []);
  
  if (unreadCount === 0) return null;
  
  return (
    <div className="notification-badge">
      {unreadCount > 99 ? '99+' : unreadCount}
    </div>
  );
}
```

### Real-time Updates with Socket.io

For better user experience, combine the unread count endpoint with Socket.io message notifications:

```javascript theme={null}
import { io } from 'socket.io-client';

let unreadCount = 0;

// Initialize Socket.io
const socket = io('https://api.horsetrust.com', {
  auth: { token: localStorage.getItem('jwt_token') }
});

// Get initial count on load
async function initializeUnreadCount() {
  const response = await fetch('https://api.horsetrust.com/api/chat/unread-count', {
    headers: {
      'Authorization': `Bearer ${localStorage.getItem('jwt_token')}`
    }
  });
  
  const data = await response.json();
  if (data.success) {
    unreadCount = data.unread_count;
    updateBadge(unreadCount);
  }
}

// Increment count on new message notification
socket.on('message_notification', (notification) => {
  unreadCount++;
  updateBadge(unreadCount);
  
  // Show system notification
  new Notification('New message', {
    body: notification.preview
  });
});

// Decrement count when user reads messages
function onConversationOpened(conversationId) {
  // When user opens a conversation and reads messages,
  // fetch updated unread count
  initializeUnreadCount();
}

function updateBadge(count) {
  const badge = document.getElementById('unread-badge');
  if (count > 0) {
    badge.textContent = count > 99 ? '99+' : count;
    badge.style.display = 'block';
  } else {
    badge.style.display = 'none';
  }
}

initializeUnreadCount();
```

### Mobile App Integration

```swift Swift theme={null}
import Foundation

class ChatService {
    private let baseURL = "https://api.horsetrust.com"
    private var token: String
    
    init(token: String) {
        self.token = token
    }
    
    func getUnreadCount() async throws -> Int {
        let url = URL(string: "\(baseURL)/api/chat/unread-count")!
        var request = URLRequest(url: url)
        request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
        
        let (data, _) = try await URLSession.shared.data(for: request)
        let response = try JSONDecoder().decode(UnreadCountResponse.self, from: data)
        
        if response.success {
            return response.unreadCount
        } else {
            throw ChatError.serverError(response.message ?? "Unknown error")
        }
    }
    
    func updateBadge() async {
        do {
            let count = try await getUnreadCount()
            await MainActor.run {
                UIApplication.shared.applicationIconBadgeNumber = count
            }
        } catch {
            print("Failed to update badge: \(error)")
        }
    }
}

struct UnreadCountResponse: Codable {
    let success: Bool
    let unreadCount: Int
    let message: String?
    
    enum CodingKeys: String, CodingKey {
        case success
        case unreadCount = "unread_count"
        case message
    }
}

enum ChatError: Error {
    case serverError(String)
}
```

***

## Best Practices

### Polling Strategy

<AccordionGroup>
  <Accordion title="How often should I poll?">
    The recommended polling interval depends on your use case:

    * **Active chat view**: Poll every 10-30 seconds
    * **Background/other views**: Poll every 1-2 minutes
    * **Mobile apps**: Poll when app comes to foreground

    Always combine with Socket.io for real-time updates when possible to reduce unnecessary API calls.
  </Accordion>

  <Accordion title="Reducing API calls">
    To minimize server load and improve performance:

    1. Use Socket.io's `message_notification` event to increment the count client-side
    2. Only fetch the actual count periodically or when the user opens the app
    3. Store the count in local state and update it optimistically
    4. Reset the count when users read messages (mark them as read)
  </Accordion>

  <Accordion title="Handling errors">
    If the unread count request fails:

    * Keep showing the last known count
    * Don't show "0" as it may be misleading
    * Retry with exponential backoff
    * Show a visual indicator if the count is stale
  </Accordion>
</AccordionGroup>

### Optimistic Updates

Update the count optimistically when users interact with messages:

```javascript theme={null}
// When user opens a conversation with N unread messages
function onConversationOpened(conversation) {
  const unreadInThisConversation = conversation.messages.filter(
    msg => !msg.is_read && msg.sender_id !== currentUserId
  ).length;
  
  // Optimistically decrease the count
  setUnreadCount(prev => Math.max(0, prev - unreadInThisConversation));
  
  // The actual read status is updated server-side when fetching messages
}

// When user receives a new message notification
socket.on('message_notification', () => {
  // Optimistically increase the count
  setUnreadCount(prev => prev + 1);
});

// Periodically sync with server to fix any drift
setInterval(async () => {
  const response = await fetch('/api/chat/unread-count', {
    headers: { 'Authorization': `Bearer ${token}` }
  });
  const data = await response.json();
  if (data.success) {
    setUnreadCount(data.unread_count); // Sync with server truth
  }
}, 60000); // Every minute
```

***

## Related Endpoints

* [Get Messages](/api/chat/messages#get-messages) - Fetching messages automatically marks them as read
* [List Conversations](/api/chat/conversations#list-conversations) - See which conversations have unread messages via `last_message.is_read`
* [Socket.io Events](/api/chat/messages#message-notifications) - Real-time message notifications

***

## Implementation Checklist

<Steps>
  <Step title="Initial Load">
    Fetch the unread count when your application loads to display the initial badge state.
  </Step>

  <Step title="Socket.io Integration">
    Listen to `message_notification` events to increment the count in real-time when new messages arrive.
  </Step>

  <Step title="Optimistic Updates">
    Decrease the count optimistically when users open conversations and read messages.
  </Step>

  <Step title="Periodic Sync">
    Poll the endpoint periodically (every 1-2 minutes) to sync with the server and correct any client-side drift.
  </Step>

  <Step title="Error Handling">
    Handle network errors gracefully by keeping the last known count and retrying with exponential backoff.
  </Step>
</Steps>
