Beeper Chats API
Chats, reminders, read state, archive state, priority, mute, and other conversation metadata.
Chats, reminders, read state, archive state, priority, mute, and other conversation metadata.
openapi: 3.1.0
info:
title: Beeper Desktop Accounts Chats API
version: 5.0.0
description: 'Beeper Desktop''s local HTTP and WebSocket API. One auth flow and one chat shape work across WhatsApp, iMessage, Telegram, Slack, Matrix, Discord, Twitter/X, Signal, and more.
Beeper is built on the Matrix standard. Identifiers and rich text use Matrix conventions: `mxc://` and `localmxc://` URLs reference media on the Matrix homeserver and on this device''s local bridge respectively; message text is Matrix HTML on the wire; `@room` is a group-mention sentinel.
## Quickstart
1. Discover the server with `GET /v1/info`. The Desktop API is local-only unless the user has enabled remote access.
2. Authenticate with an access token from Beeper Desktop, or run OAuth2 Authorization Code with PKCE under the OAuth tag.
3. Call `GET /v1/accounts` to see connected Chat Accounts, then `GET /v1/chats` for the unified inbox.
## WebSocket
Connect to `/v1/ws` with the same Bearer token in the upgrade request. Browser `new WebSocket()` clients are not supported yet because browsers cannot set the Authorization header. After the server sends `ready`, send `{"type":"subscriptions.set","chatIDs":["*"]}` to receive every chat update, or pass specific chat IDs. The server replies with `subscriptions.updated`, then streams `chat.upserted`, `chat.deleted`, `message.upserted`, and `message.deleted`.
Delivery is at-most-once. There is no replay on reconnect, and `seq` is per connection. Refetch via HTTP after a disconnect to reconcile drift. Initial subscription state is empty; `subscriptions.set` replaces previous state; `["*"]` cannot be combined with specific chat IDs.
## Conventions
- IDs and cursors are opaque strings.
- Timestamps are ISO 8601 with timezone, except OAuth fields that use Unix seconds per RFC.
- Pagination is `cursor` plus `direction=before|after`.
- Sends return a `pendingMessageID`; resolve it with `GET /v1/chats/{chatID}/messages/{messageID}` or wait for `message.upserted` over the WebSocket.
- Optional fields may be omitted when unknown. Nullable write fields use `null` as an explicit clear operation.
- Every response carries `X-Beeper-Desktop-Version` so clients can tell which app version produced it.'
termsOfService: https://www.beeper.com/terms
contact:
name: Beeper
email: help@beeper.com
url: https://www.beeper.com
license:
name: Proprietary
url: https://www.beeper.com/terms
servers:
- url: http://localhost:23373
description: Beeper Desktop API server
security:
- bearerAuth: []
tags:
- name: Chats
description: Chats, reminders, read state, archive state, priority, mute, and other conversation metadata.
paths:
/v1/chats/search:
get:
summary: Search chats
description: Search chats by title, network, or participant names.
tags:
- Chats
operationId: searchChats
security:
- bearerAuth: []
parameters:
- schema:
type: string
description: Opaque pagination cursor; do not inspect. Use together with 'direction'.
example: 1725489123456|c29tZUltc2dQYWdl
x-stainless-pagination-property:
purpose: next_cursor_param
required: false
description: Opaque pagination cursor; do not inspect. Use together with 'direction'.
name: cursor
in: query
- schema:
type: string
enum:
- after
- before
description: 'Pagination direction used with ''cursor'': ''before'' fetches older results, ''after'' fetches newer results. Defaults to ''before'' when only ''cursor'' is provided.'
example: before
required: false
description: 'Pagination direction used with ''cursor'': ''before'' fetches older results, ''after'' fetches newer results. Defaults to ''before'' when only ''cursor'' is provided.'
name: direction
in: query
- schema:
type: string
enum:
- primary
- low-priority
- archive
description: 'Filter by inbox type: "primary" (non-archived, non-low-priority), "low-priority", or "archive". If not specified, shows all chats.'
required: false
description: 'Filter by inbox type: "primary" (non-archived, non-low-priority), "low-priority", or "archive". If not specified, shows all chats.'
name: inbox
in: query
- schema:
type: boolean
nullable: true
description: Set to true to only retrieve chats that have unread messages
required: false
description: Set to true to only retrieve chats that have unread messages
name: unreadOnly
in: query
- schema:
type: integer
minimum: 1
maximum: 200
default: 50
description: 'Set the maximum number of chats to retrieve. Valid range: 1-200, default is 50'
required: false
description: 'Set the maximum number of chats to retrieve. Valid range: 1-200, default is 50'
name: limit
in: query
- schema:
type: string
enum:
- single
- group
- any
default: any
description: 'Specify the type of chats to retrieve: use "single" for direct messages, "group" for group chats, or "any" to get all types'
required: false
description: 'Specify the type of chats to retrieve: use "single" for direct messages, "group" for group chats, or "any" to get all types'
name: type
in: query
- schema:
type: string
minLength: 1
description: Literal token search (non-semantic). Use single words users type (e.g., "dinner"). When multiple words provided, ALL must match. Case-insensitive.
required: false
description: Literal token search (non-semantic). Use single words users type (e.g., "dinner"). When multiple words provided, ALL must match. Case-insensitive.
name: query
in: query
- schema:
type: string
enum:
- titles
- participants
default: titles
description: 'Search scope: ''titles'' matches title + network; ''participants'' matches participant names.'
required: false
description: 'Search scope: ''titles'' matches title + network; ''participants'' matches participant names.'
name: scope
in: query
- schema:
type: string
format: date-time
description: Provide an ISO datetime string to only retrieve chats with last activity before this time
required: false
description: Provide an ISO datetime string to only retrieve chats with last activity before this time
name: lastActivityBefore
in: query
- schema:
type: string
format: date-time
description: Provide an ISO datetime string to only retrieve chats with last activity after this time
required: false
description: Provide an ISO datetime string to only retrieve chats with last activity after this time
name: lastActivityAfter
in: query
- schema:
type: array
items:
type: string
description: Account ID this resource belongs to.
description: Provide an array of account IDs to filter chats from specific messaging accounts only
example:
- matrix
- discordgo
- local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc
required: false
description: Provide an array of account IDs to filter chats from specific messaging accounts only
name: accountIDs
in: query
- schema:
type: boolean
nullable: true
default: true
description: 'Include chats marked as Muted by the user, which are usually less important. Default: true. Set to false if the user wants a more refined search.'
required: false
description: 'Include chats marked as Muted by the user, which are usually less important. Default: true. Set to false if the user wants a more refined search.'
name: includeMuted
in: query
responses:
'200':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
content:
application/json:
schema:
$ref: '#/components/schemas/SearchChatsOutput'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/chats:
get:
summary: List chats
description: List all chats sorted by last activity (most recent first). Combines all accounts into a single paginated list.
tags:
- Chats
operationId: listChats
security:
- bearerAuth: []
parameters:
- schema:
type: string
description: Opaque pagination cursor; do not inspect. Use together with 'direction'.
example: 1725489123456|c29tZUltc2dQYWdl
x-stainless-pagination-property:
purpose: next_cursor_param
required: false
description: Opaque pagination cursor; do not inspect. Use together with 'direction'.
name: cursor
in: query
- schema:
type: string
enum:
- after
- before
description: 'Pagination direction used with ''cursor'': ''before'' fetches older results, ''after'' fetches newer results. Defaults to ''before'' when only ''cursor'' is provided.'
example: before
required: false
description: 'Pagination direction used with ''cursor'': ''before'' fetches older results, ''after'' fetches newer results. Defaults to ''before'' when only ''cursor'' is provided.'
name: direction
in: query
- schema:
type: array
items:
type: string
description: Account ID this resource belongs to.
description: Limit to specific account IDs. If omitted, fetches from all accounts.
example:
- matrix
- discordgo
- local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc
required: false
description: Limit to specific account IDs. If omitted, fetches from all accounts.
name: accountIDs
in: query
responses:
'200':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
content:
application/json:
schema:
$ref: '#/components/schemas/ListChatsOutput'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: Create a chat
description: Create a direct or group chat from participant IDs. Returns the created chat.
tags:
- Chats
operationId: createChat
security:
- bearerAuth: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateChatInput'
responses:
'200':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
content:
application/json:
schema:
$ref: '#/components/schemas/CreateChatOutput'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/chats/start:
post:
summary: Start a direct chat
description: Resolve a user/contact and open a direct chat. Reuses and returns an existing direct chat when one is found. Available in Beeper Desktop v4.2.808+.
tags:
- Chats
operationId: startChat
security:
- bearerAuth: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/StartChatInput'
responses:
'200':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
content:
application/json:
schema:
$ref: '#/components/schemas/CreateChatOutput'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/chats/{chatID}:
get:
summary: Retrieve chat details
description: Retrieve chat details including metadata, participants, and latest message
tags:
- Chats
operationId: getChat
security:
- bearerAuth: []
parameters:
- schema:
type: string
description: Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.
example: '!NCdzlIaMjZUmvmvyHU:beeper.com'
required: true
description: Chat ID or local chat ID.
name: chatID
in: path
- schema:
type: integer
nullable: true
minimum: -1
maximum: 500
default: 100
description: Maximum number of participants to return. Use -1 for all; otherwise 0-500. Defaults to 100. List and search endpoints return up to 20 participants per chat.
example: 100
required: false
description: Maximum number of participants to return. Use -1 for all; otherwise 0-500. Defaults to 100. List and search endpoints return up to 20 participants per chat.
name: maxParticipantCount
in: query
responses:
'200':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
content:
application/json:
schema:
$ref: '#/components/schemas/Chat'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
patch:
summary: Update chat
description: Update supported chat fields. Non-empty draft objects are accepted only when the current draft is empty. Send draft=null to clear the draft before setting new draft text or attachments.
tags:
- Chats
operationId: patchChat
security:
- bearerAuth: []
parameters:
- schema:
type: string
description: Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.
example: '!NCdzlIaMjZUmvmvyHU:beeper.com'
required: true
description: Chat ID or local chat ID.
name: chatID
in: path
requestBody:
content:
application/json:
schema:
type: object
properties:
draft:
$ref: '#/components/schemas/ChatDraftInput'
title:
type: string
nullable: true
description: Custom chat title. Support depends on the chat account and chat permissions.
description:
type: string
nullable: true
description: Group chat description/topic. Support depends on the chat account and chat permissions.
imgURL:
type: string
nullable: true
description: Local filesystem path to a group chat avatar image. Support depends on the chat account and chat permissions.
isArchived:
type: boolean
description: Archive or unarchive the chat.
isLowPriority:
type: boolean
description: Mark or unmark the chat as low priority when supported by the account.
isPinned:
type: boolean
description: Pin or unpin the chat when supported by the account.
isMuted:
type: boolean
description: Mute or unmute the chat.
messageExpirySeconds:
type: integer
nullable: true
minimum: 0
description: Disappearing-message timer in seconds, or null to clear when supported.
responses:
'200':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
content:
application/json:
schema:
$ref: '#/components/schemas/Chat'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/chats/{chatID}/archive:
post:
summary: Archive or unarchive a chat
description: Archive or unarchive a chat. Set archived=true to move to archive, archived=false to move back to inbox
tags:
- Chats
operationId: archiveChat
security:
- bearerAuth: []
parameters:
- schema:
type: string
description: Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.
example: '!NCdzlIaMjZUmvmvyHU:beeper.com'
required: true
description: Chat ID or local chat ID.
name: chatID
in: path
requestBody:
content:
application/json:
schema:
type: object
properties:
archived:
type: boolean
default: true
description: True to archive, false to unarchive
responses:
'204':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/chats/{chatID}/reminders:
post:
summary: Create a chat reminder
description: Set a reminder for a chat at a specific time
tags:
- Chats
operationId: setChatReminder
security:
- bearerAuth: []
parameters:
- schema:
type: string
description: Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.
example: '!NCdzlIaMjZUmvmvyHU:beeper.com'
required: true
description: Chat ID or local chat ID.
name: chatID
in: path
requestBody:
content:
application/json:
schema:
type: object
properties:
reminder:
type: object
properties:
remindAt:
type: string
format: date-time
description: Timestamp when the reminder should trigger.
example: '2025-08-31T23:30:12.520Z'
dismissOnIncomingMessage:
type: boolean
description: Cancel reminder if someone messages in the chat
required:
- remindAt
description: Reminder configuration
required:
- reminder
responses:
'204':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
summary: Delete a chat reminder
description: Clear an existing reminder from a chat
tags:
- Chats
operationId: clearChatReminder
security:
- bearerAuth: []
parameters:
- schema:
type: string
description: Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.
example: '!NCdzlIaMjZUmvmvyHU:beeper.com'
required: true
description: Chat ID or local chat ID.
name: chatID
in: path
responses:
'204':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/chats/{chatID}/read:
post:
summary: Mark a chat as read
description: Mark a chat as read, optionally through a specific message ID.
tags:
- Chats
operationId: markChatRead
security:
- bearerAuth: []
parameters:
- schema:
type: string
description: Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.
example: '!NCdzlIaMjZUmvmvyHU:beeper.com'
required: true
description: Chat ID or local chat ID.
name: chatID
in: path
requestBody:
content:
application/json:
schema:
type: object
properties:
messageID:
type: string
description: Optional message ID to mark read through.
example: '1343993'
responses:
'200':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
content:
application/json:
schema:
$ref: '#/components/schemas/Chat'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/chats/{chatID}/unread:
post:
summary: Mark a chat as unread
description: Mark a chat as unread, optionally from a specific message ID.
tags:
- Chats
operationId: markChatUnread
security:
- bearerAuth: []
parameters:
- schema:
type: string
description: Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.
example: '!NCdzlIaMjZUmvmvyHU:beeper.com'
required: true
description: Chat ID or local chat ID.
name: chatID
in: path
requestBody:
content:
application/json:
schema:
type: object
properties:
messageID:
type: string
description: Optional message ID to mark unread from.
example: '1343993'
responses:
'200':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
content:
application/json:
schema:
$ref: '#/components/schemas/Chat'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/v1/chats/{chatID}/notify-anyway:
post:
summary: Notify anyway
description: Force a delivery notification when supported by the underlying network. Currently intended for iMessage on macOS; unsupported networks return an error.
tags:
- Chats
operationId: notifyAnyway
security:
- bearerAuth: []
parameters:
- schema:
type: string
description: Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.
example: '!NCdzlIaMjZUmvmvyHU:beeper.com'
required: true
description: Chat ID or local chat ID.
name: chatID
in: path
requestBody:
content:
application/json:
schema:
type: object
properties: {}
responses:
'200':
description: Request executed successfully
headers:
X-Beeper-Desktop-Version:
$ref: '#/components/headers/X-Beeper-Desktop-Version'
content:
application/json:
schema:
$ref: '#/components/schemas/Chat'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
components:
schemas:
DraftAttachmentInput:
allOf:
- $ref: '#/components/schemas/MessageAttachmentInput'
- type: object
properties:
id:
type: string
description: Optional draft attachment identifier. If omitted, a new identifier is generated.
Message:
type: object
properties:
id:
type: string
description: Message ID.
example: '1343993'
chatID:
type: string
description: Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.
example: '!NCdzlIaMjZUmvmvyHU:beeper.com'
accountID:
type: string
description: Beeper account ID the message belongs to.
senderID:
type: string
description: Matrix-style fully-qualified sender user ID, usually including a bridge prefix and homeserver.
example: '@kishanbagaria:local-whatsapp.localhost'
senderName:
type: string
description: Resolved sender display name (impersonator/full name/username/participant name).
timestamp:
type: string
format: date-time
description: Message timestamp.
example: '2025-08-31T23:30:12.520Z'
sortKey:
type: string
description: A unique, sortable key used to sort messages.
example: '821744079'
type:
type: string
enum:
- TEXT
- NOTICE
- IMAGE
- VIDEO
- VOICE
- AUDIO
- FILE
- STICKER
- LOCATION
- REACTION
description: Message content type. Useful for distinguishing reactions, media messages, and state events from regular text messages.
text:
type: string
description: Matrix HTML body if present.
editedTimestamp:
type: string
format: date-time
description: Timestamp when the message was edited, if known.
example: '2025-08-31T23:30:12.520Z'
isSender:
type: boolean
description: True if the authenticated user sent the message.
sendStatus:
$ref: '#/components/schemas/SendStatus'
isHidden:
type: boolean
description: True if the message is hidden from normal display.
isDeleted:
type: boolean
description: True if the message has been deleted.
attachments:
type: array
items:
$ref: '#/components/schemas/Attachment'
description: Attachments included with this message, if any.
isUnread:
type: boolean
description: True if the message is unread for the authenticated user. May be omitted.
linkedMessageID:
type: string
description: ID of the message this is a reply to, if any.
example: '1343993'
mentions:
type: array
nullable: true
items:
type: string
description: Mentioned user IDs,
# --- truncated at 32 KB (72 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/beeper/refs/heads/main/openapi/beeper-chats-api-openapi.yml