## Mark a chat as unread `chats.mark_unread(strchat_id, ChatMarkUnreadParams**kwargs) -> Chat` **post** `/v1/chats/{chatID}/unread` Mark a chat as unread, optionally from a specific message ID. ### Parameters - `chat_id: str` Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available. - `message_id: Optional[str]` Optional message ID to mark unread from. ### Returns - `class Chat: …` - `id: str` Unique identifier of the chat across Beeper. - `account_id: str` Account ID this chat belongs to. - `network: str` Display-only human-readable account/network name. - `participants: Participants` Chat participants information. - `has_more: bool` True if there are more participants than included in items. - `items: List[ParticipantsItem]` Participants returned for this chat (limited by the request; may be a subset). - `is_admin: Optional[bool]` True if this participant has admin privileges in the chat. - `is_network_bot: Optional[bool]` True if this participant represents a network or bridge bot. - `is_pending: Optional[bool]` True if this participant has been invited but has not joined yet. - `total: int` Total number of participants in the chat. - `title: str` Display title of the chat as computed by the client/server. - `type: Literal["single", "group"]` Chat type: 'single' for direct messages, 'group' for group chats. - `"single"` - `"group"` - `unread_count: int` Number of unread messages. - `capabilities: Optional[Capabilities]` Chat capabilities reported by the platform. - `allowed_reactions: Optional[List[str]]` Allowed Unicode reactions. Omitted means all emoji reactions are allowed. - `archive: Optional[bool]` True if archive/unarchive is supported. - `attachments: Optional[Dict[str, CapabilitiesAttachments]]` Supported attachment message types and their per-type constraints, keyed by Matrix msgtype or pseudo-msgtype (for example m.image, m.video, org.matrix.msc3245.voice). Missing message types should be treated as rejected. - `mime_types: Dict[str, Literal[-2, -1, 0, 2 more]]` Supported MIME types or MIME patterns for this file message type. Missing MIME types should be treated as rejected. - `-2` - `-1` - `0` - `1` - `2` - `caption: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `max_caption_length: Optional[int]` Maximum caption length when captions are supported. - `max_duration: Optional[int]` Maximum audio or video duration in seconds. - `max_height: Optional[int]` Maximum image or video height in pixels. - `max_size: Optional[int]` Maximum file size in bytes. - `max_width: Optional[int]` Maximum image or video width in pixels. - `view_once: Optional[bool]` True if this file type can be sent as view-once media. - `custom_emoji_reactions: Optional[bool]` True if custom emoji reactions are supported. - `delete: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `delete_chat: Optional[bool]` True if deleting chats for the authenticated user is supported. - `delete_chat_for_everyone: Optional[bool]` True if deleting chats for everyone is supported. - `delete_for_me: Optional[bool]` True if deleting messages only for the authenticated user is supported. - `delete_max_age: Optional[int]` Maximum message age for delete-for-everyone, in seconds. - `disappearing_timer: Optional[CapabilitiesDisappearingTimer]` Disappearing-message timer capabilities. - `omit_empty_timer: Optional[bool]` True if empty timer objects should be omitted from message content. - `timers: Optional[List[int]]` Allowed disappearing timer values in milliseconds. Omitted means any timer is allowed. - `types: Optional[List[Literal["afterRead", "afterSend"]]]` Supported disappearing timer types. - `"afterRead"` - `"afterSend"` - `edit: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `edit_max_age: Optional[int]` Maximum message age for edits, in seconds. - `edit_max_count: Optional[int]` Maximum number of edits allowed for one message. - `formatting: Optional[Dict[str, Literal[-2, -1, 0, 2 more]]]` Supported rich-text formatting features keyed by feature name (for example bold, inline_code, code_block.syntax_highlighting). Omitted means no formatting support is advertised. - `-2` - `-1` - `0` - `1` - `2` - `location_message: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `mark_as_unread: Optional[bool]` True if marking chats unread is supported. - `max_text_length: Optional[int]` Maximum length of normal text messages. - `message_request: Optional[CapabilitiesMessageRequest]` Message request capabilities. - `accept_with_button: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `accept_with_message: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `participant_actions: Optional[CapabilitiesParticipantActions]` Participant management capabilities. - `ban: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `invite: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `kick: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `leave: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `revoke_invite: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `poll: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `reaction: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `reaction_count: Optional[int]` Maximum number of reactions allowed on a single message. - `read_receipts: Optional[bool]` True if read receipts are supported. - `reply: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `state: Optional[CapabilitiesState]` Chat state update capabilities. - `avatar: Optional[CapabilitiesStateAvatar]` Chat avatar state capability. - `level: Literal[-2, -1, 0, 2 more]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `description: Optional[CapabilitiesStateDescription]` Chat description/topic state capability. - `level: Literal[-2, -1, 0, 2 more]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `disappearing_timer: Optional[CapabilitiesStateDisappearingTimer]` Disappearing-message timer state capability. - `level: Literal[-2, -1, 0, 2 more]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `title: Optional[CapabilitiesStateTitle]` Chat title state capability. - `level: Literal[-2, -1, 0, 2 more]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `thread: Optional[Literal[-2, -1, 0, 2 more]]` -2: rejected, -1: dropped, 0: unsupported, 1: partially supported, 2: fully supported. - `-2` - `-1` - `0` - `1` - `2` - `typing_notifications: Optional[bool]` True if typing notifications are supported. - `description: Optional[str]` Group chat description/topic when available. - `draft: Optional[Draft]` Current draft object for this chat, or null when no draft is set. - `text: str` Matrix HTML draft body. - `attachments: Optional[Dict[str, DraftAttachments]]` Draft attachments keyed by attachment ID. - `id: str` Draft attachment identifier. - `type: Literal["file", "gif", "recorded_audio"]` Draft attachment type. GIF and recorded audio are mutually exclusive types. - `"file"` - `"gif"` - `"recorded_audio"` - `audio_duration_seconds: Optional[float]` Audio duration in seconds if known. - `file_name: Optional[str]` Original filename if available. - `file_path: Optional[str]` Local filesystem path for the draft attachment. - `file_size: Optional[float]` File size in bytes if known. - `mime_type: Optional[str]` MIME type if known. - `size: Optional[DraftAttachmentsSize]` Pixel dimensions of the attachment. - `height: Optional[float]` - `width: Optional[float]` - `sticker_id: Optional[str]` Sticker identifier if the draft attachment is a sticker. - `img_url: Optional[str]` Local filesystem path to the chat avatar image when available. - `is_archived: Optional[bool]` True if chat is archived. - `is_low_priority: Optional[bool]` True if chat is marked low priority. - `is_marked_unread: Optional[bool]` True if the chat was explicitly marked unread by the authenticated user. - `is_muted: Optional[bool]` True if chat notifications are muted. - `is_pinned: Optional[bool]` True if chat is pinned. - `is_read_only: Optional[bool]` True if messages cannot be sent in this chat. - `last_activity: Optional[datetime]` Timestamp of last activity. - `last_read_message_sort_key: Optional[str]` Last read message sortKey. - `local_chat_id: Optional[str]` Local chat ID specific to this Beeper Desktop installation. - `message_expiry_seconds: Optional[int]` Disappearing-message timer in seconds when available. - `reminder: Optional[Reminder]` Current reminder for this chat, or null when no reminder is set. - `dismiss_on_incoming_message: Optional[bool]` Cancel reminder if someone messages in the chat. - `remind_at: Optional[datetime]` Timestamp when the reminder should trigger. - `snooze: Optional[Snooze]` Current snooze state for this chat, or null when no snooze is set. - `snooze_until: Optional[datetime]` Timestamp when the snooze expires. - `user_snoozed_at: Optional[datetime]` Timestamp when the user set the snooze. - `unread_mentions_count: Optional[int]` Number of unread messages that mention the authenticated user or @room. ### Example ```python import os from beeper_desktop_api import BeeperDesktop client = BeeperDesktop( access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted ) chat = client.chats.mark_unread( chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com", ) print(chat.id) ``` #### Response ```json { "id": "!whatsapp_15550101002:ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc.local-whatsapp.localhost", "accountID": "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc", "network": "WhatsApp", "participants": { "hasMore": false, "items": [ { "id": "@15550101002:local-whatsapp.localhost", "cannotMessage": false, "email": "email", "fullName": "Kishan Bagaria", "imgURL": "imgURL", "isSelf": false, "phoneNumber": "+15550101002", "username": "username", "isAdmin": true, "isNetworkBot": true, "isPending": true }, { "id": "@ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc:local-whatsapp.localhost", "cannotMessage": false, "email": "email", "fullName": "Batuhan İçöz", "imgURL": "imgURL", "isSelf": true, "phoneNumber": "phoneNumber", "username": "username", "isAdmin": true, "isNetworkBot": true, "isPending": true } ], "total": 2 }, "title": "Kishan Bagaria", "type": "single", "unreadCount": 0, "capabilities": { "allowedReactions": [ "string" ], "archive": true, "attachments": { "foo": { "mimeTypes": { "foo": -2 }, "caption": -2, "maxCaptionLength": 0, "maxDuration": 0, "maxHeight": 0, "maxSize": 0, "maxWidth": 0, "viewOnce": true } }, "customEmojiReactions": true, "delete": -2, "deleteChat": true, "deleteChatForEveryone": true, "deleteForMe": true, "deleteMaxAge": 0, "disappearingTimer": { "omitEmptyTimer": true, "timers": [ 0 ], "types": [ "afterRead" ] }, "edit": -2, "editMaxAge": 0, "editMaxCount": 0, "formatting": { "foo": -2 }, "locationMessage": -2, "markAsUnread": true, "maxTextLength": 0, "messageRequest": { "acceptWithButton": -2, "acceptWithMessage": -2 }, "participantActions": { "ban": -2, "invite": -2, "kick": -2, "leave": -2, "revokeInvite": -2 }, "poll": -2, "reaction": -2, "reactionCount": 0, "readReceipts": true, "reply": -2, "state": { "avatar": { "level": -2 }, "description": { "level": -2 }, "disappearingTimer": { "level": -2 }, "title": { "level": -2 } }, "thread": -2, "typingNotifications": true }, "description": "description", "draft": { "text": "text", "attachments": { "foo": { "id": "id", "type": "file", "audioDurationSeconds": 0, "fileName": "fileName", "filePath": "filePath", "fileSize": 0, "mimeType": "mimeType", "size": { "height": 0, "width": 0 }, "stickerID": "stickerID" } } }, "imgURL": "imgURL", "isArchived": false, "isLowPriority": true, "isMarkedUnread": true, "isMuted": false, "isPinned": false, "isReadOnly": true, "lastActivity": "2026-05-05T20:11:54.000Z", "lastReadMessageSortKey": "455171049984", "localChatID": "5639", "messageExpirySeconds": 0, "reminder": { "dismissOnIncomingMessage": true, "remindAt": "2025-08-31T23:30:12.520Z" }, "snooze": { "snoozeUntil": "2025-08-31T23:30:12.520Z", "userSnoozedAt": "2025-08-31T23:30:12.520Z" }, "unreadMentionsCount": 0 } ```