Batch unread message counts per room for a set of users
Returns, for each requested user, how many unread messages they have per chat room in the target app. Built for backend / CRON flows - e.g. a scheduled "you have unread messages" digest email - where your backend iterates its own users and asks Ethora for their unread state.
Why POST, not GET: the input is an array of user ids, which would not fit reliably in a query string. The call is otherwise a plain synchronous read - it returns the counts immediately, nothing is queued or processed in the background.
How unread is derived (read-only, no client change required): per room, a cutoff is chosen as the user's lastViewed marker for that room (persisted by the chat clients in ejabberd private storage), or - if the user never opened the room - the time they were added to it. Unread = messages in that room newer than the cutoff, excluding the user's own. Messages are counted from the Mongo archive (*_chat_archive.messages, the same store as /messages/search), so this load never touches the live XMPP database.
Modes:
- count (default): exact per-room counts, each bounded by cap (a room with more than cap unread reports cap with capped: true, i.e. "99+").
- flag: skips exact counting and only reports whether each room has any unread (unreadCount collapses to 1). Cheapest option for very large / hot deployments.
Scope & limits: all userIds must belong to appId. Identifiers may be a user's uuid, Mongo _id, or xmppUsername. Max 200 users per request - split larger runs into multiple calls. Ids that don't resolve to a user in the app are returned in notFound rather than failing the request.
Accuracy note: this is a best-effort count for nudge/notification use. It can differ slightly from the in-app badge (which zeroes the active room live and is multi-device-synced only on app open). For a periodic digest that difference is immaterial.
Request
- Base URL: https://api.chat.ethora.com
- URL: https://api.chat.ethora.com/v2/apps/{appId}/users/unread-counts
- Auth: one of:
- HTTP bearer
- HTTP bearer
Path parameters
Target App ID. Must be an app the calling actor owns or has been delegated access to.
Request body
Response
Per-user unread breakdown. Rooms with zero unread are omitted from each user's rooms array.
{
appId: string,
mode: 'count' | 'flag',
cap: number,
markerSource: 'private-storage' | 'membership-fallback',
results: [
{
userId: string, // the identifier you passed in
uuid: string | null,
xmppUsername: string | null,
total: number, // sum of per-room unreadCount
hasUnread: boolean,
unreadRoomCount: number,
capped: boolean, // any room hit the cap
rooms: [
{ chatId: string, unreadCount: number, capped: boolean }
]
}
],
notFound: string[] // ids that didn't resolve to a user
}
Changes
No recorded changes to this operation across all 1 revision of this API.