openapi: 3.1.0 info: title: Beeper Desktop Accounts Files 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: Files description: File upload, download, and streaming helpers for message attachments and drafts. paths: /v1/assets/download: post: summary: Download a file description: Download a Matrix file using its mxc:// or localmxc:// URL to the device running Beeper Desktop and return the local file URL. tags: - Files operationId: downloadAsset security: - bearerAuth: [] requestBody: content: application/json: schema: $ref: '#/components/schemas/DownloadAssetInput' 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/DownloadAssetOutput' '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/assets/serve: get: summary: Serve a file description: Stream a file given an mxc://, localmxc://, or file:// URL. Downloads first if not cached. Supports Range requests for seeking in large files. tags: - Files operationId: serveAsset security: - bearerAuth: [] parameters: - schema: type: string minLength: 1 description: File URL to serve. Accepts mxc://, localmxc://, or file:// URLs. required: true description: File URL to serve. Accepts mxc://, localmxc://, or file:// URLs. name: url in: query responses: '200': description: File stream headers: X-Beeper-Desktop-Version: $ref: '#/components/headers/X-Beeper-Desktop-Version' content: application/octet-stream: schema: type: string format: binary '206': description: Partial file stream headers: X-Beeper-Desktop-Version: $ref: '#/components/headers/X-Beeper-Desktop-Version' content: application/octet-stream: schema: type: string format: binary '304': description: File not modified 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' '416': description: Requested range not satisfiable headers: X-Beeper-Desktop-Version: $ref: '#/components/headers/X-Beeper-Desktop-Version' '422': $ref: '#/components/responses/UnprocessableEntity' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalServerError' /v1/assets/upload: post: summary: Upload a file description: Upload a file to a temporary location using multipart/form-data. Returns an uploadID that can be referenced when sending a message or materializing a draft attachment. tags: - Files operationId: uploadAsset security: - bearerAuth: [] requestBody: content: multipart/form-data: schema: $ref: '#/components/schemas/UploadAssetMultipart' 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/UploadAssetOutput' '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/assets/upload/base64: post: summary: Upload a file (base64) description: Upload a file using a JSON body with base64-encoded content. Returns an uploadID that can be referenced when sending a message or materializing a draft attachment. Alternative to the multipart upload endpoint. tags: - Files operationId: uploadAssetBase64 security: - bearerAuth: [] requestBody: content: application/json: schema: $ref: '#/components/schemas/UploadAssetInput' 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/UploadAssetOutput' '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: responses: UnauthorizedError: description: Access token is missing or invalid headers: X-Beeper-Desktop-Version: $ref: '#/components/headers/X-Beeper-Desktop-Version' content: application/json: schema: $ref: '#/components/schemas/Error' NotFound: description: Resource not found headers: X-Beeper-Desktop-Version: $ref: '#/components/headers/X-Beeper-Desktop-Version' content: application/json: schema: $ref: '#/components/schemas/Error' TooManyRequests: description: Too many requests - rate limit exceeded headers: X-Beeper-Desktop-Version: $ref: '#/components/headers/X-Beeper-Desktop-Version' content: application/json: schema: $ref: '#/components/schemas/Error' UnprocessableEntity: description: Unprocessable entity - validation error headers: X-Beeper-Desktop-Version: $ref: '#/components/headers/X-Beeper-Desktop-Version' content: application/json: schema: $ref: '#/components/schemas/Error' InternalServerError: description: Internal server error headers: X-Beeper-Desktop-Version: $ref: '#/components/headers/X-Beeper-Desktop-Version' content: application/json: schema: $ref: '#/components/schemas/Error' BadRequest: description: Invalid request parameters headers: X-Beeper-Desktop-Version: $ref: '#/components/headers/X-Beeper-Desktop-Version' content: application/json: schema: $ref: '#/components/schemas/Error' ForbiddenError: description: Access token does not have the required scope headers: X-Beeper-Desktop-Version: $ref: '#/components/headers/X-Beeper-Desktop-Version' content: application/json: schema: $ref: '#/components/schemas/Error' schemas: DownloadAssetInput: type: object properties: url: type: string minLength: 1 description: Matrix content URL (mxc:// or localmxc://) for the file to download. required: - url example: url: mxc://example.org/Q4x9CqGz1pB3Oa6XgJ DownloadAssetOutput: type: object properties: srcURL: type: string description: Local file URL to the downloaded file. error: type: string description: Error message if the download failed. UploadAssetInput: type: object properties: content: type: string minLength: 1 maxLength: 750000000 description: Base64-encoded file content (max ~500MB decoded) fileName: type: string description: Original filename. Generated if omitted mimeType: type: string description: MIME type. Auto-detected from magic bytes if omitted required: - content description: Upload a temporary file. Upload IDs can be referenced by send-message and draft attachment requests while the temporary upload remains available. UploadAssetOutput: type: object properties: uploadID: type: string description: Unique upload ID for this temporary file srcURL: type: string description: Local file URL (file://) for the uploaded file fileName: type: string description: Resolved filename mimeType: type: string description: Detected or provided MIME type fileSize: type: number description: File size in bytes width: type: number description: Width in pixels (images/videos) height: type: number description: Height in pixels (images/videos) duration: type: number description: Duration in seconds (audio/videos) error: type: string description: Error message if upload failed UploadAssetMultipart: type: object properties: file: type: string description: The file to upload (max 500 MB). format: binary fileName: type: string description: Original filename. Defaults to the uploaded file name if omitted mimeType: type: string description: MIME type. Auto-detected from magic bytes if omitted required: - file description: Upload a temporary file. Upload IDs can be referenced by send-message and draft attachment requests while the temporary upload remains available. Error: type: object properties: message: type: string description: Error message code: type: string description: Machine-readable error code details: anyOf: - type: object properties: issues: type: array items: type: object properties: code: type: string description: Validation issue code example: invalid_type message: type: string description: Human-readable description of the validation issue path: type: array items: anyOf: - type: string x-stainless-variantName: field - type: number x-stainless-variantName: index description: Path pointing to the invalid field within the payload example: - body - chatID required: - code - message - path description: List of validation issues required: - issues description: Validation error details x-stainless-variantName: validation_details - type: object additionalProperties: nullable: true x-stainless-any: true description: Additional error context x-stainless-variantName: context - nullable: true description: Arbitrary details payload supplied by the server x-stainless-any: true x-stainless-variantName: arbitrary - nullable: true description: Additional error details for debugging required: - message - code headers: X-Beeper-Desktop-Version: description: Beeper Desktop application version providing this response. schema: type: string example: 4.0.0 securitySchemes: bearerAuth: type: http scheme: bearer description: Bearer token authentication. Access token obtained via OAuth2 PKCE flow or created in-app. Required for all API operations. oauth2: type: oauth2 description: OAuth2 Authorization Code flow with PKCE for obtaining bearer access tokens. Used by MCP servers to authenticate clients. flows: authorizationCode: authorizationUrl: http://localhost:23373/oauth/authorize tokenUrl: http://localhost:23373/oauth/token scopes: read: Read access to messages, chats, and accounts write: Write access to send messages, edit messages, react to messages, archive chats, and set reminders externalDocs: description: Beeper Desktop API Documentation url: https://developers.beeper.com/desktop-api